crewswarm 0.9.2 → 0.9.4
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.
- package/README.md +22 -9
- package/apps/dashboard/dist/assets/chat-core-uXb_C0GM.js +1 -0
- package/apps/dashboard/dist/assets/chat-core-uXb_C0GM.js.br +0 -0
- package/apps/dashboard/dist/assets/cli-process-CNZ_UBCt.js +1 -0
- package/apps/dashboard/dist/assets/cli-process-CNZ_UBCt.js.br +0 -0
- package/apps/dashboard/dist/assets/index-BeVllEj_.js +2 -0
- package/apps/dashboard/dist/assets/index-BeVllEj_.js.br +0 -0
- package/apps/dashboard/dist/assets/{index-CF0aJRtC.css → index-D-sRshvg.css} +1 -1
- package/apps/dashboard/dist/assets/index-D-sRshvg.css.br +0 -0
- package/apps/dashboard/dist/assets/tab-benchmarks-tab-BHjKCPm3.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-models-tab-dNRgsTOO.js +1 -0
- package/apps/dashboard/dist/assets/tab-models-tab-dNRgsTOO.js.br +0 -0
- package/apps/dashboard/dist/assets/{tab-pm-loop-tab-Bfd449B4.js → tab-pm-loop-tab-DiAPTJXu.js} +1 -1
- package/apps/dashboard/dist/assets/tab-pm-loop-tab-DiAPTJXu.js.br +0 -0
- package/apps/dashboard/dist/assets/{tab-projects-tab-DhNWnlzt.js → tab-projects-tab-SFH4E--a.js} +1 -1
- package/apps/dashboard/dist/assets/tab-projects-tab-SFH4E--a.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-settings-tab-CuvH_Fj_.js +1 -0
- package/apps/dashboard/dist/assets/tab-settings-tab-CuvH_Fj_.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-skills-tab-DR7PJ7NB.js +1 -0
- package/apps/dashboard/dist/assets/tab-skills-tab-DR7PJ7NB.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-testing-tab-CezZOZcJ.js +1 -0
- package/apps/dashboard/dist/assets/tab-testing-tab-CezZOZcJ.js.br +0 -0
- package/apps/dashboard/dist/index.html +135 -15
- package/apps/dashboard/dist/index.html.br +0 -0
- package/apps/dashboard/dist/index.html.gz +0 -0
- package/apps/vibe/README.md +2 -2
- package/apps/vibe/package.json +1 -1
- package/apps/vibe/server.mjs +101 -56
- package/crew-lead.mjs +34 -4
- package/lib/bridges/cli-executor.mjs +1 -1
- package/lib/bridges/gateway-ws.mjs +4 -0
- package/lib/browser/passthrough-stderr.js +1 -0
- package/lib/chat/project-messages.mjs +3 -5
- package/lib/cli-process-tracker.mjs +3 -2
- package/lib/contacts/identity-linker.mjs +1 -0
- package/lib/crew-judge/judge.mjs +19 -18
- package/lib/crew-lead/agent-manager.mjs +1 -1
- package/lib/crew-lead/background.mjs +14 -1
- package/lib/crew-lead/chat-handler.mjs +38 -1
- package/lib/crew-lead/http-server.mjs +106 -57
- package/lib/crew-lead/llm-caller.mjs +24 -8
- package/lib/crew-lead/prompts.mjs +14 -1
- package/lib/crew-lead/tools.mjs +3 -2
- package/lib/crew-lead/wave-dispatcher.mjs +19 -5
- package/lib/crew-lead/ws-router.mjs +219 -27
- package/lib/engines/crew-cli.mjs +1 -1
- package/lib/engines/engine-registry.mjs +14 -3
- package/lib/engines/rt-envelope.mjs +1 -0
- package/lib/engines/runners.mjs +28 -4
- package/lib/gemini-cli-passthrough-noise.mjs +1 -1
- package/lib/integrations/code-search.mjs +4 -3
- package/lib/memory/shared-adapter.mjs +23 -10
- package/lib/pipeline/manager.mjs +2 -1
- package/lib/runtime/config.mjs +1 -1
- package/lib/runtime/paths.mjs +12 -8
- package/lib/runtime/spending.mjs +2 -1
- package/package.json +42 -14
- package/scripts/capture-build-flow.mjs +118 -0
- package/scripts/coverage-report.mjs +209 -0
- package/scripts/coverage-summary.mjs +47 -0
- package/scripts/dashboard-validation.mjs +76 -0
- package/scripts/dashboard.mjs +1667 -551
- package/scripts/generate-openapi.mjs +683 -277
- package/scripts/live-bridge-matrix.mjs +79 -0
- package/scripts/live-cli-matrix.mjs +166 -0
- package/scripts/live-crewchat-check.mjs +42 -0
- package/scripts/live-engine-matrix.mjs +50 -0
- package/scripts/live-provider-failover-matrix.mjs +107 -0
- package/scripts/live-provider-matrix.mjs +228 -0
- package/scripts/restart-all-from-repo.sh +4 -4
- package/scripts/restart-service.sh +12 -9
- package/scripts/smoke-dispatch.mjs +4 -1
- package/scripts/test-blast-radius.mjs +204 -0
- package/scripts/test-report-summary.mjs +88 -0
- package/scripts/test-reporter.mjs +651 -0
- package/scripts/test-rerun.mjs +136 -0
- package/scripts/tmux-bridge +130 -0
- package/apps/dashboard/dist/assets/chat-core-Cx4sTxDd.js +0 -1
- package/apps/dashboard/dist/assets/chat-core-Cx4sTxDd.js.br +0 -0
- package/apps/dashboard/dist/assets/cli-process-COMRNPqr.js +0 -1
- package/apps/dashboard/dist/assets/cli-process-COMRNPqr.js.br +0 -0
- package/apps/dashboard/dist/assets/index-CF0aJRtC.css.br +0 -0
- package/apps/dashboard/dist/assets/index-DnClJ1ee.js +0 -2
- package/apps/dashboard/dist/assets/index-DnClJ1ee.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-models-tab-BLEjmd19.js +0 -1
- package/apps/dashboard/dist/assets/tab-models-tab-BLEjmd19.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-pm-loop-tab-Bfd449B4.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-projects-tab-DhNWnlzt.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-settings-tab-Bn4nXtDe.js +0 -1
- package/apps/dashboard/dist/assets/tab-settings-tab-Bn4nXtDe.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-skills-tab-BpY0uZHW.js +0 -1
- package/apps/dashboard/dist/assets/tab-skills-tab-BpY0uZHW.js.br +0 -0
- package/apps/dashboard/index.html +0 -6529
- package/apps/dashboard/package.json +0 -15
- package/apps/dashboard/src/app.js +0 -2828
- package/apps/dashboard/src/app.js.br +0 -0
- package/apps/dashboard/src/app.js.gz +0 -0
- package/apps/dashboard/src/chat/chat-actions.js +0 -1847
- package/apps/dashboard/src/chat/chat-actions.js.br +0 -0
- package/apps/dashboard/src/chat/unified-messages.js +0 -327
- package/apps/dashboard/src/chat/unified-messages.js.br +0 -0
- package/apps/dashboard/src/cli-process.js +0 -208
- package/apps/dashboard/src/cli-process.js.br +0 -0
- package/apps/dashboard/src/cli-process.js.gz +0 -0
- package/apps/dashboard/src/components/active-tasks-panel.js +0 -175
- package/apps/dashboard/src/components/active-tasks-panel.js.br +0 -0
- package/apps/dashboard/src/core/api.js +0 -18
- package/apps/dashboard/src/core/api.js.br +0 -0
- package/apps/dashboard/src/core/dom.js +0 -228
- package/apps/dashboard/src/core/dom.js.br +0 -0
- package/apps/dashboard/src/core/state.js +0 -91
- package/apps/dashboard/src/core/state.js.br +0 -0
- package/apps/dashboard/src/core/task-manager.js +0 -134
- package/apps/dashboard/src/core/task-manager.js.br +0 -0
- package/apps/dashboard/src/orchestration-status.js +0 -127
- package/apps/dashboard/src/orchestration-status.js.br +0 -0
- package/apps/dashboard/src/setup-wizard.js +0 -562
- package/apps/dashboard/src/setup-wizard.js.br +0 -0
- package/apps/dashboard/src/styles.css +0 -2085
- package/apps/dashboard/src/styles.css.br +0 -0
- package/apps/dashboard/src/styles.css.gz +0 -0
- package/apps/dashboard/src/tabs/agents-tab.js +0 -2237
- package/apps/dashboard/src/tabs/agents-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/benchmarks-tab.js +0 -229
- package/apps/dashboard/src/tabs/benchmarks-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/comms-tab.js +0 -955
- package/apps/dashboard/src/tabs/comms-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/contacts-tab.js +0 -654
- package/apps/dashboard/src/tabs/contacts-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/engines-tab.js +0 -175
- package/apps/dashboard/src/tabs/engines-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/memory-tab.js +0 -182
- package/apps/dashboard/src/tabs/memory-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/models-tab.js +0 -450
- package/apps/dashboard/src/tabs/models-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/pm-loop-tab.js +0 -185
- package/apps/dashboard/src/tabs/pm-loop-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/projects-tab.js +0 -663
- package/apps/dashboard/src/tabs/projects-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/projects-tab.js.gz +0 -0
- package/apps/dashboard/src/tabs/prompts-tab.js +0 -160
- package/apps/dashboard/src/tabs/prompts-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/services-tab.js +0 -202
- package/apps/dashboard/src/tabs/services-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/settings-tab.js +0 -861
- package/apps/dashboard/src/tabs/settings-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/skills-tab.js +0 -284
- package/apps/dashboard/src/tabs/skills-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/spending-tab.js +0 -173
- package/apps/dashboard/src/tabs/spending-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/swarm-chat-tab.js +0 -660
- package/apps/dashboard/src/tabs/swarm-chat-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/swarm-tab.js +0 -538
- package/apps/dashboard/src/tabs/swarm-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/usage-tab.js +0 -390
- package/apps/dashboard/src/tabs/usage-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/waves-tab.js +0 -238
- package/apps/dashboard/src/tabs/waves-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/workflows-tab.js +0 -747
- package/apps/dashboard/src/tabs/workflows-tab.js.br +0 -0
- package/apps/vibe/.crew/agent-memory/pipeline.json +0 -304
- package/apps/vibe/.crew/cost.json +0 -17
- package/apps/vibe/.crew/json-parse-metrics.jsonl +0 -27
- package/apps/vibe/.crew/pipeline-metrics.jsonl +0 -27
- package/apps/vibe/.crew/pipeline-runs/pipeline-0f90c392-2425-4ae5-850c-bd9d17b1d690.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-1c269dd9-a63f-4fba-af81-5cf08048ef06.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-288a7765-da24-4a22-89bc-1f3cc9b0562c.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-2c78fd22-a657-4bd1-bc49-0679fb384409.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-3da23550-22ed-4904-9a0a-8e79c1f3024c.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-3e6fe08d-3264-404a-8df3-aab7efef10e7.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-42eec610-57fe-4e09-9e7e-b315038495c2.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-4438eb4c-ae13-42b1-90e2-b043d8983be8.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-4740a9f5-86e7-44b6-a394-de433e291727.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-49e1da6a-957e-48fd-9220-415019e4f8e2.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-4c9251db-be68-427b-a3fc-a264f2b5778d.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-6413fa33-a802-4b57-a8c0-a9056ad67842.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-65e29a57-664d-4196-8109-017e364f182e.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-6aa04bc5-9593-4b1f-b58d-3bf2978cb602.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-6e1cba53-9b70-457e-99e0-59199149dd21.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-749f41cc-4dac-4204-be64-873a6080a0d2.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-74d68121-e181-4864-bd9a-c3211341dfaf.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-8509bc24-142d-4e07-b44a-a50bf99d1103.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-960339c6-07ca-43ce-9900-f6e1702b39b9.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-9bef2dd2-6122-42e5-b3d9-19f4d80f9e40.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-9c6480a9-7031-4146-b241-825b9a2d1de1.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-9fd42426-8492-4157-9d5f-e1537c060489.jsonl +0 -2
- package/apps/vibe/.crew/pipeline-runs/pipeline-ad6d40a3-2f5e-46a9-a345-47caaccc51aa.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-bc606133-8d5b-4535-8d85-f1a29cdaa981.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-c1418f4e-b773-4ca1-84a3-216acf36e2f2.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-c1a13ccd-634a-4d01-a4a7-1177b8a752ff.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-c7d27b42-249e-4bd4-8f26-6aa998110b8a.jsonl +0 -5
- package/apps/vibe/.crew/pipeline-runs/pipeline-cca2e9b9-4a34-4d25-a311-5c793fa7e91e.jsonl +0 -5
- package/apps/vibe/.crew/sandbox.json +0 -7
- package/apps/vibe/.crew/session.json +0 -330
- package/apps/vibe/.crew/training-data.jsonl +0 -0
- package/apps/vibe/.github/workflows/studio-quality.yml +0 -37
- package/apps/vibe/.studio-data/project-messages/chuck-norris.jsonl +0 -18
- package/apps/vibe/.studio-data/project-messages/general.jsonl +0 -81
- package/apps/vibe/.studio-data/project-messages/studio-local.jsonl +0 -18
- package/apps/vibe/ARCHITECTURE.md +0 -3393
- package/apps/vibe/QUICK-REFERENCE.md +0 -211
- package/apps/vibe/ROADMAP.md +0 -41
- package/apps/vibe/STUDIO-SETUP-COMPLETE.md +0 -35
- package/apps/vibe/VISUAL-GUIDE.md +0 -378
- package/apps/vibe/capture-demo.mjs +0 -160
- package/apps/vibe/capture-full-demo.mjs +0 -255
- package/apps/vibe/capture-quickstart.mjs +0 -256
- package/apps/vibe/capture-vibe-assets.mjs +0 -71
- package/apps/vibe/capture-vibe-video.mjs +0 -260
- package/apps/vibe/check-buttons.js +0 -41
- package/apps/vibe/diagnose.html +0 -106
- package/apps/vibe/fix-buttons.js +0 -103
- package/apps/vibe/index.html +0 -3404
- package/apps/vibe/package-lock.json +0 -920
- package/apps/vibe/scripts/studio-pty-host.py +0 -117
- package/apps/vibe/src/main.js +0 -2940
- package/apps/vibe/src/register-all-languages.js +0 -98
- package/apps/vibe/start-studio.sh +0 -11
- package/apps/vibe/test/accessibility-tests.js +0 -77
- package/apps/vibe/test/browser-performance-audit.mjs +0 -205
- package/apps/vibe/test/performance-tests.js +0 -120
- package/apps/vibe/test/security-tests.js +0 -213
- package/apps/vibe/tests/e2e.local.mjs +0 -54
- package/apps/vibe/tests/server.smoke.mjs +0 -106
- package/apps/vibe/update_website.mjs +0 -74
- package/apps/vibe/vite.config.js +0 -19
- package/lib/crew-lead/chat-handler.mjs.bak +0 -1274
- package/lib/engines/rt-envelope.mjs.backup-current +0 -870
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
<title>crewswarm dashboard</title>
|
|
7
7
|
<link rel="icon" type="image/png" href="/favicon.png" />
|
|
8
8
|
<!-- Font: system stack only to avoid CORS when dashboard (4319) and studio (3333) both load Inter from Google -->
|
|
9
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-BeVllEj_.js"></script>
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/core-utils-CmOkXgzi.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/setup-wizard-CA0Or47w.js">
|
|
12
12
|
<link rel="modulepreload" crossorigin href="/assets/components-BS9fQjE_.js">
|
|
13
13
|
<link rel="modulepreload" crossorigin href="/assets/orchestration-Ca2DLWN-.js">
|
|
14
|
-
<link rel="modulepreload" crossorigin href="/assets/cli-process-
|
|
15
|
-
<link rel="modulepreload" crossorigin href="/assets/chat-core-
|
|
14
|
+
<link rel="modulepreload" crossorigin href="/assets/cli-process-CNZ_UBCt.js">
|
|
15
|
+
<link rel="modulepreload" crossorigin href="/assets/chat-core-uXb_C0GM.js">
|
|
16
16
|
<link rel="modulepreload" crossorigin href="/assets/tab-swarm-chat-tab-BNrd88-r.js">
|
|
17
17
|
<link rel="modulepreload" crossorigin href="/assets/tab-waves-tab-SaJDkb4x.js">
|
|
18
18
|
<link rel="modulepreload" crossorigin href="/assets/tab-workflows-tab-B-soSy1k.js">
|
|
@@ -20,18 +20,19 @@
|
|
|
20
20
|
<link rel="modulepreload" crossorigin href="/assets/tab-services-tab-DU_LH3uG.js">
|
|
21
21
|
<link rel="modulepreload" crossorigin href="/assets/tab-agents-tab-BgpIsjkw.js">
|
|
22
22
|
<link rel="modulepreload" crossorigin href="/assets/tab-prompts-tab-DVkUNaJd.js">
|
|
23
|
-
<link rel="modulepreload" crossorigin href="/assets/tab-
|
|
23
|
+
<link rel="modulepreload" crossorigin href="/assets/tab-testing-tab-CezZOZcJ.js">
|
|
24
|
+
<link rel="modulepreload" crossorigin href="/assets/tab-skills-tab-DR7PJ7NB.js">
|
|
24
25
|
<link rel="modulepreload" crossorigin href="/assets/tab-contacts-tab-DiOyMYth.js">
|
|
25
26
|
<link rel="modulepreload" crossorigin href="/assets/tab-engines-tab-BsdZVvU0.js">
|
|
26
27
|
<link rel="modulepreload" crossorigin href="/assets/tab-swarm-tab-B1AcjL1W.js">
|
|
27
|
-
<link rel="modulepreload" crossorigin href="/assets/tab-models-tab-
|
|
28
|
-
<link rel="modulepreload" crossorigin href="/assets/tab-projects-tab-
|
|
29
|
-
<link rel="modulepreload" crossorigin href="/assets/tab-settings-tab-
|
|
28
|
+
<link rel="modulepreload" crossorigin href="/assets/tab-models-tab-dNRgsTOO.js">
|
|
29
|
+
<link rel="modulepreload" crossorigin href="/assets/tab-projects-tab-SFH4E--a.js">
|
|
30
|
+
<link rel="modulepreload" crossorigin href="/assets/tab-settings-tab-CuvH_Fj_.js">
|
|
30
31
|
<link rel="modulepreload" crossorigin href="/assets/tab-comms-tab-kguqTIzD.js">
|
|
31
32
|
<link rel="modulepreload" crossorigin href="/assets/tab-usage-tab-BIOOnB-Y.js">
|
|
32
33
|
<link rel="modulepreload" crossorigin href="/assets/tab-spending-tab-DEccQHnt.js">
|
|
33
|
-
<link rel="modulepreload" crossorigin href="/assets/tab-pm-loop-tab-
|
|
34
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
34
|
+
<link rel="modulepreload" crossorigin href="/assets/tab-pm-loop-tab-DiAPTJXu.js">
|
|
35
|
+
<link rel="stylesheet" crossorigin href="/assets/index-D-sRshvg.css">
|
|
35
36
|
</head>
|
|
36
37
|
<body>
|
|
37
38
|
<!-- Skip link for keyboard navigation -->
|
|
@@ -112,6 +113,10 @@
|
|
|
112
113
|
<button class="nav-item" id="navRunSkills" data-view="run-skills">
|
|
113
114
|
<span class="nav-icon">⚡</span> Run skills
|
|
114
115
|
</button>
|
|
116
|
+
<button class="nav-item" id="navTesting" data-view="testing">
|
|
117
|
+
<span class="nav-icon">🧪</span> Testing
|
|
118
|
+
<span class="nav-badge hidden" id="testingBadge">0</span>
|
|
119
|
+
</button>
|
|
115
120
|
<button class="nav-item" id="navBenchmarks" data-view="benchmarks">
|
|
116
121
|
<span class="nav-icon">📊</span> Benchmarks
|
|
117
122
|
</button>
|
|
@@ -1177,6 +1182,8 @@
|
|
|
1177
1182
|
<option value="deepseek-chat">DeepSeek Chat</option>
|
|
1178
1183
|
<option value="llama-3.3-70b-versatile">Llama 3.3 70B (Groq)</option>
|
|
1179
1184
|
<option value="gpt-4o">GPT-4o</option>
|
|
1185
|
+
<option value="claude-haiku-4-5-20251001">Claude Haiku 4.5 (OAuth)</option>
|
|
1186
|
+
<option value="claude-sonnet-4-6">Claude Sonnet 4.6 (OAuth)</option>
|
|
1180
1187
|
<option value="moonshot-v1-128k">Moonshot V1 128K</option>
|
|
1181
1188
|
<option value="grok-4.20-beta-0309-non-reasoning">Grok 4.2 Beta (non-reasoning)</option>
|
|
1182
1189
|
<option value="grok-4.20-beta-0309-reasoning">Grok 4.2 Beta (reasoning)</option>
|
|
@@ -2405,6 +2412,22 @@
|
|
|
2405
2412
|
</div>
|
|
2406
2413
|
</div>
|
|
2407
2414
|
|
|
2415
|
+
<!-- OAuth / Subscription Providers (no API key needed) -->
|
|
2416
|
+
<div
|
|
2417
|
+
style="
|
|
2418
|
+
font-size: 11px;
|
|
2419
|
+
font-weight: 600;
|
|
2420
|
+
color: var(--text-2);
|
|
2421
|
+
text-transform: uppercase;
|
|
2422
|
+
letter-spacing: 0.08em;
|
|
2423
|
+
margin: 18px 0 10px;
|
|
2424
|
+
padding: 0 2px;
|
|
2425
|
+
"
|
|
2426
|
+
>
|
|
2427
|
+
Subscription Providers (no API key)
|
|
2428
|
+
</div>
|
|
2429
|
+
<div id="oauthProvidersList"></div>
|
|
2430
|
+
|
|
2408
2431
|
<!-- Search & Research Tools -->
|
|
2409
2432
|
<div
|
|
2410
2433
|
style="
|
|
@@ -4427,6 +4450,76 @@
|
|
|
4427
4450
|
></div>
|
|
4428
4451
|
</div>
|
|
4429
4452
|
|
|
4453
|
+
<div class="card" style="margin-top: 16px">
|
|
4454
|
+
<div
|
|
4455
|
+
style="
|
|
4456
|
+
display: flex;
|
|
4457
|
+
align-items: center;
|
|
4458
|
+
justify-content: space-between;
|
|
4459
|
+
flex-wrap: wrap;
|
|
4460
|
+
gap: 12px;
|
|
4461
|
+
"
|
|
4462
|
+
>
|
|
4463
|
+
<div>
|
|
4464
|
+
<div class="card-title" style="margin-bottom: 2px">
|
|
4465
|
+
🔌 tmux-bridge Sessions
|
|
4466
|
+
</div>
|
|
4467
|
+
<div
|
|
4468
|
+
style="
|
|
4469
|
+
font-size: 11px;
|
|
4470
|
+
color: var(--text-3);
|
|
4471
|
+
line-height: 1.5;
|
|
4472
|
+
"
|
|
4473
|
+
>
|
|
4474
|
+
Enable persistent tmux sessions that survive across pipeline
|
|
4475
|
+
waves. Agents can hand off live execution context (running
|
|
4476
|
+
servers, env vars, cwd) to the next wave instead of
|
|
4477
|
+
cold-starting. Requires
|
|
4478
|
+
<code
|
|
4479
|
+
style="
|
|
4480
|
+
background: var(--bg-1);
|
|
4481
|
+
padding: 1px 4px;
|
|
4482
|
+
border-radius: 3px;
|
|
4483
|
+
"
|
|
4484
|
+
>tmux</code
|
|
4485
|
+
>
|
|
4486
|
+
+
|
|
4487
|
+
<code
|
|
4488
|
+
style="
|
|
4489
|
+
background: var(--bg-1);
|
|
4490
|
+
padding: 1px 4px;
|
|
4491
|
+
border-radius: 3px;
|
|
4492
|
+
"
|
|
4493
|
+
>smux</code
|
|
4494
|
+
>
|
|
4495
|
+
installed. One writer per session (lock enforced).
|
|
4496
|
+
</div>
|
|
4497
|
+
</div>
|
|
4498
|
+
<button
|
|
4499
|
+
id="tmuxBridgeBtn"
|
|
4500
|
+
data-action="toggleTmuxBridge"
|
|
4501
|
+
style="
|
|
4502
|
+
font-size: 12px;
|
|
4503
|
+
font-weight: 700;
|
|
4504
|
+
padding: 8px 18px;
|
|
4505
|
+
border-radius: 8px;
|
|
4506
|
+
cursor: pointer;
|
|
4507
|
+
border: 1px solid var(--border);
|
|
4508
|
+
background: var(--surface-2);
|
|
4509
|
+
color: var(--text-2);
|
|
4510
|
+
white-space: nowrap;
|
|
4511
|
+
min-width: 80px;
|
|
4512
|
+
"
|
|
4513
|
+
>
|
|
4514
|
+
Loading…
|
|
4515
|
+
</button>
|
|
4516
|
+
</div>
|
|
4517
|
+
<div
|
|
4518
|
+
id="tmuxBridgeStatus"
|
|
4519
|
+
style="margin-top: 8px; font-size: 12px; color: var(--text-3)"
|
|
4520
|
+
></div>
|
|
4521
|
+
</div>
|
|
4522
|
+
|
|
4430
4523
|
<div class="card" style="margin-top: 16px">
|
|
4431
4524
|
<div
|
|
4432
4525
|
style="
|
|
@@ -5466,6 +5559,32 @@
|
|
|
5466
5559
|
</div>
|
|
5467
5560
|
</div>
|
|
5468
5561
|
|
|
5562
|
+
<!-- Testing -->
|
|
5563
|
+
<div class="view" id="testingView">
|
|
5564
|
+
<div class="page-header">
|
|
5565
|
+
<div>
|
|
5566
|
+
<div class="page-title">Testing</div>
|
|
5567
|
+
<div class="page-sub">
|
|
5568
|
+
Test suite results, group breakdown, and run history
|
|
5569
|
+
</div>
|
|
5570
|
+
</div>
|
|
5571
|
+
<div style="display: flex; align-items: center; gap: 8px">
|
|
5572
|
+
<button
|
|
5573
|
+
data-action="refreshTesting"
|
|
5574
|
+
class="btn-ghost"
|
|
5575
|
+
style="font-size: 12px"
|
|
5576
|
+
>
|
|
5577
|
+
↻ Refresh
|
|
5578
|
+
</button>
|
|
5579
|
+
</div>
|
|
5580
|
+
</div>
|
|
5581
|
+
<div id="testProgressBar"></div>
|
|
5582
|
+
<div id="testingContent">
|
|
5583
|
+
<div class="meta" style="padding: 20px">Loading test results...</div>
|
|
5584
|
+
</div>
|
|
5585
|
+
<div id="testingHistory"></div>
|
|
5586
|
+
</div>
|
|
5587
|
+
|
|
5469
5588
|
<!-- Benchmarks — ZeroEval / llm-stats leaderboards -->
|
|
5470
5589
|
<div class="view" id="benchmarksView">
|
|
5471
5590
|
<div class="page-header">
|
|
@@ -5977,9 +6096,9 @@
|
|
|
5977
6096
|
<button
|
|
5978
6097
|
id="enhancePromptBtn"
|
|
5979
6098
|
class="btn-purple"
|
|
5980
|
-
title="
|
|
6099
|
+
title="Plan the requirement with the configured crew-pm CLI engine"
|
|
5981
6100
|
>
|
|
5982
|
-
|
|
6101
|
+
🧭 Plan
|
|
5983
6102
|
</button>
|
|
5984
6103
|
<span class="meta" id="buildStatus"></span>
|
|
5985
6104
|
</div>
|
|
@@ -5991,10 +6110,11 @@
|
|
|
5991
6110
|
<div
|
|
5992
6111
|
style="margin-top: 10px; font-size: 11px; color: var(--text-3)"
|
|
5993
6112
|
>
|
|
5994
|
-
<b
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
6113
|
+
<b>🧭 Plan</b> — turns a rough idea into a concrete build brief
|
|
6114
|
+
using the configured PM engine. <b>▶ Run Build</b> — one phased
|
|
6115
|
+
build (MVP→Ph1→Ph2), runs in background. <b>🔁 Build Until Done</b>
|
|
6116
|
+
— loops continuously until roadmap exhausted. <b>PM Loop ▶</b> —
|
|
6117
|
+
reads ROADMAP.md and dispatches each item one at a time.
|
|
5998
6118
|
</div>
|
|
5999
6119
|
</div>
|
|
6000
6120
|
|
|
Binary file
|
|
Binary file
|
package/apps/vibe/README.md
CHANGED
|
@@ -48,7 +48,7 @@ npm run perf:audit
|
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
`npm run test` runs the standalone smoke, accessibility, performance, and security checks.
|
|
51
|
-
`npm run test:e2e` runs a self-contained local HTTP/API end-to-end check for the shipped
|
|
51
|
+
`npm run test:e2e` runs a self-contained local HTTP/API end-to-end check for the shipped Vibe bundle and server routes.
|
|
52
52
|
|
|
53
53
|
## Performance Tooling
|
|
54
54
|
|
|
@@ -60,7 +60,7 @@ python3 ../../scripts/bench/load_testing.py \
|
|
|
60
60
|
--requests 40 \
|
|
61
61
|
--concurrency 4 \
|
|
62
62
|
--profile-command "npm start" \
|
|
63
|
-
--profile-output /tmp/crewswarm-
|
|
63
|
+
--profile-output /tmp/crewswarm-vibe.speedscope.json
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
Use `npm run perf:audit` for a browser-level audit of the shipped Vibe bundle. It boots the local Vibe server on an isolated port, captures navigation timing, transfer size, long tasks, and heap usage through Playwright + the browser Performance APIs, then writes a report to `apps/vibe/output/performance-audit.json`.
|
package/apps/vibe/package.json
CHANGED
package/apps/vibe/server.mjs
CHANGED
|
@@ -13,7 +13,7 @@ import http from "node:http";
|
|
|
13
13
|
import os from "node:os";
|
|
14
14
|
import path from "node:path";
|
|
15
15
|
import fs from "node:fs";
|
|
16
|
-
import { spawn } from "node:child_process";
|
|
16
|
+
import { spawn, execFileSync } from "node:child_process";
|
|
17
17
|
import { fileURLToPath } from "node:url";
|
|
18
18
|
import { WebSocketServer } from "ws";
|
|
19
19
|
import { shouldSkipGeminiPassthroughLine } from "../../lib/gemini-cli-passthrough-noise.mjs";
|
|
@@ -40,9 +40,9 @@ const SHARED_PROJECTS_FILE = path.join(CREWSWARM_CFG_DIR, "projects.json");
|
|
|
40
40
|
const UI_STATE_FILE = path.join(CREWSWARM_CFG_DIR, "ui-state.json");
|
|
41
41
|
const DEFAULT_PROJECT = {
|
|
42
42
|
id: DEFAULT_PROJECT_ID,
|
|
43
|
-
name: "
|
|
43
|
+
name: "Vibe Workspace",
|
|
44
44
|
outputDir: WORKSPACE_DIR,
|
|
45
|
-
description: "Local
|
|
45
|
+
description: "Local Vibe workspace",
|
|
46
46
|
};
|
|
47
47
|
|
|
48
48
|
const MIME_TYPES = {
|
|
@@ -752,60 +752,54 @@ function createCodexStreamRelay(onChunk) {
|
|
|
752
752
|
}
|
|
753
753
|
|
|
754
754
|
function createCrewCliStreamRelay(onChunk) {
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
let
|
|
758
|
-
let collectingAssistant = false;
|
|
759
|
-
|
|
760
|
-
const appendAssistant = (text) => {
|
|
761
|
-
const normalized = String(text || "").replace(/\r/g, "").trimEnd();
|
|
762
|
-
if (!normalized) return;
|
|
763
|
-
transcript = appendNormalizedChunk(transcript, normalized);
|
|
764
|
-
onChunk?.(`${normalized}\n`);
|
|
765
|
-
};
|
|
766
|
-
|
|
767
|
-
const handleLine = (line) => {
|
|
768
|
-
const cleaned = stripAnsi(line).replace(/\r/g, "");
|
|
769
|
-
rawTranscript = appendNormalizedChunk(rawTranscript, cleaned);
|
|
770
|
-
const trimmed = cleaned.trim();
|
|
771
|
-
if (!trimmed) {
|
|
772
|
-
if (collectingAssistant && transcript) {
|
|
773
|
-
appendAssistant("");
|
|
774
|
-
}
|
|
775
|
-
return;
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
if (trimmed === "--- Agent Response ---") {
|
|
779
|
-
collectingAssistant = true;
|
|
780
|
-
return;
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
if (trimmed === "Pipeline timeline:") {
|
|
784
|
-
collectingAssistant = false;
|
|
785
|
-
return;
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
if (collectingAssistant) {
|
|
789
|
-
appendAssistant(cleaned);
|
|
790
|
-
}
|
|
791
|
-
};
|
|
755
|
+
// Buffer ALL output — don't stream anything until we can extract the response.
|
|
756
|
+
// crew-cli emits logs + a JSON envelope; we only want the response field.
|
|
757
|
+
let rawOutput = "";
|
|
792
758
|
|
|
793
759
|
return {
|
|
794
760
|
push(chunk) {
|
|
795
|
-
|
|
796
|
-
while (lineBuffer.includes("\n")) {
|
|
797
|
-
const newlineIndex = lineBuffer.indexOf("\n");
|
|
798
|
-
const line = lineBuffer.slice(0, newlineIndex);
|
|
799
|
-
lineBuffer = lineBuffer.slice(newlineIndex + 1);
|
|
800
|
-
handleLine(line);
|
|
801
|
-
}
|
|
761
|
+
rawOutput += chunk.toString("utf8");
|
|
802
762
|
},
|
|
803
763
|
finish() {
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
764
|
+
const cleaned = stripAnsi(rawOutput).replace(/\r/g, "");
|
|
765
|
+
|
|
766
|
+
// Strategy 1: Find JSON envelope with "response" field
|
|
767
|
+
const jsonMatch = cleaned.match(/\{[\s\S]*"kind":\s*"[^"]+\.result"[\s\S]*\}/);
|
|
768
|
+
if (jsonMatch) {
|
|
769
|
+
try {
|
|
770
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
771
|
+
if (parsed.response) {
|
|
772
|
+
onChunk?.(parsed.response);
|
|
773
|
+
return parsed.response;
|
|
774
|
+
}
|
|
775
|
+
} catch { /* fall through to other strategies */ }
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
// Strategy 2: Extract "response" field via regex (handles malformed JSON)
|
|
779
|
+
const respMatch = cleaned.match(/"response":\s*"((?:[^"\\]|\\.)*)"/);
|
|
780
|
+
if (respMatch) {
|
|
781
|
+
const response = respMatch[1].replace(/\\n/g, "\n").replace(/\\"/g, '"').replace(/\\t/g, "\t");
|
|
782
|
+
onChunk?.(response);
|
|
783
|
+
return response;
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
// Strategy 3: Legacy "--- Agent Response ---" marker
|
|
787
|
+
const markerIdx = cleaned.indexOf("--- Agent Response ---");
|
|
788
|
+
if (markerIdx >= 0) {
|
|
789
|
+
let response = cleaned.slice(markerIdx + "--- Agent Response ---".length);
|
|
790
|
+
const timelineIdx = response.indexOf("Pipeline timeline:");
|
|
791
|
+
if (timelineIdx >= 0) response = response.slice(0, timelineIdx);
|
|
792
|
+
response = response.trim();
|
|
793
|
+
if (response) {
|
|
794
|
+
onChunk?.(response);
|
|
795
|
+
return response;
|
|
796
|
+
}
|
|
807
797
|
}
|
|
808
|
-
|
|
798
|
+
|
|
799
|
+
// Fallback: send raw output (stripped of common log prefixes)
|
|
800
|
+
const fallback = summarizeCliFailure("crew-cli", cleaned);
|
|
801
|
+
onChunk?.(fallback);
|
|
802
|
+
return fallback;
|
|
809
803
|
},
|
|
810
804
|
};
|
|
811
805
|
}
|
|
@@ -957,6 +951,20 @@ function createCliRelay(engine, onChunk, onDone) {
|
|
|
957
951
|
return createDefaultCliRelay(onChunk);
|
|
958
952
|
}
|
|
959
953
|
|
|
954
|
+
function isClaudeOauthAuthenticated() {
|
|
955
|
+
try {
|
|
956
|
+
const output = execFileSync("claude", ["auth", "status"], {
|
|
957
|
+
encoding: "utf8",
|
|
958
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
959
|
+
}).trim().toLowerCase();
|
|
960
|
+
if (!output) return false;
|
|
961
|
+
if (/"loggedin"\s*:\s*true/.test(output)) return true;
|
|
962
|
+
return output.includes("logged in");
|
|
963
|
+
} catch {
|
|
964
|
+
return false;
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
|
|
960
968
|
function broadcastTerminalMessage(sessionId, payload) {
|
|
961
969
|
const session = terminalSessions.get(sessionId);
|
|
962
970
|
if (!session) return;
|
|
@@ -1093,12 +1101,13 @@ export function getCliCommand(engine, projectDir, message, modelOverride, resume
|
|
|
1093
1101
|
command: binary,
|
|
1094
1102
|
args: codexArgs,
|
|
1095
1103
|
stdin: null,
|
|
1104
|
+
stripEnv: ["OPENAI_API_KEY"],
|
|
1096
1105
|
};
|
|
1097
1106
|
}
|
|
1098
1107
|
case "claude":
|
|
1099
1108
|
// Claude Code uses OAuth — no API key needed
|
|
1100
1109
|
{
|
|
1101
|
-
const args = ["-p", "--setting-sources", "user", "--output-format", "stream-json", "--verbose"];
|
|
1110
|
+
const args = ["-p", "--setting-sources", "user", "--output-format", "stream-json", "--verbose", "--permission-mode", "auto"];
|
|
1102
1111
|
const model = modelOverride || process.env.CREWSWARM_CLAUDE_CODE_MODEL || "";
|
|
1103
1112
|
// Add workspace directory context
|
|
1104
1113
|
if (projectDir) args.push("--add-dir", projectDir);
|
|
@@ -1110,7 +1119,7 @@ export function getCliCommand(engine, projectDir, message, modelOverride, resume
|
|
|
1110
1119
|
command: "claude",
|
|
1111
1120
|
args,
|
|
1112
1121
|
stdin: null,
|
|
1113
|
-
stripEnv: ["CLAUDECODE", "CLAUDE_CODE"],
|
|
1122
|
+
stripEnv: ["CLAUDECODE", "CLAUDE_CODE", "ANTHROPIC_API_KEY"],
|
|
1114
1123
|
};
|
|
1115
1124
|
}
|
|
1116
1125
|
case "cursor":
|
|
@@ -1153,6 +1162,7 @@ export function getCliCommand(engine, projectDir, message, modelOverride, resume
|
|
|
1153
1162
|
command: "gemini",
|
|
1154
1163
|
args,
|
|
1155
1164
|
stdin: null,
|
|
1165
|
+
stripEnv: ["GEMINI_API_KEY", "GOOGLE_API_KEY"],
|
|
1156
1166
|
};
|
|
1157
1167
|
}
|
|
1158
1168
|
case "opencode":
|
|
@@ -1165,7 +1175,7 @@ export function getCliCommand(engine, projectDir, message, modelOverride, resume
|
|
|
1165
1175
|
model = cfg.opencodeModel || "";
|
|
1166
1176
|
} catch {}
|
|
1167
1177
|
}
|
|
1168
|
-
if (!model) model = "
|
|
1178
|
+
if (!model) model = "openai/gpt-5.2-codex";
|
|
1169
1179
|
const args = ["run", "-m", model, message];
|
|
1170
1180
|
// Add workspace directory context
|
|
1171
1181
|
if (projectDir) args.push("--dir", projectDir);
|
|
@@ -1175,12 +1185,13 @@ export function getCliCommand(engine, projectDir, message, modelOverride, resume
|
|
|
1175
1185
|
command: "opencode",
|
|
1176
1186
|
args,
|
|
1177
1187
|
stdin: null,
|
|
1188
|
+
stripEnv: ["OPENAI_API_KEY", "ANTHROPIC_API_KEY", "GEMINI_API_KEY"],
|
|
1178
1189
|
};
|
|
1179
1190
|
}
|
|
1180
1191
|
case "crew-cli": {
|
|
1181
1192
|
const crewBin = path.join(__dirname, "..", "..", "crew-cli", "bin", "crew.js");
|
|
1182
1193
|
const model = modelOverride || process.env.CREWSWARM_CREW_CLI_MODEL || "";
|
|
1183
|
-
const crewArgs = [crewBin, "chat", message, ...(projectDir ? ["--project", projectDir] : []), ...(model ? ["--model", model] : [])];
|
|
1194
|
+
const crewArgs = [crewBin, "chat", message, "--apply", "--json", ...(projectDir ? ["--project", projectDir] : []), ...(model ? ["--model", model] : [])];
|
|
1184
1195
|
// Resume: crew-cli supports --session for conversation continuity
|
|
1185
1196
|
if (resumeSession?.sessionId) crewArgs.push("--session", resumeSession.sessionId);
|
|
1186
1197
|
return {
|
|
@@ -1214,6 +1225,10 @@ export function runCli({
|
|
|
1214
1225
|
resume = true,
|
|
1215
1226
|
}) {
|
|
1216
1227
|
return new Promise((resolve, reject) => {
|
|
1228
|
+
if (engine === "claude" && !isClaudeOauthAuthenticated()) {
|
|
1229
|
+
reject(new Error("Claude Code requires CLI OAuth login. Run `claude auth login` and try again."));
|
|
1230
|
+
return;
|
|
1231
|
+
}
|
|
1217
1232
|
// Look up existing session for resume
|
|
1218
1233
|
const resumeKey = getCliResumeKey(engine, projectDir);
|
|
1219
1234
|
const resumeSession = resume ? cliResumeSessions.get(resumeKey) : undefined;
|
|
@@ -1857,12 +1872,42 @@ export const server = http.createServer(async (req, res) => {
|
|
|
1857
1872
|
return;
|
|
1858
1873
|
}
|
|
1859
1874
|
|
|
1875
|
+
// GET /api/studio/git-diff — return changed files with old/new content for diff preview
|
|
1876
|
+
if (parsedUrl.pathname === "/api/studio/git-diff" && req.method === "GET") {
|
|
1877
|
+
const projDir = parsedUrl.searchParams.get("projectDir") || WORKSPACE_DIR;
|
|
1878
|
+
const resolved = resolveStudioProjectPath(projDir, WORKSPACE_DIR);
|
|
1879
|
+
try {
|
|
1880
|
+
const { execSync } = await import("node:child_process");
|
|
1881
|
+
const hasGit = fs.existsSync(path.join(resolved, ".git"));
|
|
1882
|
+
if (!hasGit) {
|
|
1883
|
+
sendJson(res, 200, { ok: true, files: [], message: "Not a git repository" });
|
|
1884
|
+
return;
|
|
1885
|
+
}
|
|
1886
|
+
const filesRaw = execSync("git diff --name-only", { cwd: resolved, encoding: "utf8", timeout: 3000 }).trim();
|
|
1887
|
+
const files = filesRaw ? filesRaw.split("\n").filter(Boolean) : [];
|
|
1888
|
+
// For each changed file, get old (HEAD) and new (working tree) content
|
|
1889
|
+
const changes = [];
|
|
1890
|
+
for (const f of files.slice(0, 20)) {
|
|
1891
|
+
try {
|
|
1892
|
+
let oldContent = "";
|
|
1893
|
+
try { oldContent = execSync(`git show HEAD:${f}`, { cwd: resolved, encoding: "utf8", timeout: 3000 }); } catch { /* new file */ }
|
|
1894
|
+
const newContent = fs.readFileSync(path.join(resolved, f), "utf8");
|
|
1895
|
+
changes.push({ path: f, oldContent, newContent });
|
|
1896
|
+
} catch { /* skip unreadable */ }
|
|
1897
|
+
}
|
|
1898
|
+
sendJson(res, 200, { ok: true, files, changes });
|
|
1899
|
+
} catch (e) {
|
|
1900
|
+
sendJson(res, 200, { ok: true, files: [], changes: [], error: e.message });
|
|
1901
|
+
}
|
|
1902
|
+
return;
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1860
1905
|
if (parsedUrl.pathname === "/api/studio/chat/unified" && req.method === "POST") {
|
|
1861
1906
|
try {
|
|
1862
1907
|
const body = await readBody(req);
|
|
1863
1908
|
if (body.mode !== "cli") {
|
|
1864
1909
|
sendJson(res, 400, {
|
|
1865
|
-
error: "Local
|
|
1910
|
+
error: "Local Vibe chat only supports CLI passthrough right now",
|
|
1866
1911
|
});
|
|
1867
1912
|
return;
|
|
1868
1913
|
}
|
package/crew-lead.mjs
CHANGED
|
@@ -101,6 +101,7 @@ import {
|
|
|
101
101
|
} from "./lib/crew-lead/wave-dispatcher.mjs";
|
|
102
102
|
import { normalizeRtAgentId } from "./lib/agent-registry.mjs";
|
|
103
103
|
import { handleAutonomousMentions } from "./lib/chat/autonomous-mentions.mjs";
|
|
104
|
+
import { saveProjectMessage } from "./lib/chat/project-messages.mjs";
|
|
104
105
|
import { initIntervalManagers } from "./lib/crew-lead/interval-manager.mjs";
|
|
105
106
|
|
|
106
107
|
// ── Single instance + canonical PID (dashboard / restart-crew-lead.sh use this path) ──
|
|
@@ -128,6 +129,11 @@ const agentLastHeartbeat = new Map(); // agentId → timestamp (ms) — tracks
|
|
|
128
129
|
// SSE message throttling to prevent dashboard flashing
|
|
129
130
|
const SSE_THROTTLE_MS = 500; // Only send same agent_working/idle once per 500ms
|
|
130
131
|
const sseThrottle = new Map(); // key → lastSentMs
|
|
132
|
+
// Clean stale throttle entries every 10 minutes (#17)
|
|
133
|
+
setInterval(() => {
|
|
134
|
+
const cutoff = Date.now() - 3600_000; // 1 hour TTL
|
|
135
|
+
for (const [k, v] of sseThrottle) { if (v < cutoff) sseThrottle.delete(k); }
|
|
136
|
+
}, 600_000);
|
|
131
137
|
|
|
132
138
|
|
|
133
139
|
|
|
@@ -581,11 +587,33 @@ process.on("unhandledRejection", (reason) => {
|
|
|
581
587
|
});
|
|
582
588
|
|
|
583
589
|
process.on("uncaughtException", (err) => {
|
|
584
|
-
|
|
590
|
+
const msg = String(err?.message || err || "");
|
|
591
|
+
console.error("[crew-lead] uncaught exception:", err?.stack || msg);
|
|
592
|
+
|
|
593
|
+
// Benign errors from engine passthrough / WebSocket streams — keep alive
|
|
594
|
+
if (
|
|
595
|
+
msg === "terminated" ||
|
|
596
|
+
msg === "aborted" ||
|
|
597
|
+
/client.*disconnect/i.test(msg) ||
|
|
598
|
+
/socket hang up/i.test(msg) ||
|
|
599
|
+
/ECONNRESET/i.test(msg) ||
|
|
600
|
+
/EPIPE/i.test(msg) ||
|
|
601
|
+
/fetch failed/i.test(msg) ||
|
|
602
|
+
/UND_ERR/i.test(msg) ||
|
|
603
|
+
/ECONNREFUSED/i.test(msg)
|
|
604
|
+
) {
|
|
605
|
+
console.error("[crew-lead] Non-fatal uncaughtException — keeping alive");
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
585
608
|
|
|
586
|
-
//
|
|
587
|
-
|
|
588
|
-
|
|
609
|
+
// Fatal errors: port conflicts, permissions, OOM — must exit
|
|
610
|
+
if (/EADDRINUSE|EACCES|out of memory|cannot allocate/i.test(msg)) {
|
|
611
|
+
console.error("[crew-lead] FATAL — exiting due to uncaught exception");
|
|
612
|
+
process.exit(1);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// Default: log but keep alive
|
|
616
|
+
console.error("[crew-lead] Unexpected uncaughtException — keeping alive (not fatal)");
|
|
589
617
|
});
|
|
590
618
|
|
|
591
619
|
// ── RT Bus listener — receives replies from agents ────────────────────────────
|
|
@@ -616,6 +644,7 @@ initWaveDispatcher({
|
|
|
616
644
|
bumpOpsCounter,
|
|
617
645
|
tryRead,
|
|
618
646
|
_cursorWavesEnabled,
|
|
647
|
+
loadAgentList: loadAgentListFromConfig,
|
|
619
648
|
getClaudeCodeEnabled: () => _claudeCodeEnabled,
|
|
620
649
|
dispatchTimeoutMs: DISPATCH_TIMEOUT_MS,
|
|
621
650
|
dispatchClaimedTimeoutMs: DISPATCH_CLAIMED_TIMEOUT_MS,
|
|
@@ -646,6 +675,7 @@ const connectRT = initWsRouter({
|
|
|
646
675
|
appendHistory,
|
|
647
676
|
pendingPipelines,
|
|
648
677
|
handleAutonomousMentions,
|
|
678
|
+
saveProjectMessage,
|
|
649
679
|
checkWaveQualityGate,
|
|
650
680
|
failPipelineOnQualityGate,
|
|
651
681
|
savePipelineState,
|
|
@@ -313,7 +313,7 @@ function existsSync(path) {
|
|
|
313
313
|
function getDefaultModelForCLI(cliName) {
|
|
314
314
|
switch (cliName) {
|
|
315
315
|
case "opencode":
|
|
316
|
-
return process.env.CREWSWARM_OPENCODE_MODEL || "
|
|
316
|
+
return process.env.CREWSWARM_OPENCODE_MODEL || "openai/gpt-5.4";
|
|
317
317
|
case "cursor":
|
|
318
318
|
return process.env.CURSOR_DEFAULT_MODEL || "gemini-3-flash";
|
|
319
319
|
case "claude":
|
|
@@ -43,6 +43,10 @@ export function initGatewayWs(deps) {
|
|
|
43
43
|
|
|
44
44
|
const client = {
|
|
45
45
|
publish({ channel, type, to = "broadcast", taskId, correlationId, priority = "medium", payload = {} }) {
|
|
46
|
+
if (!ready) {
|
|
47
|
+
console.warn(`[gateway-ws] Publish skipped — client not ready (channel=${channel}, to=${to})`);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
46
50
|
sendFrame({
|
|
47
51
|
type: "publish",
|
|
48
52
|
channel,
|
|
@@ -14,6 +14,7 @@ export function shouldDropPassthroughStderrLine(engine, line) {
|
|
|
14
14
|
if (/rmcp::/i.test(l)) return true;
|
|
15
15
|
if (/error decoding response body.*initialized notification/i.test(l))
|
|
16
16
|
return true;
|
|
17
|
+
if (/\[Executor\]\s+\w+\s+\((OAuth|API)\)/i.test(l)) return true;
|
|
17
18
|
if (
|
|
18
19
|
engine === "codex" &&
|
|
19
20
|
/worker quit with fatal/i.test(l) &&
|
|
@@ -198,7 +198,7 @@ export function getProjectMessageStats(projectId) {
|
|
|
198
198
|
|
|
199
199
|
const stats = {
|
|
200
200
|
total: messages.length,
|
|
201
|
-
|
|
201
|
+
bySource: {},
|
|
202
202
|
byAgent: {},
|
|
203
203
|
oldestMessage: null,
|
|
204
204
|
newestMessage: null,
|
|
@@ -206,8 +206,6 @@ export function getProjectMessageStats(projectId) {
|
|
|
206
206
|
assistantMessages: 0
|
|
207
207
|
};
|
|
208
208
|
|
|
209
|
-
stats.bySource = {};
|
|
210
|
-
|
|
211
209
|
for (const msg of messages) {
|
|
212
210
|
// Count by source
|
|
213
211
|
stats.bySource[msg.source] = (stats.bySource[msg.source] || 0) + 1;
|
|
@@ -381,8 +379,8 @@ export function buildMessageTree(projectId, rootId = null) {
|
|
|
381
379
|
if (msg.parentId && messageMap.has(msg.parentId)) {
|
|
382
380
|
// Add to parent's children
|
|
383
381
|
messageMap.get(msg.parentId).children.push(node);
|
|
384
|
-
} else
|
|
385
|
-
// Root node (no parent) or
|
|
382
|
+
} else {
|
|
383
|
+
// Root node (no parent), requested root, or orphan (parentId references missing message)
|
|
386
384
|
roots.push(node);
|
|
387
385
|
}
|
|
388
386
|
}
|
|
@@ -19,7 +19,7 @@ import { homedir } from "node:os";
|
|
|
19
19
|
const CLI_PROCESS_LOG = join(homedir(), ".crewswarm", "logs", "cli-processes.jsonl");
|
|
20
20
|
const CLI_PROCESS_STATE = join(homedir(), ".crewswarm", "cli-process-state.json");
|
|
21
21
|
|
|
22
|
-
mkdirSync(join(homedir(), ".crewswarm", "logs"), { recursive: true });
|
|
22
|
+
try { mkdirSync(join(homedir(), ".crewswarm", "logs"), { recursive: true }); } catch { /* read-only homedir */ }
|
|
23
23
|
|
|
24
24
|
// Active processes: { processId: { pid, agent, cli, task, startTime, lastActivity, status, chatId, sessionId } }
|
|
25
25
|
let activeProcesses = new Map();
|
|
@@ -121,10 +121,11 @@ export function completeCLIProcess(processId, result) {
|
|
|
121
121
|
log("info", "CLI process completed", { processId, ...result });
|
|
122
122
|
|
|
123
123
|
// Remove from active list after 30s (keep recent history visible)
|
|
124
|
-
setTimeout(() => {
|
|
124
|
+
const timer = setTimeout(() => {
|
|
125
125
|
activeProcesses.delete(processId);
|
|
126
126
|
saveState();
|
|
127
127
|
}, 30000);
|
|
128
|
+
timer.unref(); // Don't prevent process exit in tests
|
|
128
129
|
}
|
|
129
130
|
|
|
130
131
|
/**
|