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,232 @@
|
|
|
1
|
+
// Shared crewswarm agent registry.
|
|
2
|
+
// Dynamically loads agents from ~/.crewswarm/crewswarm.json so new agents
|
|
3
|
+
// are automatically discovered without code changes.
|
|
4
|
+
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import os from "node:os";
|
|
8
|
+
|
|
9
|
+
// Minimal built-in fallback for core coordinator agents
|
|
10
|
+
// Plus agents used in tests (so tests pass on CI without config file)
|
|
11
|
+
const CORE_AGENTS = [
|
|
12
|
+
"crew-main",
|
|
13
|
+
"crew-pm",
|
|
14
|
+
"crew-pm-cli",
|
|
15
|
+
"crew-pm-frontend",
|
|
16
|
+
"crew-pm-core",
|
|
17
|
+
"crew-orchestrator",
|
|
18
|
+
"crew-lead",
|
|
19
|
+
"crew-judge",
|
|
20
|
+
// Test agents (needed for CI)
|
|
21
|
+
"crew-coder",
|
|
22
|
+
"crew-coder-back",
|
|
23
|
+
"crew-coder-front",
|
|
24
|
+
"crew-researcher",
|
|
25
|
+
"crew-qa",
|
|
26
|
+
"crew-copywriter",
|
|
27
|
+
"crew-fixer",
|
|
28
|
+
"crew-github",
|
|
29
|
+
"crew-frontend",
|
|
30
|
+
"crew-security",
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
const CORE_MAP = {
|
|
34
|
+
"crew-main": "main",
|
|
35
|
+
"crew-pm": "pm",
|
|
36
|
+
"crew-pm-cli": "pm-cli",
|
|
37
|
+
"crew-pm-frontend": "pm-frontend",
|
|
38
|
+
"crew-pm-core": "pm-core",
|
|
39
|
+
"crew-orchestrator": "orchestrator",
|
|
40
|
+
"crew-lead": "lead",
|
|
41
|
+
"crew-judge": "judge",
|
|
42
|
+
// Test agents
|
|
43
|
+
"crew-coder": "coder",
|
|
44
|
+
"crew-coder-back": "coder-back",
|
|
45
|
+
"crew-coder-front": "coder-front",
|
|
46
|
+
"crew-researcher": "researcher",
|
|
47
|
+
"crew-qa": "qa",
|
|
48
|
+
"crew-copywriter": "copywriter",
|
|
49
|
+
"crew-fixer": "fixer",
|
|
50
|
+
"crew-github": "github",
|
|
51
|
+
"crew-frontend": "frontend",
|
|
52
|
+
"crew-security": "security",
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Build agent registry dynamically from config files.
|
|
57
|
+
* Reads ~/.crewswarm/crewswarm.json and discovers all configured agents.
|
|
58
|
+
*/
|
|
59
|
+
function buildAgentRegistry() {
|
|
60
|
+
const map = { ...CORE_MAP };
|
|
61
|
+
const listSet = new Set(CORE_AGENTS);
|
|
62
|
+
|
|
63
|
+
const cfgPaths = [
|
|
64
|
+
path.join(os.homedir(), ".crewswarm", "crewswarm.json"),
|
|
65
|
+
path.join(os.homedir(), ".openclaw", "openclaw.json"),
|
|
66
|
+
];
|
|
67
|
+
|
|
68
|
+
for (const cfgPath of cfgPaths) {
|
|
69
|
+
try {
|
|
70
|
+
const cfg = JSON.parse(fs.readFileSync(cfgPath, "utf8"));
|
|
71
|
+
const agents = Array.isArray(cfg.agents) ? cfg.agents
|
|
72
|
+
: Array.isArray(cfg.agents?.list) ? cfg.agents.list
|
|
73
|
+
: [];
|
|
74
|
+
|
|
75
|
+
for (const agent of agents) {
|
|
76
|
+
const rawId = String(agent.id || "").trim();
|
|
77
|
+
if (!rawId) continue;
|
|
78
|
+
|
|
79
|
+
// Normalize to RT format (crew-xxx)
|
|
80
|
+
const bareId = rawId.replace(/^crew-/, "");
|
|
81
|
+
const rtId = rawId.startsWith("crew-") ? rawId : `crew-${bareId}`;
|
|
82
|
+
|
|
83
|
+
// Always keep canonical RT IDs in the exported list
|
|
84
|
+
if (!map[rtId]) {
|
|
85
|
+
map[rtId] = bareId;
|
|
86
|
+
listSet.add(rtId);
|
|
87
|
+
}
|
|
88
|
+
// Support bare alias lookup (e.g. "orchestrator", "security")
|
|
89
|
+
// without adding duplicate non-RT IDs to BUILT_IN_RT_AGENTS.
|
|
90
|
+
if (rawId === bareId && !map[bareId]) {
|
|
91
|
+
map[bareId] = bareId;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
} catch (err) {
|
|
95
|
+
// Config file not found or invalid JSON — use core agents only
|
|
96
|
+
if (process.env.DEBUG) {
|
|
97
|
+
console.warn(`[agent-registry] Could not load ${cfgPath}: ${err.message}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return { list: [...listSet].sort(), map };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Build registry on module load
|
|
106
|
+
const { list, map } = buildAgentRegistry();
|
|
107
|
+
|
|
108
|
+
export const BUILT_IN_RT_AGENTS = list;
|
|
109
|
+
export const RT_TO_GATEWAY_AGENT_MAP = map;
|
|
110
|
+
|
|
111
|
+
// Core agents that MUST exist - system breaks if missing
|
|
112
|
+
export const REQUIRED_AGENTS = new Set([
|
|
113
|
+
"crew-lead", // Fatal: no chat handler, no dispatch
|
|
114
|
+
"crew-main", // Fatal: no synthesis, no fallback coordinator
|
|
115
|
+
"crew-pm", // Fatal: PM-loop breaks, no roadmap processing
|
|
116
|
+
"crew-orchestrator", // Fatal: pipeline dispatch fails
|
|
117
|
+
"crew-coder", // Fatal: PM-loop's default worker
|
|
118
|
+
"crew-judge" // Fatal: PM-loop judge decisions fail (if PM_USE_JUDGE=on)
|
|
119
|
+
]);
|
|
120
|
+
|
|
121
|
+
// Coordinator agents that can dispatch to other agents
|
|
122
|
+
export const COORDINATOR_AGENT_IDS = [
|
|
123
|
+
"crew-main",
|
|
124
|
+
"crew-pm",
|
|
125
|
+
"crew-pm-cli",
|
|
126
|
+
"crew-pm-frontend",
|
|
127
|
+
"crew-pm-core",
|
|
128
|
+
"crew-orchestrator"
|
|
129
|
+
];
|
|
130
|
+
|
|
131
|
+
// Backward-compatible alias for a misspelled import introduced by recent edits.
|
|
132
|
+
export const coordinate_aget_ids = COORDINATOR_AGENT_IDS;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Agents whose tasks assume the configured engine runs (read_file / write_file / git / CLI).
|
|
136
|
+
* If Codex/Cursor/OpenCode fails, we must NOT silently fall back to direct LLM — the user would
|
|
137
|
+
* get prose with no qa-report.md, no audits, etc.
|
|
138
|
+
*/
|
|
139
|
+
export const AGENTS_NO_ENGINE_LLM_FALLBACK = new Set([
|
|
140
|
+
"crew-coder",
|
|
141
|
+
"crew-coder-back",
|
|
142
|
+
"crew-coder-front",
|
|
143
|
+
"crew-frontend",
|
|
144
|
+
"crew-fixer",
|
|
145
|
+
"crew-architect",
|
|
146
|
+
"crew-qa",
|
|
147
|
+
"crew-security",
|
|
148
|
+
"crew-github",
|
|
149
|
+
"crew-copywriter",
|
|
150
|
+
"crew-researcher",
|
|
151
|
+
"crew-seo",
|
|
152
|
+
"crew-ml",
|
|
153
|
+
"crew-mega",
|
|
154
|
+
"crew-pm",
|
|
155
|
+
"crew-pm-cli",
|
|
156
|
+
"crew-pm-frontend",
|
|
157
|
+
"crew-pm-core",
|
|
158
|
+
"crew-orchestrator",
|
|
159
|
+
]);
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* True when engine failure should surface an error instead of LLM-only fallback (rt-envelope).
|
|
163
|
+
* @param {string} agentId
|
|
164
|
+
* @returns {boolean}
|
|
165
|
+
*/
|
|
166
|
+
export function agentMustNotUseEngineLlmFallback(agentId = "") {
|
|
167
|
+
const id = normalizeRtAgentId(String(agentId || "").trim());
|
|
168
|
+
if (!id) return false;
|
|
169
|
+
if (AGENTS_NO_ENGINE_LLM_FALLBACK.has(id)) return true;
|
|
170
|
+
// Dynamic coding-style workers
|
|
171
|
+
if (/^crew-[\w-]*(coder|fixer)(-|$)/i.test(id)) return true;
|
|
172
|
+
if (/^crew-[\w-]*frontend(-|$)/i.test(id)) return true;
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Check if an agent ID is a coordinator (can dispatch to other agents)
|
|
178
|
+
* Handles both RT format (crew-xxx) and bare aliases (xxx)
|
|
179
|
+
* @param {string} agentId - Agent ID to check
|
|
180
|
+
* @returns {boolean} True if agent is a coordinator
|
|
181
|
+
*/
|
|
182
|
+
export function isCoordinator(agentId = "") {
|
|
183
|
+
const id = String(agentId || "").trim();
|
|
184
|
+
if (!id) return false;
|
|
185
|
+
|
|
186
|
+
// Check RT format directly
|
|
187
|
+
if (COORDINATOR_AGENT_IDS.includes(id)) return true;
|
|
188
|
+
|
|
189
|
+
// Check bare alias by normalizing to RT format
|
|
190
|
+
const rtId = normalizeRtAgentId(id);
|
|
191
|
+
return COORDINATOR_AGENT_IDS.includes(rtId);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Validate that all required agents exist in config
|
|
196
|
+
* @param {Array} agents - Agent list from config
|
|
197
|
+
* @returns {Object} { valid: boolean, missing: string[] }
|
|
198
|
+
*/
|
|
199
|
+
export function validateRequiredAgents(agents = []) {
|
|
200
|
+
const agentIds = new Set(
|
|
201
|
+
agents
|
|
202
|
+
.map((a) => normalizeRtAgentId(a?.id))
|
|
203
|
+
.filter(Boolean)
|
|
204
|
+
);
|
|
205
|
+
const missing = [];
|
|
206
|
+
|
|
207
|
+
for (const required of REQUIRED_AGENTS) {
|
|
208
|
+
if (!agentIds.has(required)) {
|
|
209
|
+
missing.push(required);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return {
|
|
214
|
+
valid: missing.length === 0,
|
|
215
|
+
missing
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Agents that don't get "crew-" prefix normalization
|
|
220
|
+
export const NO_PREFIX_AGENT_IDS = new Set(["security"]);
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Normalize agent ID to RT format (crew-xxx).
|
|
224
|
+
* @param {string} agentId - Raw agent ID
|
|
225
|
+
* @returns {string} Normalized RT agent ID
|
|
226
|
+
*/
|
|
227
|
+
export function normalizeRtAgentId(agentId = "") {
|
|
228
|
+
const id = String(agentId || "").trim();
|
|
229
|
+
if (!id) return "";
|
|
230
|
+
if (id.startsWith("crew-") || NO_PREFIX_AGENT_IDS.has(id)) return id;
|
|
231
|
+
return `crew-${id}`;
|
|
232
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent daemon utilities — spawn, PID, heartbeat, resolve spawn targets.
|
|
3
|
+
* Extracted from gateway-bridge.mjs.
|
|
4
|
+
* Dependencies: fs, path, os, spawn from child_process
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import fs from "node:fs";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
import { spawn } from "node:child_process";
|
|
10
|
+
import {
|
|
11
|
+
SWARM_RUNTIME_DIR,
|
|
12
|
+
SWARM_STATUS_LOG,
|
|
13
|
+
CREWSWARM_RT_CHANNELS,
|
|
14
|
+
CREWSWARM_REPO_ROOT,
|
|
15
|
+
} from "../runtime/config.mjs";
|
|
16
|
+
import { CREWSWARM_RT_SWARM_AGENTS } from "./registry.mjs";
|
|
17
|
+
|
|
18
|
+
function agentRuntimeDir() {
|
|
19
|
+
const dir = path.join(SWARM_RUNTIME_DIR, "rt-agents");
|
|
20
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
21
|
+
return dir;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function agentPidPath(agent) {
|
|
25
|
+
return path.join(agentRuntimeDir(), `${agent}.pid`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function agentLogPath(agent) {
|
|
29
|
+
return path.join(agentRuntimeDir(), `${agent}.log`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function readPid(agent) {
|
|
33
|
+
try {
|
|
34
|
+
return Number(fs.readFileSync(agentPidPath(agent), "utf8").trim());
|
|
35
|
+
} catch {
|
|
36
|
+
return 0;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function isPidAlive(pid) {
|
|
41
|
+
if (!pid || Number.isNaN(pid)) return false;
|
|
42
|
+
try {
|
|
43
|
+
process.kill(pid, 0);
|
|
44
|
+
return true;
|
|
45
|
+
} catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function latestHeartbeatAgeSec(agent) {
|
|
51
|
+
try {
|
|
52
|
+
if (!fs.existsSync(SWARM_STATUS_LOG)) return null;
|
|
53
|
+
const lines = fs.readFileSync(SWARM_STATUS_LOG, "utf8").split("\n");
|
|
54
|
+
for (let i = lines.length - 1; i >= 0; i -= 1) {
|
|
55
|
+
const line = lines[i].trim();
|
|
56
|
+
if (!line) continue;
|
|
57
|
+
let row;
|
|
58
|
+
try { row = JSON.parse(line); } catch { continue; }
|
|
59
|
+
if (row?.type !== "agent.heartbeat") continue;
|
|
60
|
+
const hbAgent = row?.payload?.agent || row?.from;
|
|
61
|
+
if (hbAgent !== agent) continue;
|
|
62
|
+
const ts = Date.parse(row?.ts || "");
|
|
63
|
+
if (!Number.isFinite(ts)) return null;
|
|
64
|
+
return (Date.now() - ts) / 1000;
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
} catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function isAgentDaemonRunning(agent) {
|
|
73
|
+
const SWARM_HEARTBEAT_WINDOW_SEC = Number(process.env.CREWSWARM_RT_HEARTBEAT_WINDOW_SEC || "90");
|
|
74
|
+
const heartbeatAge = latestHeartbeatAgeSec(agent);
|
|
75
|
+
if (heartbeatAge !== null && heartbeatAge <= SWARM_HEARTBEAT_WINDOW_SEC) return true;
|
|
76
|
+
const pid = readPid(agent);
|
|
77
|
+
if (isPidAlive(pid)) return true;
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function spawnAgentDaemon(agent) {
|
|
82
|
+
if (isAgentDaemonRunning(agent)) {
|
|
83
|
+
return { agent, status: "already_running" };
|
|
84
|
+
}
|
|
85
|
+
const logFile = agentLogPath(agent);
|
|
86
|
+
const out = fs.openSync(logFile, "a");
|
|
87
|
+
const child = spawn(
|
|
88
|
+
process.execPath,
|
|
89
|
+
[path.join(CREWSWARM_REPO_ROOT, "gateway-bridge.mjs"), "--rt-daemon"],
|
|
90
|
+
{
|
|
91
|
+
cwd: CREWSWARM_REPO_ROOT,
|
|
92
|
+
detached: true,
|
|
93
|
+
stdio: ["ignore", out, out],
|
|
94
|
+
env: {
|
|
95
|
+
...process.env,
|
|
96
|
+
CREWSWARM_RT_AGENT: agent,
|
|
97
|
+
CREWSWARM_RT_CHANNELS,
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
);
|
|
101
|
+
child.unref();
|
|
102
|
+
fs.writeFileSync(agentPidPath(agent), `${child.pid}`);
|
|
103
|
+
return { agent, status: "started", pid: child.pid, logFile };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function resolveSpawnTargets(payload) {
|
|
107
|
+
const all = [...new Set(CREWSWARM_RT_SWARM_AGENTS)];
|
|
108
|
+
if (Array.isArray(payload?.agents)) {
|
|
109
|
+
const agents = payload.agents.map((a) => String(a).trim()).filter(Boolean);
|
|
110
|
+
return agents.length ? agents : all;
|
|
111
|
+
}
|
|
112
|
+
if (typeof payload?.agent === "string" && payload.agent.trim()) {
|
|
113
|
+
if (payload.agent.trim().toLowerCase() === "all") return all;
|
|
114
|
+
return [payload.agent.trim()];
|
|
115
|
+
}
|
|
116
|
+
if (typeof payload?.target === "string" && payload.target.trim()) {
|
|
117
|
+
if (payload.target.trim().toLowerCase() === "all") return all;
|
|
118
|
+
return [payload.target.trim()];
|
|
119
|
+
}
|
|
120
|
+
return all;
|
|
121
|
+
}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dispatch guard, task lease, and task helpers — extracted from gateway-bridge.mjs.
|
|
3
|
+
* File-based lease and done records for dispatch deduplication.
|
|
4
|
+
* Dependencies: fs, path, crypto
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import fs from "node:fs";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
import crypto from "node:crypto";
|
|
10
|
+
import {
|
|
11
|
+
SWARM_DISPATCH_DIR,
|
|
12
|
+
CREWSWARM_RT_AGENT,
|
|
13
|
+
CREWSWARM_RT_TASK_STATE_TTL_MS,
|
|
14
|
+
CREWSWARM_RT_DISPATCH_ENABLED,
|
|
15
|
+
} from "../runtime/config.mjs";
|
|
16
|
+
|
|
17
|
+
function transientError(err) {
|
|
18
|
+
const msg = String(err?.message ?? err ?? "").toLowerCase();
|
|
19
|
+
return ["timeout", "timed out", "econnrefused", "ehostunreach", "econnreset", "socket hang up", "websocket is not open", "connection closed", "broken pipe"].some((s) => msg.includes(s));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function ensureDispatchDir() {
|
|
23
|
+
fs.mkdirSync(SWARM_DISPATCH_DIR, { recursive: true });
|
|
24
|
+
return SWARM_DISPATCH_DIR;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function safeReadJson(filePath) {
|
|
28
|
+
try {
|
|
29
|
+
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
30
|
+
} catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function isoNow() {
|
|
36
|
+
return new Date().toISOString();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function dispatchKeyForTask({ taskId, incomingType, prompt, idempotencyKey }) {
|
|
40
|
+
const stableTaskId = String(taskId || "").trim();
|
|
41
|
+
if (stableTaskId) return `task-${stableTaskId}`;
|
|
42
|
+
const stableIdempotency = String(idempotencyKey || "").trim();
|
|
43
|
+
if (stableIdempotency) return `idem-${stableIdempotency}`;
|
|
44
|
+
const hash = crypto.createHash("sha256")
|
|
45
|
+
.update(`${incomingType || "event"}\n${prompt || ""}`, "utf8")
|
|
46
|
+
.digest("hex")
|
|
47
|
+
.slice(0, 24);
|
|
48
|
+
return `hash-${hash}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function leasePathForKey(key) {
|
|
52
|
+
return path.join(ensureDispatchDir(), `${key}.lease`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function donePathForKey(key) {
|
|
56
|
+
return path.join(ensureDispatchDir(), `${key}.done.json`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function readTaskDoneRecord(key) {
|
|
60
|
+
return safeReadJson(donePathForKey(key));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function isDoneRecordFresh(record) {
|
|
64
|
+
if (!record?.doneAt) return false;
|
|
65
|
+
const doneAtMs = Date.parse(record.doneAt);
|
|
66
|
+
if (!Number.isFinite(doneAtMs)) return false;
|
|
67
|
+
return (Date.now() - doneAtMs) <= CREWSWARM_RT_TASK_STATE_TTL_MS;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function readLeaseRecord(leaseDir) {
|
|
71
|
+
return safeReadJson(path.join(leaseDir, "lease.json"));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function writeLeaseRecord(leaseDir, leaseRecord) {
|
|
75
|
+
fs.writeFileSync(path.join(leaseDir, "lease.json"), JSON.stringify(leaseRecord, null, 2));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function acquireTaskLease({ key, source, incomingType, from, leaseMs }) {
|
|
79
|
+
const leaseDir = leasePathForKey(key);
|
|
80
|
+
const donePath = donePathForKey(key);
|
|
81
|
+
const doneRecord = readTaskDoneRecord(key);
|
|
82
|
+
if (doneRecord) {
|
|
83
|
+
if (isDoneRecordFresh(doneRecord)) {
|
|
84
|
+
return { acquired: false, reason: "already_done", doneRecord };
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
fs.rmSync(donePath, { force: true });
|
|
88
|
+
} catch {}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const now = Date.now();
|
|
92
|
+
const claimId = `${CREWSWARM_RT_AGENT}-${process.pid}-${crypto.randomUUID()}`;
|
|
93
|
+
const leaseRecord = {
|
|
94
|
+
key,
|
|
95
|
+
claimId,
|
|
96
|
+
agent: CREWSWARM_RT_AGENT,
|
|
97
|
+
source,
|
|
98
|
+
from,
|
|
99
|
+
incomingType,
|
|
100
|
+
leaseMs,
|
|
101
|
+
leasedAt: isoNow(),
|
|
102
|
+
leaseExpiresAt: new Date(now + leaseMs).toISOString(),
|
|
103
|
+
updatedAt: isoNow(),
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const writeNewLease = () => {
|
|
107
|
+
fs.mkdirSync(leaseDir);
|
|
108
|
+
writeLeaseRecord(leaseDir, leaseRecord);
|
|
109
|
+
return { acquired: true, claimId, leaseDir };
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
return writeNewLease();
|
|
114
|
+
} catch (err) {
|
|
115
|
+
if (err?.code !== "EEXIST") throw err;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const existing = readLeaseRecord(leaseDir);
|
|
119
|
+
const existingExpiry = Date.parse(existing?.leaseExpiresAt || "");
|
|
120
|
+
if (Number.isFinite(existingExpiry) && existingExpiry > now) {
|
|
121
|
+
return {
|
|
122
|
+
acquired: false,
|
|
123
|
+
reason: "claimed",
|
|
124
|
+
claimedBy: existing?.agent || "unknown",
|
|
125
|
+
leaseExpiresAt: existing?.leaseExpiresAt || null,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
try {
|
|
130
|
+
fs.rmSync(leaseDir, { recursive: true, force: true });
|
|
131
|
+
return writeNewLease();
|
|
132
|
+
} catch {
|
|
133
|
+
return {
|
|
134
|
+
acquired: false,
|
|
135
|
+
reason: "claimed",
|
|
136
|
+
claimedBy: existing?.agent || "unknown",
|
|
137
|
+
leaseExpiresAt: existing?.leaseExpiresAt || null,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function renewTaskLease({ key, claimId, leaseMs }) {
|
|
143
|
+
const leaseDir = leasePathForKey(key);
|
|
144
|
+
const current = readLeaseRecord(leaseDir);
|
|
145
|
+
if (!current || current.claimId !== claimId || current.agent !== CREWSWARM_RT_AGENT) return false;
|
|
146
|
+
const now = Date.now();
|
|
147
|
+
current.updatedAt = isoNow();
|
|
148
|
+
current.leaseMs = leaseMs;
|
|
149
|
+
current.leaseExpiresAt = new Date(now + leaseMs).toISOString();
|
|
150
|
+
writeLeaseRecord(leaseDir, current);
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function releaseTaskLease({ key, claimId }) {
|
|
155
|
+
const leaseDir = leasePathForKey(key);
|
|
156
|
+
try {
|
|
157
|
+
const current = readLeaseRecord(leaseDir);
|
|
158
|
+
if (!current || current.claimId !== claimId || current.agent !== CREWSWARM_RT_AGENT) return false;
|
|
159
|
+
fs.rmSync(leaseDir, { recursive: true, force: true });
|
|
160
|
+
return true;
|
|
161
|
+
} catch {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function markTaskDone({ key, claimId, taskId, incomingType, from, attempt, idempotencyKey, reply }) {
|
|
167
|
+
const donePath = donePathForKey(key);
|
|
168
|
+
const replyText = String(reply || "");
|
|
169
|
+
const doneRecord = {
|
|
170
|
+
key,
|
|
171
|
+
taskId,
|
|
172
|
+
incomingType,
|
|
173
|
+
from,
|
|
174
|
+
claimId,
|
|
175
|
+
idempotencyKey,
|
|
176
|
+
agent: CREWSWARM_RT_AGENT,
|
|
177
|
+
attempt,
|
|
178
|
+
reply: replyText.slice(0, 24000),
|
|
179
|
+
replyHash: crypto.createHash("sha256").update(replyText, "utf8").digest("hex"),
|
|
180
|
+
doneAt: isoNow(),
|
|
181
|
+
};
|
|
182
|
+
fs.writeFileSync(donePath, JSON.stringify(doneRecord, null, 2));
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export function shouldUseDispatchGuard(incomingType) {
|
|
186
|
+
if (!CREWSWARM_RT_DISPATCH_ENABLED) return false;
|
|
187
|
+
return incomingType === "command.run_task" || incomingType === "task.assigned" || incomingType === "task.reassigned";
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export function shouldRetryTaskFailure(err) {
|
|
191
|
+
const msg = String(err?.message ?? err ?? "");
|
|
192
|
+
if (!msg) return false;
|
|
193
|
+
if (msg.includes("MEMORY_PROTOCOL_MISSING") || msg.includes("MEMORY_LOAD_FAILED")) return false;
|
|
194
|
+
if (msg.includes("CODING_ARTIFACT_MISSING")) return true;
|
|
195
|
+
return transientError(err) || msg.toLowerCase().includes("timeout");
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function isCodingTask(incomingType, prompt, payload) {
|
|
199
|
+
if (!incomingType) return false;
|
|
200
|
+
const codingTypes = ["command.run_task", "task.assigned", "task.reassigned"];
|
|
201
|
+
if (!codingTypes.includes(incomingType)) return false;
|
|
202
|
+
|
|
203
|
+
const action = String(payload?.action || "").toLowerCase();
|
|
204
|
+
if (action === "collect_status" || action === "status" || action === "heartbeat") return false;
|
|
205
|
+
|
|
206
|
+
const text = String(prompt || "").toLowerCase();
|
|
207
|
+
if (text.includes("report status") || text.includes("reply with agent id")) return false;
|
|
208
|
+
if (text.includes("busy/idle") || text.includes("active task")) return false;
|
|
209
|
+
|
|
210
|
+
const codingKeywords = [
|
|
211
|
+
"implement", "build", "create", "fix", "refactor", "add", "update", "modify",
|
|
212
|
+
"code", "function", "class", "component", "api", "endpoint", "route", "test",
|
|
213
|
+
"bug", "error", "issue", "file", "script", "module", "package"
|
|
214
|
+
];
|
|
215
|
+
return codingKeywords.some(kw => text.includes(kw));
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export function looksLikeCodingTask(prompt = "") {
|
|
219
|
+
const p = String(prompt).toLowerCase();
|
|
220
|
+
return [
|
|
221
|
+
"implement", "write code", "refactor", "fix bug", "unit test", "integration test",
|
|
222
|
+
"build", "compile", "typescript", "javascript", "python", "go ", "rust",
|
|
223
|
+
"repo", "pull request", "pr ", "commit", "lint", "migrate",
|
|
224
|
+
].some((kw) => p.includes(kw));
|
|
225
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent tool permission helpers — extracted from crew-lead.mjs
|
|
3
|
+
* Reads/writes per-agent tool permissions from crewswarm.json.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import fs from "fs";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import os from "os";
|
|
9
|
+
import { applySharedChatPromptOverlay } from "../chat/shared-chat-prompt-overlay.mjs";
|
|
10
|
+
|
|
11
|
+
function tryRead(p) {
|
|
12
|
+
try { return JSON.parse(fs.readFileSync(p, "utf8")); } catch { return null; }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const CREWSWARM_TOOL_NAMES = new Set([
|
|
16
|
+
"write_file","read_file","mkdir","run_cmd","git","dispatch","telegram","web_search","web_fetch","skill","define_skill","browser",
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
export const AGENT_TOOL_ROLE_DEFAULTS = {
|
|
20
|
+
"crew-qa": ["read_file"],
|
|
21
|
+
"crew-security": ["read_file","run_cmd"],
|
|
22
|
+
"crew-coder": ["write_file","read_file","mkdir","run_cmd","browser"],
|
|
23
|
+
"crew-coder-front": ["write_file","read_file","mkdir","run_cmd","browser"],
|
|
24
|
+
"crew-coder-back": ["write_file","read_file","mkdir","run_cmd","browser"],
|
|
25
|
+
"crew-frontend": ["write_file","read_file","mkdir","run_cmd"],
|
|
26
|
+
"crew-fixer": ["write_file","read_file","mkdir","run_cmd","browser"],
|
|
27
|
+
"crew-github": ["read_file","run_cmd","git"],
|
|
28
|
+
"crew-copywriter": ["write_file","read_file","web_search","web_fetch"],
|
|
29
|
+
"crew-main": ["write_file","read_file","mkdir","run_cmd","dispatch","web_search","web_fetch"],
|
|
30
|
+
"crew-pm": ["read_file","dispatch"],
|
|
31
|
+
"crew-telegram": ["telegram","read_file"],
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export function readAgentTools(agentId) {
|
|
35
|
+
const swarm = tryRead(path.join(os.homedir(), ".crewswarm", "crewswarm.json")) || {};
|
|
36
|
+
const agents = Array.isArray(swarm.agents) ? swarm.agents : [];
|
|
37
|
+
const agent = agents.find(a => a.id === agentId);
|
|
38
|
+
const exact = AGENT_TOOL_ROLE_DEFAULTS[agentId];
|
|
39
|
+
const roleDefaults = exact || Object.entries(AGENT_TOOL_ROLE_DEFAULTS).find(([key]) => agentId.startsWith(key))?.[1] || [];
|
|
40
|
+
const explicit = agent?.tools?.crewswarmAllow || agent?.tools?.alsoAllow || null;
|
|
41
|
+
if (explicit) {
|
|
42
|
+
const valid = explicit.filter(t => CREWSWARM_TOOL_NAMES.has(t));
|
|
43
|
+
if (valid.length) return { source: "config", tools: [...new Set([...roleDefaults, ...valid])] };
|
|
44
|
+
}
|
|
45
|
+
if (roleDefaults.length) return { source: "role-default", tools: roleDefaults };
|
|
46
|
+
return { source: "fallback", tools: ["read_file","write_file","mkdir","run_cmd"] };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function writeAgentTools(agentId, tools) {
|
|
50
|
+
const valid = tools.filter(t => CREWSWARM_TOOL_NAMES.has(t));
|
|
51
|
+
const swarmPath = path.join(os.homedir(), ".crewswarm", "crewswarm.json");
|
|
52
|
+
const swarm = tryRead(swarmPath) || {};
|
|
53
|
+
if (!Array.isArray(swarm.agents)) swarm.agents = [];
|
|
54
|
+
let agent = swarm.agents.find(a => a.id === agentId);
|
|
55
|
+
if (!agent) {
|
|
56
|
+
agent = { id: agentId };
|
|
57
|
+
swarm.agents.push(agent);
|
|
58
|
+
}
|
|
59
|
+
if (!agent.tools) agent.tools = {};
|
|
60
|
+
agent.tools.crewswarmAllow = valid;
|
|
61
|
+
fs.writeFileSync(swarmPath, JSON.stringify(swarm, null, 2), "utf8");
|
|
62
|
+
return valid;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function getSearchToolsConfig() {
|
|
66
|
+
return tryRead(path.join(os.homedir(), ".crewswarm", "search-tools.json")) || {};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function getRawAgentPrompts() {
|
|
70
|
+
return (
|
|
71
|
+
tryRead(path.join(os.homedir(), ".crewswarm", "agent-prompts.json")) || {}
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function getAgentPrompts() {
|
|
76
|
+
const prompts = getRawAgentPrompts();
|
|
77
|
+
const augmented = {};
|
|
78
|
+
for (const [key, value] of Object.entries(prompts)) {
|
|
79
|
+
augmented[key] = applySharedChatPromptOverlay(value, key);
|
|
80
|
+
}
|
|
81
|
+
return augmented;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function writeAgentPrompt(agentId, promptText) {
|
|
85
|
+
const promptsPath = path.join(os.homedir(), ".crewswarm", "agent-prompts.json");
|
|
86
|
+
const prompts = getRawAgentPrompts();
|
|
87
|
+
prompts[agentId] = promptText;
|
|
88
|
+
fs.writeFileSync(promptsPath, JSON.stringify(prompts, null, 2), "utf8");
|
|
89
|
+
return promptText;
|
|
90
|
+
}
|