crewswarm 0.8.1-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +155 -0
- package/LICENSE +21 -0
- package/README.md +316 -0
- package/apps/dashboard/dist/assets/chat-core-BwSoInmZ.js +1 -0
- package/apps/dashboard/dist/assets/chat-core-BwSoInmZ.js.br +0 -0
- package/apps/dashboard/dist/assets/cli-process-COMRNPqr.js +1 -0
- package/apps/dashboard/dist/assets/cli-process-COMRNPqr.js.br +0 -0
- package/apps/dashboard/dist/assets/components-CSUb80ze.js +1 -0
- package/apps/dashboard/dist/assets/components-CSUb80ze.js.br +0 -0
- package/apps/dashboard/dist/assets/core-utils-CAVnDoe1.js +1 -0
- package/apps/dashboard/dist/assets/core-utils-CAVnDoe1.js.br +0 -0
- package/apps/dashboard/dist/assets/index-CF0aJRtC.css +1 -0
- package/apps/dashboard/dist/assets/index-CF0aJRtC.css.br +0 -0
- package/apps/dashboard/dist/assets/index-Px49zu76.js +2 -0
- package/apps/dashboard/dist/assets/index-Px49zu76.js.br +0 -0
- package/apps/dashboard/dist/assets/orchestration-Ca2DLWN-.js +1 -0
- package/apps/dashboard/dist/assets/orchestration-Ca2DLWN-.js.br +0 -0
- package/apps/dashboard/dist/assets/setup-wizard-i3eEixlo.js +1 -0
- package/apps/dashboard/dist/assets/setup-wizard-i3eEixlo.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-agents-tab-BThdsdJY.js +1 -0
- package/apps/dashboard/dist/assets/tab-agents-tab-BThdsdJY.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-benchmarks-tab-DfCuAClu.js +1 -0
- package/apps/dashboard/dist/assets/tab-comms-tab-eHpOSBhG.js +1 -0
- package/apps/dashboard/dist/assets/tab-comms-tab-eHpOSBhG.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-contacts-tab-yEegNyO4.js +1 -0
- package/apps/dashboard/dist/assets/tab-contacts-tab-yEegNyO4.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-engines-tab-C3DYxTwy.js +1 -0
- package/apps/dashboard/dist/assets/tab-engines-tab-C3DYxTwy.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-memory-tab-C59BYFQD.js +1 -0
- package/apps/dashboard/dist/assets/tab-memory-tab-C59BYFQD.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-models-tab-9Ur7pXWA.js +1 -0
- package/apps/dashboard/dist/assets/tab-models-tab-9Ur7pXWA.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-pm-loop-tab-D7mnDelU.js +1 -0
- package/apps/dashboard/dist/assets/tab-pm-loop-tab-D7mnDelU.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-projects-tab-C6h2Mv1K.js +1 -0
- package/apps/dashboard/dist/assets/tab-projects-tab-C6h2Mv1K.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-prompts-tab-C0wZvWK3.js +1 -0
- package/apps/dashboard/dist/assets/tab-prompts-tab-C0wZvWK3.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-services-tab-DBj_w3bc.js +1 -0
- package/apps/dashboard/dist/assets/tab-services-tab-DBj_w3bc.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-settings-tab-ezeqAjZk.js +1 -0
- package/apps/dashboard/dist/assets/tab-settings-tab-ezeqAjZk.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-skills-tab-BYdU2whk.js +1 -0
- package/apps/dashboard/dist/assets/tab-skills-tab-BYdU2whk.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-spending-tab-Bg6w9t_p.js +1 -0
- package/apps/dashboard/dist/assets/tab-spending-tab-Bg6w9t_p.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-swarm-chat-tab-BBV9HB2X.js +1 -0
- package/apps/dashboard/dist/assets/tab-swarm-chat-tab-BBV9HB2X.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-swarm-tab-ChqLlEVs.js +1 -0
- package/apps/dashboard/dist/assets/tab-swarm-tab-ChqLlEVs.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-usage-tab-B2UWXenJ.js +1 -0
- package/apps/dashboard/dist/assets/tab-usage-tab-B2UWXenJ.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-waves-tab-SaJDkb4x.js +1 -0
- package/apps/dashboard/dist/assets/tab-waves-tab-SaJDkb4x.js.br +0 -0
- package/apps/dashboard/dist/assets/tab-workflows-tab-6QSXLJ0i.js +1 -0
- package/apps/dashboard/dist/assets/tab-workflows-tab-6QSXLJ0i.js.br +0 -0
- package/apps/dashboard/dist/favicon.png +0 -0
- package/apps/dashboard/dist/index.html +6466 -0
- package/apps/dashboard/dist/index.html.br +0 -0
- package/apps/dashboard/dist/index.html.gz +0 -0
- package/apps/dashboard/dist/signup.html +446 -0
- package/apps/dashboard/index.html +6442 -0
- package/apps/dashboard/package.json +15 -0
- package/apps/dashboard/src/app.js +2823 -0
- 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 +1847 -0
- package/apps/dashboard/src/chat/chat-actions.js.br +0 -0
- package/apps/dashboard/src/chat/unified-messages.js +327 -0
- package/apps/dashboard/src/chat/unified-messages.js.br +0 -0
- package/apps/dashboard/src/cli-process.js +208 -0
- 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 +175 -0
- package/apps/dashboard/src/components/active-tasks-panel.js.br +0 -0
- package/apps/dashboard/src/core/api.js +18 -0
- package/apps/dashboard/src/core/api.js.br +0 -0
- package/apps/dashboard/src/core/dom.js +220 -0
- package/apps/dashboard/src/core/dom.js.br +0 -0
- package/apps/dashboard/src/core/state.js +91 -0
- package/apps/dashboard/src/core/state.js.br +0 -0
- package/apps/dashboard/src/core/task-manager.js +134 -0
- package/apps/dashboard/src/core/task-manager.js.br +0 -0
- package/apps/dashboard/src/orchestration-status.js +127 -0
- package/apps/dashboard/src/orchestration-status.js.br +0 -0
- package/apps/dashboard/src/setup-wizard.js +555 -0
- package/apps/dashboard/src/setup-wizard.js.br +0 -0
- package/apps/dashboard/src/styles.css +2085 -0
- 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 +2237 -0
- package/apps/dashboard/src/tabs/agents-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/benchmarks-tab.js +229 -0
- package/apps/dashboard/src/tabs/benchmarks-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/comms-tab.js +955 -0
- package/apps/dashboard/src/tabs/comms-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/contacts-tab.js +654 -0
- package/apps/dashboard/src/tabs/contacts-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/engines-tab.js +175 -0
- package/apps/dashboard/src/tabs/engines-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/memory-tab.js +182 -0
- package/apps/dashboard/src/tabs/memory-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/models-tab.js +441 -0
- package/apps/dashboard/src/tabs/models-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/pm-loop-tab.js +185 -0
- package/apps/dashboard/src/tabs/pm-loop-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/projects-tab.js +663 -0
- 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 +160 -0
- package/apps/dashboard/src/tabs/prompts-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/services-tab.js +202 -0
- package/apps/dashboard/src/tabs/services-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/settings-tab.js +803 -0
- package/apps/dashboard/src/tabs/settings-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/skills-tab.js +284 -0
- package/apps/dashboard/src/tabs/skills-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/spending-tab.js +173 -0
- package/apps/dashboard/src/tabs/spending-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/swarm-chat-tab.js +660 -0
- package/apps/dashboard/src/tabs/swarm-chat-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/swarm-tab.js +538 -0
- package/apps/dashboard/src/tabs/swarm-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/usage-tab.js +390 -0
- package/apps/dashboard/src/tabs/usage-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/waves-tab.js +238 -0
- package/apps/dashboard/src/tabs/waves-tab.js.br +0 -0
- package/apps/dashboard/src/tabs/workflows-tab.js +747 -0
- package/apps/dashboard/src/tabs/workflows-tab.js.br +0 -0
- package/apps/vibe/.crew/agent-memory/pipeline.json +249 -0
- package/apps/vibe/.crew/cost.json +17 -0
- package/apps/vibe/.crew/json-parse-metrics.jsonl +22 -0
- package/apps/vibe/.crew/pipeline-metrics.jsonl +22 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-0f90c392-2425-4ae5-850c-bd9d17b1d690.jsonl +5 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-1c269dd9-a63f-4fba-af81-5cf08048ef06.jsonl +5 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-288a7765-da24-4a22-89bc-1f3cc9b0562c.jsonl +1 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-2c78fd22-a657-4bd1-bc49-0679fb384409.jsonl +5 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-3e6fe08d-3264-404a-8df3-aab7efef10e7.jsonl +5 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-42eec610-57fe-4e09-9e7e-b315038495c2.jsonl +5 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-4438eb4c-ae13-42b1-90e2-b043d8983be8.jsonl +5 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-4740a9f5-86e7-44b6-a394-de433e291727.jsonl +5 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-49e1da6a-957e-48fd-9220-415019e4f8e2.jsonl +5 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-4c9251db-be68-427b-a3fc-a264f2b5778d.jsonl +5 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-65e29a57-664d-4196-8109-017e364f182e.jsonl +5 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-6aa04bc5-9593-4b1f-b58d-3bf2978cb602.jsonl +5 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-6e1cba53-9b70-457e-99e0-59199149dd21.jsonl +5 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-749f41cc-4dac-4204-be64-873a6080a0d2.jsonl +5 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-74d68121-e181-4864-bd9a-c3211341dfaf.jsonl +5 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-8509bc24-142d-4e07-b44a-a50bf99d1103.jsonl +5 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-960339c6-07ca-43ce-9900-f6e1702b39b9.jsonl +5 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-9c6480a9-7031-4146-b241-825b9a2d1de1.jsonl +5 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-9fd42426-8492-4157-9d5f-e1537c060489.jsonl +2 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-ad6d40a3-2f5e-46a9-a345-47caaccc51aa.jsonl +5 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-bc606133-8d5b-4535-8d85-f1a29cdaa981.jsonl +5 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-c1a13ccd-634a-4d01-a4a7-1177b8a752ff.jsonl +5 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-c7d27b42-249e-4bd4-8f26-6aa998110b8a.jsonl +5 -0
- package/apps/vibe/.crew/pipeline-runs/pipeline-cca2e9b9-4a34-4d25-a311-5c793fa7e91e.jsonl +5 -0
- package/apps/vibe/.crew/sandbox.json +7 -0
- package/apps/vibe/.crew/session.json +285 -0
- package/apps/vibe/.crew/training-data.jsonl +0 -0
- package/apps/vibe/.github/workflows/studio-quality.yml +37 -0
- package/apps/vibe/.studio-data/project-messages/chuck-norris.jsonl +12 -0
- package/apps/vibe/.studio-data/project-messages/general.jsonl +54 -0
- package/apps/vibe/.studio-data/project-messages/studio-local.jsonl +10 -0
- package/apps/vibe/ARCHITECTURE.md +3393 -0
- package/apps/vibe/QUICK-REFERENCE.md +211 -0
- package/apps/vibe/README.md +76 -0
- package/apps/vibe/ROADMAP.md +41 -0
- package/apps/vibe/STUDIO-SETUP-COMPLETE.md +35 -0
- package/apps/vibe/VISUAL-GUIDE.md +378 -0
- package/apps/vibe/capture-demo.mjs +160 -0
- package/apps/vibe/capture-vibe-assets.mjs +71 -0
- package/apps/vibe/capture-vibe-video.mjs +260 -0
- package/apps/vibe/check-buttons.js +41 -0
- package/apps/vibe/diagnose.html +106 -0
- package/apps/vibe/fix-buttons.js +103 -0
- package/apps/vibe/index.html +3401 -0
- package/apps/vibe/package-lock.json +920 -0
- package/apps/vibe/package.json +31 -0
- package/apps/vibe/public/favicon.png +0 -0
- package/apps/vibe/scripts/studio-pty-host.py +117 -0
- package/apps/vibe/server.mjs +1835 -0
- package/apps/vibe/src/main.js +2846 -0
- package/apps/vibe/src/register-all-languages.js +98 -0
- package/apps/vibe/start-studio.sh +11 -0
- package/apps/vibe/test/accessibility-tests.js +77 -0
- package/apps/vibe/test/browser-performance-audit.mjs +205 -0
- package/apps/vibe/test/performance-tests.js +120 -0
- package/apps/vibe/test/security-tests.js +213 -0
- package/apps/vibe/tests/e2e.local.mjs +54 -0
- package/apps/vibe/tests/server.smoke.mjs +106 -0
- package/apps/vibe/update_website.mjs +74 -0
- package/apps/vibe/vite.config.js +19 -0
- package/apps/vibe/watch-server.mjs +108 -0
- package/contrib/openclaw-plugin/README.md +199 -0
- package/contrib/openclaw-plugin/index.ts +306 -0
- package/contrib/openclaw-plugin/openclaw.plugin.json +41 -0
- package/contrib/openclaw-plugin/package.json +27 -0
- package/contrib/openclaw-plugin/skills/crewswarm/SKILL.md +88 -0
- package/crew-lead.mjs +649 -0
- package/engines/claude-code.json +36 -0
- package/engines/codex.json +37 -0
- package/engines/crew-cli.json +42 -0
- package/engines/cursor.json +40 -0
- package/engines/docker-sandbox.json +38 -0
- package/engines/gemini-cli.json +75 -0
- package/engines/opencode.json +31 -0
- package/gateway-bridge.mjs +1575 -0
- package/install.sh +738 -0
- package/lib/agent-registry.mjs +232 -0
- package/lib/agents/daemon.mjs +121 -0
- package/lib/agents/dispatch.mjs +225 -0
- package/lib/agents/permissions.mjs +90 -0
- package/lib/agents/platform-formatting.mjs +102 -0
- package/lib/agents/registry.mjs +81 -0
- package/lib/agents/tool-instructions.mjs +257 -0
- package/lib/agents/validation.mjs +75 -0
- package/lib/approval/policy-manager.mjs +221 -0
- package/lib/autoharness/index.mjs +391 -0
- package/lib/bridges/cli-executor.mjs +332 -0
- package/lib/bridges/gateway-ws.mjs +345 -0
- package/lib/bridges/integration.mjs +229 -0
- package/lib/bridges/rag-helper.mjs +90 -0
- package/lib/browser/opencode-passthrough-filter.js +44 -0
- package/lib/browser/passthrough-stderr.js +109 -0
- package/lib/chat/autonomous-mentions.mjs +373 -0
- package/lib/chat/history.mjs +82 -0
- package/lib/chat/mention-routing-intent.mjs +136 -0
- package/lib/chat/participants.mjs +95 -0
- package/lib/chat/project-messages-rag.mjs +265 -0
- package/lib/chat/project-messages.mjs +479 -0
- package/lib/chat/shared-chat-prompt-overlay.mjs +52 -0
- package/lib/chat/thread-binding.mjs +34 -0
- package/lib/chat/unified-history.mjs +223 -0
- package/lib/chat/unified-wrapper.mjs +41 -0
- package/lib/cli-process-tracker.mjs +228 -0
- package/lib/collections/index.mjs +433 -0
- package/lib/contacts/identity-linker.mjs +248 -0
- package/lib/contacts/index.mjs +341 -0
- package/lib/crew-judge/PROMPT.md +93 -0
- package/lib/crew-judge/judge.mjs +260 -0
- package/lib/crew-lead/agent-manager.mjs +125 -0
- package/lib/crew-lead/background.mjs +270 -0
- package/lib/crew-lead/brain.mjs +110 -0
- package/lib/crew-lead/chat-handler.mjs +2603 -0
- package/lib/crew-lead/chat-handler.mjs.bak +1274 -0
- package/lib/crew-lead/classifier.mjs +83 -0
- package/lib/crew-lead/http-server.mjs +4824 -0
- package/lib/crew-lead/intent.mjs +102 -0
- package/lib/crew-lead/interval-manager.mjs +41 -0
- package/lib/crew-lead/llm-caller.mjs +544 -0
- package/lib/crew-lead/prompts.mjs +392 -0
- package/lib/crew-lead/retry-manager.mjs +118 -0
- package/lib/crew-lead/tools.mjs +318 -0
- package/lib/crew-lead/wave-dispatcher.mjs +798 -0
- package/lib/crew-lead/waves-config.json +73 -0
- package/lib/crew-lead/waves-loader.mjs +110 -0
- package/lib/crew-lead/ws-router.mjs +428 -0
- package/lib/dispatch/parsers.mjs +299 -0
- package/lib/domain-planning/detector.mjs +196 -0
- package/lib/domain-planning/prompts/crew-pm-cli.md +96 -0
- package/lib/domain-planning/prompts/crew-pm-core.md +122 -0
- package/lib/domain-planning/prompts/crew-pm-frontend.md +111 -0
- package/lib/engines/crew-cli-sandbox.mjs +422 -0
- package/lib/engines/crew-cli.mjs +155 -0
- package/lib/engines/cursor-launcher.mjs +110 -0
- package/lib/engines/engine-registry.mjs +253 -0
- package/lib/engines/llm-direct.mjs +184 -0
- package/lib/engines/opencode.mjs +256 -0
- package/lib/engines/ouroboros.mjs +114 -0
- package/lib/engines/rt-envelope.mjs +1643 -0
- package/lib/engines/rt-envelope.mjs.backup-current +870 -0
- package/lib/engines/runners.mjs +1367 -0
- package/lib/gemini-cli-passthrough-noise.mjs +37 -0
- package/lib/integrations/code-search.mjs +259 -0
- package/lib/integrations/greptile.mjs +148 -0
- package/lib/integrations/multimodal.mjs +313 -0
- package/lib/integrations/telegram-streaming.mjs +153 -0
- package/lib/integrations/tts.mjs +312 -0
- package/lib/integrations/twitter-links.mjs +294 -0
- package/lib/memory/shared-adapter.mjs +296 -0
- package/lib/pipeline/manager.mjs +539 -0
- package/lib/preferences/extractor.mjs +347 -0
- package/lib/project-dir.mjs +20 -0
- package/lib/runtime/config.mjs +388 -0
- package/lib/runtime/dlq.mjs +170 -0
- package/lib/runtime/log-rotation.mjs +82 -0
- package/lib/runtime/logger.mjs +58 -0
- package/lib/runtime/memory.mjs +421 -0
- package/lib/runtime/paths.mjs +76 -0
- package/lib/runtime/project-dir.mjs +127 -0
- package/lib/runtime/spending.mjs +204 -0
- package/lib/runtime/startup-guard.mjs +291 -0
- package/lib/runtime/task-lease.mjs +234 -0
- package/lib/runtime/telemetry-schema.mjs +208 -0
- package/lib/runtime/telemetry.mjs +101 -0
- package/lib/runtime/utils.mjs +64 -0
- package/lib/skills/index.mjs +265 -0
- package/lib/tools/browser.mjs +135 -0
- package/lib/tools/executor.mjs +913 -0
- package/lib/types.d.ts +57 -0
- package/package.json +106 -0
- package/pm-loop.mjs +1626 -0
- package/prompts/coder-back.md +27 -0
- package/prompts/coder-front.md +27 -0
- package/prompts/coder.md +28 -0
- package/prompts/copywriter.md +17 -0
- package/prompts/fixer.md +39 -0
- package/prompts/frontend.md +23 -0
- package/prompts/github.md +24 -0
- package/prompts/main.md +39 -0
- package/prompts/pm-cli.md +95 -0
- package/prompts/pm-core.md +121 -0
- package/prompts/pm-frontend.md +110 -0
- package/prompts/pm.md +234 -0
- package/prompts/qa.md +44 -0
- package/prompts/security.md +19 -0
- package/scripts/build-crew-chat.sh +28 -0
- package/scripts/build-llms-full.mjs +52 -0
- package/scripts/chatmock-login.sh +16 -0
- package/scripts/chatmock-serve.sh +16 -0
- package/scripts/check-dashboard.mjs +88 -0
- package/scripts/crew-scribe.mjs +326 -0
- package/scripts/dashboard-helpers.mjs +391 -0
- package/scripts/dashboard-validation.mjs +198 -0
- package/scripts/dashboard.mjs +9717 -0
- package/scripts/dlq-replay.mjs +61 -0
- package/scripts/doctor.mjs +196 -0
- package/scripts/file-lock.mjs +186 -0
- package/scripts/fresh-machine-smoke.sh +323 -0
- package/scripts/generate-changelog.mjs +227 -0
- package/scripts/generate-openapi.mjs +334 -0
- package/scripts/health-check.mjs +229 -0
- package/scripts/install-docker.sh +213 -0
- package/scripts/mcp-server.mjs +1625 -0
- package/scripts/opencrew-rt-daemon.mjs +568 -0
- package/scripts/openswitchctl +646 -0
- package/scripts/refactor-configs.mjs +39 -0
- package/scripts/release-check.sh +46 -0
- package/scripts/resolve-node-bin.sh +25 -0
- package/scripts/restart-all-from-repo.sh +329 -0
- package/scripts/restart-crew-lead.sh +98 -0
- package/scripts/restart-dashboard.sh +104 -0
- package/scripts/restart-service.sh +274 -0
- package/scripts/run-accessibility-audit.mjs +356 -0
- package/scripts/run-integration-bounded.mjs +188 -0
- package/scripts/run-scheduled-pipeline.mjs +230 -0
- package/scripts/run.mjs +41 -0
- package/scripts/scan-skills.mjs +79 -0
- package/scripts/setup-firewall.sh +128 -0
- package/scripts/smoke-dispatch.mjs +149 -0
- package/scripts/smoke.sh +163 -0
- package/scripts/start-crew.mjs +328 -0
- package/scripts/start.mjs +146 -0
- package/scripts/swiftbar-restart-service.sh +19 -0
- package/scripts/sync-agents.mjs +152 -0
- package/scripts/sync-prompts.mjs +79 -0
- package/scripts/validate-config.mjs +337 -0
- package/scripts/wow.mjs +89 -0
- package/telegram-bridge.mjs +2421 -0
- package/unified-orchestrator.mjs +519 -0
- package/whatsapp-bridge.mjs +1481 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dynamic agent creation and management — extracted from crew-lead.mjs
|
|
3
|
+
* Manages agents in ~/.crewswarm/crewswarm.json.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import fs from "node:fs";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import os from "node:os";
|
|
9
|
+
import { writeAgentTools, writeAgentPrompt } from "../agents/permissions.mjs";
|
|
10
|
+
import { getSharedChatPromptOverlay } from "../chat/shared-chat-prompt-overlay.mjs";
|
|
11
|
+
|
|
12
|
+
function tryRead(p) {
|
|
13
|
+
try { return JSON.parse(fs.readFileSync(p, "utf8")); } catch { return null; }
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function withSharedChatGuidance(id, body) {
|
|
17
|
+
return `${body}\n\n${getSharedChatPromptOverlay(id)}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const AGENT_ROLE_PRESETS = {
|
|
21
|
+
coder: {
|
|
22
|
+
tools: ["read_file", "write_file", "mkdir", "run_cmd", "skill"],
|
|
23
|
+
useOpenCode: false,
|
|
24
|
+
promptTemplate: (id, desc) => withSharedChatGuidance(id, `You are ${id}, a specialist coding agent.\n\nFocus: ${desc || "full-stack development"}\n\nUse @@READ_FILE before modifying files. Always @@WRITE_FILE your output with absolute paths. Report what you did and the full file paths in your reply.`),
|
|
25
|
+
},
|
|
26
|
+
researcher: {
|
|
27
|
+
tools: ["read_file", "web_search", "web_fetch", "skill"],
|
|
28
|
+
useOpenCode: false,
|
|
29
|
+
promptTemplate: (id, desc) => withSharedChatGuidance(id, `You are ${id}, a research specialist.\n\nFocus: ${desc || "deep research and analysis"}\n\nUse @@WEB_SEARCH and @@WEB_FETCH to gather information. Synthesize findings into clear, actionable summaries. Always cite sources.`),
|
|
30
|
+
},
|
|
31
|
+
writer: {
|
|
32
|
+
tools: ["read_file", "write_file", "web_search", "web_fetch", "skill"],
|
|
33
|
+
useOpenCode: false,
|
|
34
|
+
promptTemplate: (id, desc) => withSharedChatGuidance(id, `You are ${id}, a writing specialist.\n\nFocus: ${desc || "technical writing and documentation"}\n\nUse @@WEB_SEARCH for research when needed. Always @@WRITE_FILE your output with absolute paths. Write clear, concise, scannable content.`),
|
|
35
|
+
},
|
|
36
|
+
auditor: {
|
|
37
|
+
tools: ["read_file", "run_cmd", "skill"],
|
|
38
|
+
useOpenCode: false,
|
|
39
|
+
promptTemplate: (id, desc) => withSharedChatGuidance(id, `You are ${id}, an audit and review specialist.\n\nFocus: ${desc || "code review, testing, and quality assurance"}\n\nUse @@READ_FILE to inspect files and @@RUN_CMD for tests. Report issues with specific file paths and line numbers. Never modify files directly.`),
|
|
40
|
+
},
|
|
41
|
+
ops: {
|
|
42
|
+
tools: ["read_file", "write_file", "mkdir", "run_cmd", "git", "skill"],
|
|
43
|
+
useOpenCode: false,
|
|
44
|
+
promptTemplate: (id, desc) => withSharedChatGuidance(id, `You are ${id}, a DevOps and infrastructure specialist.\n\nFocus: ${desc || "deployment, CI/CD, infrastructure, and operations"}\n\nUse @@RUN_CMD for system tasks. Use @@WRITE_FILE for configs and scripts. Report status and any issues.`),
|
|
45
|
+
},
|
|
46
|
+
generalist: {
|
|
47
|
+
tools: ["read_file", "write_file", "mkdir", "run_cmd", "dispatch", "skill"],
|
|
48
|
+
useOpenCode: false,
|
|
49
|
+
promptTemplate: (id, desc) => withSharedChatGuidance(id, `You are ${id}, a generalist agent.\n\nFocus: ${desc || "versatile task execution"}\n\nAdapt to whatever is needed. Use @@READ_FILE, @@WRITE_FILE, @@RUN_CMD as appropriate. You can @@DISPATCH to other agents if a task needs a specialist.`),
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const MAX_DYNAMIC_AGENTS = Number(process.env.CREWSWARM_MAX_DYNAMIC_AGENTS || "5");
|
|
54
|
+
|
|
55
|
+
export function createAgent({ id, role, displayName, prompt, description, model }) {
|
|
56
|
+
if (!id) throw new Error("Agent id is required");
|
|
57
|
+
if (!id.startsWith("crew-")) id = `crew-${id}`;
|
|
58
|
+
|
|
59
|
+
const swarmPath = path.join(os.homedir(), ".crewswarm", "crewswarm.json");
|
|
60
|
+
const swarm = tryRead(swarmPath) || {};
|
|
61
|
+
if (!Array.isArray(swarm.agents)) swarm.agents = [];
|
|
62
|
+
|
|
63
|
+
// Check if agent already exists
|
|
64
|
+
if (swarm.agents.some(a => a.id === id)) {
|
|
65
|
+
throw new Error(`Agent ${id} already exists`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Count dynamic agents (those with _dynamic flag)
|
|
69
|
+
const dynamicCount = swarm.agents.filter(a => a._dynamic).length;
|
|
70
|
+
if (dynamicCount >= MAX_DYNAMIC_AGENTS) {
|
|
71
|
+
throw new Error(`Max dynamic agents (${MAX_DYNAMIC_AGENTS}) reached. Remove an existing dynamic agent first.`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const preset = AGENT_ROLE_PRESETS[role] || AGENT_ROLE_PRESETS.generalist;
|
|
75
|
+
const agentModel = model || swarm.agents.find(a => a.id === "crew-main")?.model || "groq/llama-3.3-70b-versatile";
|
|
76
|
+
|
|
77
|
+
// OpenCode is opt-in only. Dynamic agents inherit no execution engine unless explicitly assigned.
|
|
78
|
+
const openCodeEnabled = preset.useOpenCode || false;
|
|
79
|
+
const defaultOcModel = (() => {
|
|
80
|
+
const existingCoder = swarm.agents.find(a => a.opencodeModel && a.useOpenCode);
|
|
81
|
+
if (existingCoder) return existingCoder.opencodeModel;
|
|
82
|
+
return process.env.CREWSWARM_OPENCODE_MODEL || "openai/gpt-5.3-codex";
|
|
83
|
+
})();
|
|
84
|
+
|
|
85
|
+
const agentEntry = {
|
|
86
|
+
id,
|
|
87
|
+
model: agentModel,
|
|
88
|
+
_dynamic: true,
|
|
89
|
+
_createdAt: new Date().toISOString(),
|
|
90
|
+
_role: role || "generalist",
|
|
91
|
+
useOpenCode: openCodeEnabled,
|
|
92
|
+
};
|
|
93
|
+
if (openCodeEnabled) agentEntry.opencodeModel = defaultOcModel;
|
|
94
|
+
if (displayName) agentEntry.identity = { name: displayName };
|
|
95
|
+
|
|
96
|
+
swarm.agents.push(agentEntry);
|
|
97
|
+
fs.writeFileSync(swarmPath, JSON.stringify(swarm, null, 2), "utf8");
|
|
98
|
+
|
|
99
|
+
// Set tools
|
|
100
|
+
writeAgentTools(id, preset.tools);
|
|
101
|
+
|
|
102
|
+
// Set prompt
|
|
103
|
+
const agentPrompt = prompt || preset.promptTemplate(id, description);
|
|
104
|
+
const bareId = id.replace(/^crew-/, "");
|
|
105
|
+
writeAgentPrompt(bareId, agentPrompt);
|
|
106
|
+
|
|
107
|
+
return { id, role: role || "generalist", tools: preset.tools, model: agentModel, displayName, useOpenCode: openCodeEnabled };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function listDynamicAgents() {
|
|
111
|
+
const swarm = tryRead(path.join(os.homedir(), ".crewswarm", "crewswarm.json")) || {};
|
|
112
|
+
return (swarm.agents || []).filter(a => a._dynamic);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function removeDynamicAgent(id) {
|
|
116
|
+
if (!id.startsWith("crew-")) id = `crew-${id}`;
|
|
117
|
+
const swarmPath = path.join(os.homedir(), ".crewswarm", "crewswarm.json");
|
|
118
|
+
const swarm = tryRead(swarmPath) || {};
|
|
119
|
+
if (!Array.isArray(swarm.agents)) return false;
|
|
120
|
+
const idx = swarm.agents.findIndex(a => a.id === id && a._dynamic);
|
|
121
|
+
if (idx < 0) throw new Error(`${id} is not a dynamic agent (or doesn't exist)`);
|
|
122
|
+
swarm.agents.splice(idx, 1);
|
|
123
|
+
fs.writeFileSync(swarmPath, JSON.stringify(swarm, null, 2), "utf8");
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Background loop and rate-limit fallback — extracted from crew-lead.mjs
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import os from "node:os";
|
|
8
|
+
|
|
9
|
+
let _broadcastSSE = () => {};
|
|
10
|
+
let _appendHistory = () => {};
|
|
11
|
+
let _appendToBrain = () => {};
|
|
12
|
+
let _dispatchTask = () => null;
|
|
13
|
+
let _findNextRoadmapPhase = () => null;
|
|
14
|
+
let _parseDispatches = () => [];
|
|
15
|
+
let _pendingPipelines = new Map();
|
|
16
|
+
let _readProjectsRegistry = () => [];
|
|
17
|
+
let _autoAdvanceRoadmap = async () => {};
|
|
18
|
+
let _tryRead = (p) => { try { return JSON.parse(fs.readFileSync(p, "utf8")); } catch { return null; } };
|
|
19
|
+
|
|
20
|
+
let _bgConsciousnessEnabled = false;
|
|
21
|
+
let _getBgConsciousnessEnabled = null;
|
|
22
|
+
let _bgConsciousnessIntervalMs = 15 * 60 * 1000;
|
|
23
|
+
let _bgConsciousnessModel = "groq/llama-3.1-8b-instant";
|
|
24
|
+
let _brainPath = "";
|
|
25
|
+
|
|
26
|
+
export const _agentTimeoutCounts = new Map();
|
|
27
|
+
const _timeoutLog = [];
|
|
28
|
+
let _lastBgConsciousnessAt = 0;
|
|
29
|
+
let _bgLoopInterval = null;
|
|
30
|
+
|
|
31
|
+
export function initBackground({
|
|
32
|
+
broadcastSSE,
|
|
33
|
+
appendHistory,
|
|
34
|
+
appendToBrain,
|
|
35
|
+
dispatchTask,
|
|
36
|
+
findNextRoadmapPhase,
|
|
37
|
+
parseDispatches,
|
|
38
|
+
pendingPipelines,
|
|
39
|
+
readProjectsRegistry,
|
|
40
|
+
autoAdvanceRoadmap,
|
|
41
|
+
tryRead,
|
|
42
|
+
bgConsciousnessEnabled,
|
|
43
|
+
getBgConsciousnessEnabled,
|
|
44
|
+
bgConsciousnessIntervalMs,
|
|
45
|
+
bgConsciousnessModel,
|
|
46
|
+
brainPath,
|
|
47
|
+
}) {
|
|
48
|
+
if (broadcastSSE) _broadcastSSE = broadcastSSE;
|
|
49
|
+
if (appendHistory) _appendHistory = appendHistory;
|
|
50
|
+
if (appendToBrain) _appendToBrain = appendToBrain;
|
|
51
|
+
if (dispatchTask) _dispatchTask = dispatchTask;
|
|
52
|
+
if (findNextRoadmapPhase) _findNextRoadmapPhase = findNextRoadmapPhase;
|
|
53
|
+
if (parseDispatches) _parseDispatches = parseDispatches;
|
|
54
|
+
if (pendingPipelines) _pendingPipelines = pendingPipelines;
|
|
55
|
+
if (readProjectsRegistry) _readProjectsRegistry = readProjectsRegistry;
|
|
56
|
+
if (autoAdvanceRoadmap) _autoAdvanceRoadmap = autoAdvanceRoadmap;
|
|
57
|
+
if (tryRead) _tryRead = tryRead;
|
|
58
|
+
if (bgConsciousnessEnabled !== undefined) _bgConsciousnessEnabled = bgConsciousnessEnabled;
|
|
59
|
+
if (getBgConsciousnessEnabled) _getBgConsciousnessEnabled = getBgConsciousnessEnabled;
|
|
60
|
+
if (bgConsciousnessIntervalMs !== undefined) _bgConsciousnessIntervalMs = bgConsciousnessIntervalMs;
|
|
61
|
+
if (bgConsciousnessModel !== undefined) _bgConsciousnessModel = bgConsciousnessModel;
|
|
62
|
+
if (brainPath !== undefined) _brainPath = brainPath;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function recordAgentTimeout(agent) {
|
|
66
|
+
_timeoutLog.push({ agent, ts: Date.now() });
|
|
67
|
+
const cutoff = Date.now() - 24 * 60 * 60 * 1000;
|
|
68
|
+
while (_timeoutLog.length && _timeoutLog[0].ts < cutoff) _timeoutLog.shift();
|
|
69
|
+
const counts = {};
|
|
70
|
+
for (const e of _timeoutLog) counts[e.agent] = (counts[e.agent] || 0) + 1;
|
|
71
|
+
for (const [id, n] of Object.entries(counts)) _agentTimeoutCounts.set(id, n);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function getBgConsciousnessLLM() {
|
|
75
|
+
const cfg = _tryRead(path.join(os.homedir(), ".crewswarm", "crewswarm.json")) || {};
|
|
76
|
+
const providers = cfg.providers || {};
|
|
77
|
+
const [providerKey, ...modelParts] = String(_bgConsciousnessModel).split("/");
|
|
78
|
+
let modelId = modelParts.join("/") || "llama-3.1-8b-instant";
|
|
79
|
+
const p = providers[providerKey];
|
|
80
|
+
if (!p?.apiKey) return null;
|
|
81
|
+
const baseUrl = p.baseUrl || (providerKey === "groq" ? "https://api.groq.com/openai/v1" : "");
|
|
82
|
+
if (!baseUrl) return null;
|
|
83
|
+
// OpenRouter requires full ID (e.g. openrouter/hunter-alpha), not bare "hunter-alpha"
|
|
84
|
+
if ((providerKey === "openrouter" || (baseUrl || "").includes("openrouter.ai")) && modelId && !modelId.startsWith("openrouter/")) {
|
|
85
|
+
modelId = "openrouter/" + modelId;
|
|
86
|
+
}
|
|
87
|
+
return { baseUrl, apiKey: p.apiKey, modelId, providerKey };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const BG_CONSCIOUSNESS_LLM_TIMEOUT_MS = 60_000;
|
|
91
|
+
|
|
92
|
+
async function runBackgroundConsciousnessDirect() {
|
|
93
|
+
const llm = getBgConsciousnessLLM();
|
|
94
|
+
if (!llm) return false;
|
|
95
|
+
let brainContent = "";
|
|
96
|
+
try {
|
|
97
|
+
const raw = fs.readFileSync(_brainPath, "utf8");
|
|
98
|
+
const stripped = raw.replace(/^#[^\n]*\n/gm, "").replace(/^Agents: append.*\n?/gm, "").replace(/^This is the persistent.*\n?/gm, "").replace(/^Read it to.*\n?/gm, "").replace(/^Write to it.*\n?/gm, "").trim();
|
|
99
|
+
if (stripped.length < 80) {
|
|
100
|
+
console.log("[bg-loop] Brain empty — skipping consciousness cycle");
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
brainContent = raw.slice(-6000);
|
|
104
|
+
} catch {
|
|
105
|
+
console.log("[bg-loop] brain.md not found — skipping consciousness cycle");
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
const system = "You are crew-main managing the process for the user. Reply in under 100 words. Output: 1) One sentence on system/crew state or suggested next step. 2) If something needs follow-up, emit exactly one line: @@BRAIN crew-main: <fact> OR @@DISPATCH {\"agent\":\"...\",\"task\":\"...\"}. Otherwise reply NO_ACTION.";
|
|
109
|
+
const user = `Shared memory (recent):\n${brainContent}\n\nWhat should the user know? Any follow-up? Reply briefly.`;
|
|
110
|
+
const messages = [{ role: "system", content: system }, { role: "user", content: user }];
|
|
111
|
+
let content;
|
|
112
|
+
try {
|
|
113
|
+
// Reasoning models (o1/o3/gpt-5 series) don't support max_tokens parameter
|
|
114
|
+
const isReasoningModel = /^(o1|o3|gpt-5)/i.test(llm.modelId);
|
|
115
|
+
const payload = { model: llm.modelId, messages, temperature: 0.5, stream: false };
|
|
116
|
+
if (!isReasoningModel) {
|
|
117
|
+
payload.max_tokens = 256;
|
|
118
|
+
}
|
|
119
|
+
const res = await fetch(`${llm.baseUrl.replace(/\/$/, "")}/chat/completions`, {
|
|
120
|
+
method: "POST",
|
|
121
|
+
headers: { "content-type": "application/json", "authorization": `Bearer ${llm.apiKey}` },
|
|
122
|
+
body: JSON.stringify(payload),
|
|
123
|
+
signal: AbortSignal.timeout(BG_CONSCIOUSNESS_LLM_TIMEOUT_MS),
|
|
124
|
+
});
|
|
125
|
+
if (!res.ok) throw new Error(`${res.status}: ${await res.text().catch(() => "")}`);
|
|
126
|
+
const data = await res.json();
|
|
127
|
+
content = data?.choices?.[0]?.message?.content || "NO_ACTION";
|
|
128
|
+
} catch (e) {
|
|
129
|
+
console.error("[bg-loop] Background consciousness LLM failed:", e.message);
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
content = content.trim();
|
|
133
|
+
const brainMatch = content.match(/@@BRAIN\s+([^\n]+)/);
|
|
134
|
+
if (brainMatch) {
|
|
135
|
+
const entry = brainMatch[1].trim();
|
|
136
|
+
// Quality gate: reject chat fragments, status spam, and personality leaks
|
|
137
|
+
const BRAIN_JUNK = /^(crew-lead \(auto\)|Services:|System Status|All (systems|agents)|✅|Hello|Hey|Hi[,!.\s]|Yo[,!\s]|I'm |You |What |Now |Look|Always|Hell |Cute|First|RT bus)/i;
|
|
138
|
+
const looksLikeChat = entry.length < 20 || BRAIN_JUNK.test(entry) || !/[a-z]/.test(entry);
|
|
139
|
+
if (looksLikeChat) {
|
|
140
|
+
console.log("[bg-loop] @@BRAIN rejected (chat fragment):", entry.slice(0, 60));
|
|
141
|
+
} else {
|
|
142
|
+
try {
|
|
143
|
+
_appendToBrain("crew-main", entry);
|
|
144
|
+
console.log("[crew-lead] @@BRAIN (bg):", entry.slice(0, 60));
|
|
145
|
+
} catch (e) {
|
|
146
|
+
console.error("[bg-loop] Brain append failed:", e.message);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const dispatches = _parseDispatches(content);
|
|
151
|
+
for (const d of dispatches) {
|
|
152
|
+
try {
|
|
153
|
+
_dispatchTask(d.agent, d.task, "bg-consciousness", null);
|
|
154
|
+
console.log("[crew-lead] @@DISPATCH (bg):", d.agent, d.task?.slice(0, 50));
|
|
155
|
+
} catch (e) {
|
|
156
|
+
console.error("[bg-loop] Dispatch failed:", e.message);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
const short = content.replace(/\n+/g, " ").slice(0, 800).trim();
|
|
160
|
+
const isNoAction = /^NO_ACTION/i.test(short) || short.length < 10;
|
|
161
|
+
if (!isNoAction) {
|
|
162
|
+
_appendHistory("default", "owner", "system", `[crew-main — background]: ${short}`);
|
|
163
|
+
_broadcastSSE({ type: "agent_reply", from: "crew-main", content: short, sessionId: "owner", _bg: true, ts: Date.now() });
|
|
164
|
+
}
|
|
165
|
+
try {
|
|
166
|
+
const statusPath = path.join(os.homedir(), ".crewswarm", "process-status.md");
|
|
167
|
+
const stamp = new Date().toISOString().slice(0, 19).replace("T", " ");
|
|
168
|
+
fs.writeFileSync(statusPath, `# Process status (crew-main)\nLast updated: ${stamp}\n\n${content.slice(0, 2000).replace(/@@/g, "")}\n`, "utf8");
|
|
169
|
+
} catch (_) {}
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function backgroundLoop() {
|
|
174
|
+
try {
|
|
175
|
+
for (const [pid, pipeline] of _pendingPipelines) {
|
|
176
|
+
if (!pipeline._lastActivity) pipeline._lastActivity = Date.now();
|
|
177
|
+
const staleMs = Date.now() - pipeline._lastActivity;
|
|
178
|
+
if (staleMs > 15 * 60 * 1000 && pipeline.pendingTaskIds.size > 0) {
|
|
179
|
+
console.log(`[bg-loop] Pipeline ${pid} appears stalled (${Math.round(staleMs / 60000)}m no activity) — ${pipeline.pendingTaskIds.size} tasks pending`);
|
|
180
|
+
_broadcastSSE({ type: "pipeline_stalled", pipelineId: pid, staleMinutes: Math.round(staleMs / 60000), ts: Date.now() });
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
for (const [agent, count] of _agentTimeoutCounts) {
|
|
185
|
+
if (count >= 3) {
|
|
186
|
+
console.log(`[bg-loop] ⚠️ ${agent} has timed out ${count}x in last 24h — consider checking its model or restarting its bridge`);
|
|
187
|
+
_broadcastSSE({ type: "agent_timeout_pattern", agent, count, ts: Date.now() });
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (_pendingPipelines.size === 0) {
|
|
192
|
+
const projects = _readProjectsRegistry();
|
|
193
|
+
for (const project of projects) {
|
|
194
|
+
if (!project.outputDir || project.autoAdvance !== true) continue;
|
|
195
|
+
const nextPhase = _findNextRoadmapPhase(project.outputDir);
|
|
196
|
+
if (nextPhase) {
|
|
197
|
+
console.log(`[bg-loop] Auto-advancing "${project.name}" → "${nextPhase.title}"`);
|
|
198
|
+
_autoAdvanceRoadmap(project.outputDir, "owner");
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const bgEnabled = _getBgConsciousnessEnabled ? _getBgConsciousnessEnabled() : _bgConsciousnessEnabled;
|
|
203
|
+
if (bgEnabled && Date.now() - _lastBgConsciousnessAt >= _bgConsciousnessIntervalMs) {
|
|
204
|
+
_lastBgConsciousnessAt = Date.now();
|
|
205
|
+
const useDirect = getBgConsciousnessLLM();
|
|
206
|
+
if (useDirect) {
|
|
207
|
+
console.log("[bg-loop] Running background consciousness via", useDirect.providerKey + "/" + useDirect.modelId);
|
|
208
|
+
runBackgroundConsciousnessDirect().catch((e) => {
|
|
209
|
+
console.error("[bg-loop] Background consciousness error:", e.message);
|
|
210
|
+
});
|
|
211
|
+
} else {
|
|
212
|
+
const consciousnessTask = `BACKGROUND CYCLE — you are managing the process for the user. Your reply is shown in their chat and written to ~/.crewswarm/process-status.md.
|
|
213
|
+
@@READ_FILE ${_brainPath}
|
|
214
|
+
Consider: what should the user know? (stalled work, next steps, blockers, health.) Reply in under 100 words.
|
|
215
|
+
Reply with: 1) One sentence on system/crew state or suggested next step. 2) If something needs follow-up, emit exactly one @@BRAIN: or @@DISPATCH line (e.g. dispatch to fix a stuck pipeline). Otherwise reply NO_ACTION.`;
|
|
216
|
+
try {
|
|
217
|
+
_dispatchTask("crew-main", consciousnessTask, "bg-consciousness", null);
|
|
218
|
+
console.log("[bg-loop] Dispatched background consciousness cycle to crew-main (no cheap model configured)");
|
|
219
|
+
} catch (e) {
|
|
220
|
+
console.error("[bg-loop] Background consciousness dispatch failed:", e.message);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
} catch (e) {
|
|
226
|
+
console.error("[bg-loop] Error:", e.message);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export function startBackgroundLoop() {
|
|
231
|
+
if (_bgLoopInterval) clearInterval(_bgLoopInterval);
|
|
232
|
+
_bgLoopInterval = setInterval(backgroundLoop, 5 * 60 * 1000);
|
|
233
|
+
console.log("[crew-lead] Background loop started (5m interval)");
|
|
234
|
+
const bgEnabled = _getBgConsciousnessEnabled ? _getBgConsciousnessEnabled() : _bgConsciousnessEnabled;
|
|
235
|
+
if (bgEnabled) {
|
|
236
|
+
console.log("[crew-lead] Background consciousness ON — reflect every " + (_bgConsciousnessIntervalMs / 60000) + "m when idle");
|
|
237
|
+
} else {
|
|
238
|
+
console.log("[crew-lead] Background consciousness OFF — toggle in Dashboard → Settings");
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const _RATE_LIMIT_FALLBACK_STATIC = {
|
|
243
|
+
"crew-coder-back": "crew-coder",
|
|
244
|
+
"crew-coder-front": "crew-coder",
|
|
245
|
+
"crew-coder": "crew-main",
|
|
246
|
+
"crew-frontend": "crew-coder",
|
|
247
|
+
"crew-pm": "crew-main",
|
|
248
|
+
"crew-qa": "crew-main",
|
|
249
|
+
"crew-copywriter": "crew-main",
|
|
250
|
+
"crew-security": "crew-main",
|
|
251
|
+
};
|
|
252
|
+
const _ROLE_FALLBACK = {
|
|
253
|
+
coder: "crew-coder",
|
|
254
|
+
writer: "crew-copywriter",
|
|
255
|
+
researcher: "crew-main",
|
|
256
|
+
auditor: "crew-qa",
|
|
257
|
+
ops: "crew-main",
|
|
258
|
+
generalist: "crew-main",
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
export function getRateLimitFallback(agentId) {
|
|
262
|
+
if (_RATE_LIMIT_FALLBACK_STATIC[agentId]) return _RATE_LIMIT_FALLBACK_STATIC[agentId];
|
|
263
|
+
const swarm = _tryRead(path.join(os.homedir(), ".crewswarm", "crewswarm.json"));
|
|
264
|
+
const agent = (swarm?.agents || []).find(a => a.id === agentId);
|
|
265
|
+
if (agent?.fallbackModel) return agentId;
|
|
266
|
+
if (agent?._role && _ROLE_FALLBACK[agent._role]) return _ROLE_FALLBACK[agent._role];
|
|
267
|
+
return "crew-main";
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export const RATE_LIMIT_PATTERN = /429|rate\s*limit|throttl|quota\s*exceeded|too\s*many\s*requests|resource_exhausted|overloaded/i;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brain, global rules, and search helpers — extracted from crew-lead.mjs
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import os from "node:os";
|
|
8
|
+
import { execSync, spawnSync } from "node:child_process";
|
|
9
|
+
import { getSearchToolsConfig } from "../agents/permissions.mjs";
|
|
10
|
+
|
|
11
|
+
let _brainPath = "";
|
|
12
|
+
let _globalRulesPath = "";
|
|
13
|
+
|
|
14
|
+
export function initBrain({ brainPath, globalRulesPath }) {
|
|
15
|
+
if (brainPath !== undefined) _brainPath = brainPath;
|
|
16
|
+
if (globalRulesPath !== undefined) _globalRulesPath = globalRulesPath;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function appendToBrain(agentId, entry, projectDir = null) {
|
|
20
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
21
|
+
const block = `\n## [${date}] ${agentId}: ${entry}\n`;
|
|
22
|
+
if (projectDir) {
|
|
23
|
+
const projectBrainDir = path.join(projectDir, ".crewswarm");
|
|
24
|
+
const projectBrainPath = path.join(projectBrainDir, "brain.md");
|
|
25
|
+
fs.mkdirSync(projectBrainDir, { recursive: true });
|
|
26
|
+
if (!fs.existsSync(projectBrainPath)) {
|
|
27
|
+
fs.writeFileSync(projectBrainPath, "# Project Brain\n\nAccumulated knowledge for this project. Agents append discoveries here.\n", "utf8");
|
|
28
|
+
}
|
|
29
|
+
fs.appendFileSync(projectBrainPath, block, "utf8");
|
|
30
|
+
} else {
|
|
31
|
+
if (!fs.existsSync(_brainPath)) fs.mkdirSync(path.dirname(_brainPath), { recursive: true });
|
|
32
|
+
fs.appendFileSync(_brainPath, block, "utf8");
|
|
33
|
+
}
|
|
34
|
+
return block.trim();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function readGlobalRules() {
|
|
38
|
+
try { return fs.readFileSync(_globalRulesPath, "utf8").trim(); } catch { return ""; }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function writeGlobalRules(content) {
|
|
42
|
+
fs.writeFileSync(_globalRulesPath, content, "utf8");
|
|
43
|
+
return content;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function appendGlobalRule(rule) {
|
|
47
|
+
const existing = readGlobalRules();
|
|
48
|
+
const updated = existing ? `${existing}\n- ${rule}` : `# Global Agent Rules\n\n- ${rule}`;
|
|
49
|
+
writeGlobalRules(updated);
|
|
50
|
+
return updated;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export async function searchWithBrave(query) {
|
|
54
|
+
const key = getSearchToolsConfig()?.brave?.apiKey || process.env.BRAVE_API_KEY;
|
|
55
|
+
if (!key) return null;
|
|
56
|
+
try {
|
|
57
|
+
const res = await fetch(
|
|
58
|
+
`https://api.search.brave.com/res/v1/web/search?q=${encodeURIComponent(query)}&count=5&text_decorations=false`,
|
|
59
|
+
{ headers: { "Accept": "application/json", "X-Subscription-Token": key }, signal: AbortSignal.timeout(8000) }
|
|
60
|
+
);
|
|
61
|
+
if (!res.ok) return null;
|
|
62
|
+
const data = await res.json();
|
|
63
|
+
const results = (data.web?.results || []).slice(0, 5);
|
|
64
|
+
if (!results.length) return null;
|
|
65
|
+
const text = results.map((r, i) => `${i + 1}. ${r.title}\n ${r.description || ""}\n ${r.url}`).join("\n\n");
|
|
66
|
+
console.log(`[crew-lead] Brave search query="${query.slice(0, 80)}" → ${results.length} results`);
|
|
67
|
+
return text;
|
|
68
|
+
} catch { return null; }
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function getWorkspaceRoot() {
|
|
72
|
+
return process.env.CREW_LEAD_WORKSPACE || process.cwd();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Run a text search in the workspace; returns excerpt string or null. Uses rg then grep. */
|
|
76
|
+
export function searchCodebase(query) {
|
|
77
|
+
const workspace = getWorkspaceRoot();
|
|
78
|
+
if (!query || query.length < 2) return null;
|
|
79
|
+
const maxOutput = 6000;
|
|
80
|
+
const args = [
|
|
81
|
+
"-F", "-i", "-n",
|
|
82
|
+
"-C", "1",
|
|
83
|
+
"--max-files", "20",
|
|
84
|
+
"--max-count", "3",
|
|
85
|
+
"--glob", "!node_modules",
|
|
86
|
+
"--glob", "!.git",
|
|
87
|
+
"--glob", "!*.min.js",
|
|
88
|
+
query,
|
|
89
|
+
workspace,
|
|
90
|
+
];
|
|
91
|
+
try {
|
|
92
|
+
const out = spawnSync("rg", args, {
|
|
93
|
+
encoding: "utf8",
|
|
94
|
+
timeout: 5000,
|
|
95
|
+
maxBuffer: maxOutput,
|
|
96
|
+
windowsHide: true,
|
|
97
|
+
});
|
|
98
|
+
if (out.status !== 0 || !out.stdout?.trim()) return null;
|
|
99
|
+
const lines = out.stdout.trim().split("\n").slice(0, 25);
|
|
100
|
+
return lines.join("\n");
|
|
101
|
+
} catch {
|
|
102
|
+
try {
|
|
103
|
+
const out = execSync(
|
|
104
|
+
`grep -r -F -i -n --include="*.js" --include="*.mjs" --include="*.ts" --include="*.json" --include="*.md" -e ${JSON.stringify(query)} ${JSON.stringify(workspace)} 2>/dev/null | head -25`,
|
|
105
|
+
{ encoding: "utf8", timeout: 5000, maxBuffer: maxOutput }
|
|
106
|
+
);
|
|
107
|
+
return out?.trim() || null;
|
|
108
|
+
} catch { return null; }
|
|
109
|
+
}
|
|
110
|
+
}
|