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,388 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime config constants and path definitions — extracted from gateway-bridge.mjs.
|
|
3
|
+
* Dependencies: fs, path, os, crypto
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {{ apiKey?: string, baseUrl?: string }} ProviderConfig
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {{
|
|
12
|
+
* id: string,
|
|
13
|
+
* model?: string,
|
|
14
|
+
* role?: string,
|
|
15
|
+
* fallbackModel?: string,
|
|
16
|
+
* useCrewCLI?: boolean,
|
|
17
|
+
* engine?: string,
|
|
18
|
+
* identity?: { name?: string, emoji?: string, theme?: string },
|
|
19
|
+
* name?: string,
|
|
20
|
+
* emoji?: string
|
|
21
|
+
* }} AgentConfig
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @typedef {{
|
|
26
|
+
* rt?: { authToken?: string },
|
|
27
|
+
* claudeCode?: boolean,
|
|
28
|
+
* cursorWaves?: boolean,
|
|
29
|
+
* bgConsciousness?: boolean,
|
|
30
|
+
* bgConsciousnessModel?: string,
|
|
31
|
+
* providers?: Record<string, ProviderConfig>,
|
|
32
|
+
* loopBrain?: string,
|
|
33
|
+
* env?: Record<string, string>
|
|
34
|
+
* }} SystemConfig
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @typedef {{
|
|
39
|
+
* agents?: AgentConfig[],
|
|
40
|
+
* providers?: Record<string, ProviderConfig>,
|
|
41
|
+
* env?: Record<string, string>,
|
|
42
|
+
* codex?: boolean,
|
|
43
|
+
* globalFallbackModel?: string
|
|
44
|
+
* }} SwarmConfig
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
import fs from "node:fs";
|
|
48
|
+
import path from "node:path";
|
|
49
|
+
import os from "node:os";
|
|
50
|
+
import crypto from "node:crypto";
|
|
51
|
+
import { fileURLToPath } from "node:url";
|
|
52
|
+
|
|
53
|
+
// ── Path constants ─────────────────────────────────────────────────────────
|
|
54
|
+
/** Repo root of this checkout (`lib/runtime` → `../..`). Not `process.cwd()` — crew-lead may start from any cwd. */
|
|
55
|
+
const _RUNTIME_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
56
|
+
export const CREWSWARM_REPO_ROOT =
|
|
57
|
+
(process.env.CREWSWARM_REPO_ROOT && String(process.env.CREWSWARM_REPO_ROOT).trim())
|
|
58
|
+
? path.resolve(process.env.CREWSWARM_REPO_ROOT)
|
|
59
|
+
: path.resolve(_RUNTIME_DIR, "..", "..");
|
|
60
|
+
|
|
61
|
+
export const LEGACY_STATE_DIR = path.join(os.homedir(), ".openclaw");
|
|
62
|
+
export const CREWSWARM_DIR = path.join(os.homedir(), ".crewswarm");
|
|
63
|
+
export const CREWSWARM_CONFIG_PATH = path.join(CREWSWARM_DIR, "config.json");
|
|
64
|
+
export const CREWSWARM_SWARM_PATH = path.join(CREWSWARM_DIR, "crewswarm.json");
|
|
65
|
+
export const TELEGRAM_BRIDGE_CONFIG_PATH = path.join(CREWSWARM_DIR, "telegram-bridge.json");
|
|
66
|
+
export const TELEMETRY_DIR = path.join(LEGACY_STATE_DIR, "telemetry");
|
|
67
|
+
|
|
68
|
+
// ── Unified config readers ────────────────────────────────────────────────
|
|
69
|
+
// Single source of truth for reading the two JSON config files.
|
|
70
|
+
// Every module should use these instead of inline readFileSync calls.
|
|
71
|
+
|
|
72
|
+
function _tryReadJSON(filePath) {
|
|
73
|
+
try {
|
|
74
|
+
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
75
|
+
} catch (err) {
|
|
76
|
+
if (err.code === "ENOENT") return null; // file doesn't exist yet — normal on first run
|
|
77
|
+
// Surface parse errors and permission issues so users don't get silent zero-config
|
|
78
|
+
console.error(`[config] Failed to read ${filePath}: ${err.message}`);
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Read ~/.crewswarm/crewswarm.json (system/dashboard config)
|
|
85
|
+
* Contains: rt.authToken, claudeCode, providers, opencodeFallbackModel, etc.
|
|
86
|
+
* @returns {SystemConfig}
|
|
87
|
+
*/
|
|
88
|
+
export function loadSystemConfig() {
|
|
89
|
+
return _tryReadJSON(CREWSWARM_CONFIG_PATH) || {};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Read ~/.crewswarm/crewswarm.json (agent definitions, providers, env)
|
|
94
|
+
* Contains: agents[], providers{}, env{}, globalFallbackModel, etc.
|
|
95
|
+
* @returns {SwarmConfig}
|
|
96
|
+
*/
|
|
97
|
+
export function loadSwarmConfig() {
|
|
98
|
+
return _tryReadJSON(CREWSWARM_SWARM_PATH) || {};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Load agent list from crewswarm.json (with legacy fallback)
|
|
103
|
+
* Returns the agents array — the most commonly needed config value.
|
|
104
|
+
* @returns {AgentConfig[]}
|
|
105
|
+
*/
|
|
106
|
+
export function loadAgentList() {
|
|
107
|
+
const swarm = loadSwarmConfig();
|
|
108
|
+
const agents = Array.isArray(swarm.agents) ? swarm.agents
|
|
109
|
+
: Array.isArray(swarm.agents?.list) ? swarm.agents.list
|
|
110
|
+
: [];
|
|
111
|
+
return agents;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Resolve a provider config by key (checks both config files)
|
|
116
|
+
* @param {string} providerKey - e.g. "groq", "google", "anthropic"
|
|
117
|
+
* @returns {ProviderConfig | null}
|
|
118
|
+
*/
|
|
119
|
+
export function resolveProvider(providerKey) {
|
|
120
|
+
const swarm = loadSwarmConfig();
|
|
121
|
+
const sys = loadSystemConfig();
|
|
122
|
+
return swarm?.providers?.[providerKey] || sys?.providers?.[providerKey] || null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ── Built-in provider base URLs — users only need to supply apiKey ──────────
|
|
126
|
+
export const PROVIDER_REGISTRY = {
|
|
127
|
+
groq: { baseUrl: "https://api.groq.com/openai/v1" },
|
|
128
|
+
fireworks: { baseUrl: "https://api.fireworks.ai/inference/v1" },
|
|
129
|
+
anthropic: { baseUrl: "https://api.anthropic.com/v1" },
|
|
130
|
+
openai: { baseUrl: "https://api.openai.com/v1" },
|
|
131
|
+
perplexity: { baseUrl: "https://api.perplexity.ai" },
|
|
132
|
+
mistral: { baseUrl: "https://api.mistral.ai/v1" },
|
|
133
|
+
deepseek: { baseUrl: "https://api.deepseek.com/v1" },
|
|
134
|
+
together: { baseUrl: "https://api.together.xyz/v1" },
|
|
135
|
+
nvidia: { baseUrl: "https://integrate.api.nvidia.com/v1" },
|
|
136
|
+
google: { baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai" },
|
|
137
|
+
xai: { baseUrl: "https://api.x.ai/v1" },
|
|
138
|
+
ollama: { baseUrl: "http://localhost:11434/v1" },
|
|
139
|
+
openrouter: { baseUrl: "https://openrouter.ai/api/v1" },
|
|
140
|
+
"openai-compatible": { baseUrl: null }, // user must supply baseUrl
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// ── Memory / RT constants ────────────────────────────────────────────────────
|
|
144
|
+
export const MEMORY_BOOTSTRAP_AGENT = "gateway-bridge";
|
|
145
|
+
export const GATEWAY_URL = "ws://127.0.0.1:18889";
|
|
146
|
+
|
|
147
|
+
// MEMORY_PROTOCOL_MARKER is used with getLastHandoffTimestamp — must be a fn that returns the full protocol
|
|
148
|
+
// For config export we only need the marker string; the full SHARED_MEMORY_PROTOCOL is built in memory.mjs
|
|
149
|
+
export const MEMORY_PROTOCOL_MARKER = "Mandatory memory protocol (apply for this task):";
|
|
150
|
+
|
|
151
|
+
// ── RT config from process.env ──────────────────────────────────────────────
|
|
152
|
+
export const CREWSWARM_RT_URL = process.env.CREWSWARM_RT_URL || "ws://127.0.0.1:18889";
|
|
153
|
+
export const CREWSWARM_RT_AGENT = process.env.CREWSWARM_RT_AGENT || "crew-main";
|
|
154
|
+
|
|
155
|
+
export function getRTToken() {
|
|
156
|
+
let token = process.env.CREWSWARM_RT_AUTH_TOKEN || "";
|
|
157
|
+
if (!token) {
|
|
158
|
+
const cfg = loadSystemConfig();
|
|
159
|
+
token = cfg?.rt?.authToken || cfg?.env?.CREWSWARM_RT_AUTH_TOKEN || "";
|
|
160
|
+
}
|
|
161
|
+
return typeof token === "string" ? token.trim() : "";
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export const CREWSWARM_RT_TOKEN = getRTToken();
|
|
165
|
+
export const CREWSWARM_RT_CHANNELS = (process.env.CREWSWARM_RT_CHANNELS || "command,assign,handoff,reassign,events")
|
|
166
|
+
.split(",")
|
|
167
|
+
.map((s) => s.trim())
|
|
168
|
+
.filter(Boolean);
|
|
169
|
+
export const CREWSWARM_RT_TLS_INSECURE = process.env.CREWSWARM_RT_TLS_INSECURE === "1";
|
|
170
|
+
export const CREWSWARM_RT_RECONNECT_MS = Number(process.env.CREWSWARM_RT_RECONNECT_MS || "1500");
|
|
171
|
+
export const CREWSWARM_RT_DISPATCH_ENABLED = (process.env.CREWSWARM_RT_DISPATCH_ENABLED || "1") !== "0";
|
|
172
|
+
export const CREWSWARM_RT_DISPATCH_LEASE_MS = Number(process.env.CREWSWARM_RT_DISPATCH_LEASE_MS || "45000");
|
|
173
|
+
export const CREWSWARM_RT_DISPATCH_HEARTBEAT_MS = Number(process.env.CREWSWARM_RT_DISPATCH_HEARTBEAT_MS || "10000");
|
|
174
|
+
export const CREWSWARM_RT_DISPATCH_MAX_RETRIES = Number(process.env.CREWSWARM_RT_DISPATCH_MAX_RETRIES || "2");
|
|
175
|
+
export const CREWSWARM_RT_DISPATCH_MAX_RETRIES_CODING = Number(process.env.CREWSWARM_RT_DISPATCH_MAX_RETRIES_CODING || "3");
|
|
176
|
+
export const CREWSWARM_RT_DISPATCH_RETRY_BACKOFF_MS = Number(process.env.CREWSWARM_RT_DISPATCH_RETRY_BACKOFF_MS || "2000");
|
|
177
|
+
export const CREWSWARM_OPENCODE_ENABLED = (process.env.CREWSWARM_OPENCODE_ENABLED || "1") !== "0";
|
|
178
|
+
export const CREWSWARM_CURSOR_WAVES = process.env.CREWSWARM_CURSOR_WAVES === "1";
|
|
179
|
+
export const CREWSWARM_CLAUDE_CODE = (() => {
|
|
180
|
+
if (process.env.CREWSWARM_CLAUDE_CODE) return /^1|true|yes$/i.test(String(process.env.CREWSWARM_CLAUDE_CODE));
|
|
181
|
+
const cfg = loadSystemConfig();
|
|
182
|
+
if (typeof cfg.claudeCode === "boolean") return cfg.claudeCode;
|
|
183
|
+
return false;
|
|
184
|
+
})();
|
|
185
|
+
export const CREWSWARM_OPENCODE_FORCE = process.env.CREWSWARM_OPENCODE_FORCE === "1";
|
|
186
|
+
export const CREWSWARM_OPENCODE_BIN = process.env.CREWSWARM_OPENCODE_BIN || path.join(os.homedir(), ".opencode", "bin", "opencode");
|
|
187
|
+
export const CREWSWARM_OPENCODE_AGENT = process.env.CREWSWARM_OPENCODE_AGENT || "admin";
|
|
188
|
+
export const CREWSWARM_OPENCODE_MODEL = process.env.CREWSWARM_OPENCODE_MODEL || "groq/moonshotai/kimi-k2-instruct-0905";
|
|
189
|
+
export const CREWSWARM_OPENCODE_FALLBACK_DEFAULT = "groq/llama-3.3-70b-versatile";
|
|
190
|
+
export const CREWSWARM_OPENCODE_TIMEOUT_MS = Number(process.env.CREWSWARM_OPENCODE_TIMEOUT_MS || "300000");
|
|
191
|
+
|
|
192
|
+
// ── Generic drop-in engine loader ───────────────────────────────────────────
|
|
193
|
+
export const ENGINES_BUNDLED_DIR = path.join(path.dirname(new URL(import.meta.url).pathname), "..", "..", "engines");
|
|
194
|
+
export const ENGINES_USER_DIR = path.join(os.homedir(), ".crewswarm", "engines");
|
|
195
|
+
|
|
196
|
+
function _loadAllEngineJSONs() {
|
|
197
|
+
const engines = [];
|
|
198
|
+
for (const dir of [ENGINES_BUNDLED_DIR, ENGINES_USER_DIR]) {
|
|
199
|
+
try {
|
|
200
|
+
const files = fs.readdirSync(dir).filter(f => f.endsWith(".json"));
|
|
201
|
+
for (const file of files) {
|
|
202
|
+
try {
|
|
203
|
+
const def = JSON.parse(fs.readFileSync(path.join(dir, file), "utf8"));
|
|
204
|
+
if (def?.id) engines.push(def);
|
|
205
|
+
} catch { }
|
|
206
|
+
}
|
|
207
|
+
} catch { }
|
|
208
|
+
}
|
|
209
|
+
return engines;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Load all engines from JSON files (both bundled and user-defined)
|
|
214
|
+
* NOTE: Now fully dynamic - all engines (including built-ins) route via engine-registry.mjs
|
|
215
|
+
*/
|
|
216
|
+
export function loadAllEngines() {
|
|
217
|
+
return _loadAllEngineJSONs().filter(e => e.id && e.shouldUse);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Legacy: Load only "generic" engines (for backwards compatibility)
|
|
222
|
+
* Now delegates to loadAllEngines since hardcoded distinction is removed
|
|
223
|
+
*/
|
|
224
|
+
export function loadGenericEngines() {
|
|
225
|
+
return loadAllEngines().filter(e => e.bin && e.args?.run);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// ── Shared memory paths ─────────────────────────────────────────────────────
|
|
229
|
+
export const SHARED_MEMORY_BASE = process.env.SHARED_MEMORY_DIR || path.join(os.homedir(), ".crewswarm", "workspace", "shared-memory");
|
|
230
|
+
export const SHARED_MEMORY_NAMESPACE = process.env.SHARED_MEMORY_NAMESPACE || "claw-swarm";
|
|
231
|
+
export const SWARM_STATUS_LOG = path.join(SHARED_MEMORY_BASE, SHARED_MEMORY_NAMESPACE, "opencrew-rt", "channels", "status.jsonl");
|
|
232
|
+
export const SWARM_DISPATCH_DIR = path.join(SHARED_MEMORY_BASE, SHARED_MEMORY_NAMESPACE, "opencrew-rt", "dispatch");
|
|
233
|
+
export const SWARM_DLQ_DIR = path.join(SHARED_MEMORY_BASE, SHARED_MEMORY_NAMESPACE, "opencrew-rt", "dlq");
|
|
234
|
+
export const SWARM_HEARTBEAT_WINDOW_SEC = Number(process.env.CREWSWARM_RT_HEARTBEAT_WINDOW_SEC || "90");
|
|
235
|
+
export const CREWSWARM_RT_TASK_LEASE_MS = Number(process.env.CREWSWARM_RT_TASK_LEASE_MS || "120000");
|
|
236
|
+
export const CREWSWARM_RT_TASK_HEARTBEAT_MS = Number(process.env.CREWSWARM_RT_TASK_HEARTBEAT_MS || "15000");
|
|
237
|
+
export const CREWSWARM_RT_TASK_RETRY_MAX = Number(process.env.CREWSWARM_RT_TASK_RETRY_MAX || "2");
|
|
238
|
+
export const CREWSWARM_RT_TASK_STATE_TTL_MS = Number(process.env.CREWSWARM_RT_TASK_STATE_TTL_MS || "21600000");
|
|
239
|
+
export const SWARM_RUNTIME_DIR = path.join(SHARED_MEMORY_BASE, SHARED_MEMORY_NAMESPACE, "opencrew-rt", "runtime");
|
|
240
|
+
export const SWARM_TASK_LEASE_DIR = path.join(SWARM_RUNTIME_DIR, "task-leases");
|
|
241
|
+
export const SWARM_TASK_STATE_DIR = path.join(SWARM_RUNTIME_DIR, "task-state");
|
|
242
|
+
|
|
243
|
+
// ── Misc constants ─────────────────────────────────────────────────────────
|
|
244
|
+
export const CREWSWARM_RT_COMMAND_TYPES = new Set([
|
|
245
|
+
"command.spawn_agent",
|
|
246
|
+
"command.run_task",
|
|
247
|
+
"command.cancel_task",
|
|
248
|
+
"command.collect_status",
|
|
249
|
+
"task.assigned",
|
|
250
|
+
"task.reassigned",
|
|
251
|
+
"system.broadcast",
|
|
252
|
+
"cmd.approved",
|
|
253
|
+
"cmd.rejected",
|
|
254
|
+
]);
|
|
255
|
+
export const PROTOCOL_VERSION = 3;
|
|
256
|
+
export const CLI_VERSION = "1.2.0";
|
|
257
|
+
export const ED25519_SPKI_PREFIX = Buffer.from("302a300506032b6570032100", "hex");
|
|
258
|
+
export const REQUEST_TIMEOUT_MS = 60000;
|
|
259
|
+
export const CHAT_TIMEOUT_MS = 55000;
|
|
260
|
+
export const RUN_ID = crypto.randomUUID();
|
|
261
|
+
|
|
262
|
+
// ── crew-lead.mjs constants ───────────────────────────────────────────────
|
|
263
|
+
export const CREW_LEAD_PORT = Number(process.env.CREW_LEAD_PORT || 5010);
|
|
264
|
+
export const CREW_LEAD_PID_PATH = path.join(os.homedir(), ".crewswarm", "logs", "crew-lead.pid");
|
|
265
|
+
export const CREW_LEAD_HISTORY_DIR = path.join(os.homedir(), ".crewswarm", "chat-history");
|
|
266
|
+
export const PROJECTS_REGISTRY = path.join(path.dirname(new URL(import.meta.url).pathname), "..", "crew-lead", "orchestrator-logs", "projects.json");
|
|
267
|
+
export const MAX_HISTORY = 2000;
|
|
268
|
+
export const LLM_TIMEOUT = 180000;
|
|
269
|
+
export const CTL_PATH = (() => {
|
|
270
|
+
const homeBin = path.join(os.homedir(), "bin", "openswitchctl");
|
|
271
|
+
if (fs.existsSync(homeBin)) return homeBin;
|
|
272
|
+
return path.join(process.cwd(), "scripts", "openswitchctl");
|
|
273
|
+
})();
|
|
274
|
+
export const DASH_PORT = Number(process.env.SWARM_DASH_PORT || 4319);
|
|
275
|
+
export const DASH_HOST = process.env.CREWSWARM_RT_HOST || "127.0.0.1";
|
|
276
|
+
export const DASHBOARD = `http://${DASH_HOST}:${DASH_PORT}`;
|
|
277
|
+
export const DISPATCH_TIMEOUT_MS = Number(process.env.CREWSWARM_DISPATCH_TIMEOUT_MS) || 300_000;
|
|
278
|
+
export const DISPATCH_CLAIMED_TIMEOUT_MS = Number(process.env.CREWSWARM_DISPATCH_CLAIMED_TIMEOUT_MS) || 900_000;
|
|
279
|
+
|
|
280
|
+
export function loadCursorWavesEnabled() {
|
|
281
|
+
if (process.env.CREWSWARM_CURSOR_WAVES) return /^1|true|yes$/i.test(String(process.env.CREWSWARM_CURSOR_WAVES));
|
|
282
|
+
const cfg = loadSystemConfig();
|
|
283
|
+
if (typeof cfg.cursorWaves === "boolean") return cfg.cursorWaves;
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
export function loadClaudeCodeEnabled() {
|
|
288
|
+
if (process.env.CREWSWARM_CLAUDE_CODE) return /^1|true|yes$/i.test(String(process.env.CREWSWARM_CLAUDE_CODE));
|
|
289
|
+
const cfg = loadSystemConfig();
|
|
290
|
+
if (typeof cfg.claudeCode === "boolean") return cfg.claudeCode;
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
// ── Configuration Parsers (Migrated from registry.mjs) ───────────────────
|
|
294
|
+
export function resolveConfig() {
|
|
295
|
+
const paths = [CREWSWARM_CONFIG_PATH, path.join(LEGACY_STATE_DIR, "openclaw.json")];
|
|
296
|
+
for (const p of paths) {
|
|
297
|
+
try {
|
|
298
|
+
const cfg = JSON.parse(fs.readFileSync(p, "utf8"));
|
|
299
|
+
cfg.__source = p;
|
|
300
|
+
return cfg;
|
|
301
|
+
} catch { /* try next */ }
|
|
302
|
+
}
|
|
303
|
+
return {};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
export function resolveTelegramBridgeConfig() {
|
|
307
|
+
try {
|
|
308
|
+
return JSON.parse(fs.readFileSync(TELEGRAM_BRIDGE_CONFIG_PATH, "utf8"));
|
|
309
|
+
} catch {
|
|
310
|
+
return {};
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export function loadProviderMap() {
|
|
315
|
+
const sources = [
|
|
316
|
+
CREWSWARM_SWARM_PATH,
|
|
317
|
+
CREWSWARM_CONFIG_PATH,
|
|
318
|
+
];
|
|
319
|
+
const merged = {};
|
|
320
|
+
for (const p of sources) {
|
|
321
|
+
try {
|
|
322
|
+
const cfg = JSON.parse(fs.readFileSync(p, "utf8"));
|
|
323
|
+
const provs = cfg.providers || cfg.models?.providers || {};
|
|
324
|
+
for (const [k, v] of Object.entries(provs)) {
|
|
325
|
+
if (!merged[k] && v?.apiKey && v?.baseUrl) merged[k] = v;
|
|
326
|
+
}
|
|
327
|
+
} catch { }
|
|
328
|
+
}
|
|
329
|
+
return merged;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export function loadAgentLLMConfig(ocAgentId) {
|
|
333
|
+
try {
|
|
334
|
+
const agents = loadAgentList();
|
|
335
|
+
const crewId = ocAgentId.startsWith("crew-") ? ocAgentId : `crew-${ocAgentId}`;
|
|
336
|
+
const bareId = ocAgentId.startsWith("crew-") ? ocAgentId.slice(5) : ocAgentId;
|
|
337
|
+
const agent = agents.find(a => a.id === ocAgentId) ||
|
|
338
|
+
agents.find(a => a.id === crewId) ||
|
|
339
|
+
agents.find(a => a.id === bareId);
|
|
340
|
+
if (!agent?.model) return null;
|
|
341
|
+
|
|
342
|
+
const [providerKey, ...modelParts] = agent.model.split("/");
|
|
343
|
+
let modelId = modelParts.join("/");
|
|
344
|
+
const providers = loadProviderMap();
|
|
345
|
+
const provider = providers[providerKey];
|
|
346
|
+
if (!provider?.baseUrl || !provider?.apiKey) {
|
|
347
|
+
console.warn(`[bridge] No provider config for "${providerKey}" (agent ${ocAgentId}) — check ~/.crewswarm/crewswarm.json providers`);
|
|
348
|
+
return null;
|
|
349
|
+
}
|
|
350
|
+
// OpenRouter requires full ID (e.g. openrouter/hunter-alpha), not bare "hunter-alpha"
|
|
351
|
+
if ((providerKey === "openrouter" || (provider.baseUrl || "").includes("openrouter.ai")) && modelId && !modelId.startsWith("openrouter/")) {
|
|
352
|
+
modelId = "openrouter/" + modelId;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
return { baseUrl: provider.baseUrl, apiKey: provider.apiKey, modelId, agentId: agent.id, providerKey, fallbackModel: agent.fallbackModel || null };
|
|
356
|
+
} catch (e) {
|
|
357
|
+
console.warn(`[bridge] loadAgentLLMConfig error: ${e.message}`);
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
export function loadLoopBrainConfig() {
|
|
363
|
+
try {
|
|
364
|
+
const cfg = JSON.parse(fs.readFileSync(CREWSWARM_CONFIG_PATH, "utf8"));
|
|
365
|
+
const loopBrain = cfg.loopBrain || process.env.CREWSWARM_LOOP_BRAIN || null;
|
|
366
|
+
if (!loopBrain) return null;
|
|
367
|
+
const [providerKey, ...modelParts] = loopBrain.split("/");
|
|
368
|
+
let modelId = modelParts.join("/");
|
|
369
|
+
const providers = loadProviderMap();
|
|
370
|
+
const provider = providers[providerKey];
|
|
371
|
+
if (!provider?.baseUrl || !provider?.apiKey) return null;
|
|
372
|
+
// OpenRouter requires full ID (e.g. openrouter/hunter-alpha), not bare "hunter-alpha"
|
|
373
|
+
if ((providerKey === "openrouter" || (provider.baseUrl || "").includes("openrouter.ai")) && modelId && !modelId.startsWith("openrouter/")) {
|
|
374
|
+
modelId = "openrouter/" + modelId;
|
|
375
|
+
}
|
|
376
|
+
return { baseUrl: provider.baseUrl, apiKey: provider.apiKey, modelId, providerKey };
|
|
377
|
+
} catch { return null; }
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
export function resolveProviderConfig(cfg, providerKey) {
|
|
381
|
+
const explicit = cfg?.models?.providers?.[providerKey] || cfg?.providers?.[providerKey];
|
|
382
|
+
const builtin = PROVIDER_REGISTRY[providerKey];
|
|
383
|
+
if (!explicit && !builtin) return null;
|
|
384
|
+
return {
|
|
385
|
+
baseUrl: explicit?.baseUrl || builtin?.baseUrl,
|
|
386
|
+
apiKey: explicit?.apiKey || cfg?.env?.[`${providerKey.toUpperCase()}_API_KEY`] || null,
|
|
387
|
+
};
|
|
388
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dead Letter Queue (DLQ) implementation for failed tasks.
|
|
3
|
+
* Writes failed tasks to persistent storage for replay/analysis.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {{
|
|
8
|
+
* taskId: string,
|
|
9
|
+
* agent: string,
|
|
10
|
+
* prompt: string,
|
|
11
|
+
* error: string,
|
|
12
|
+
* retries: number,
|
|
13
|
+
* correlationId: string | null,
|
|
14
|
+
* originalPayload: Object,
|
|
15
|
+
* failedAt: string,
|
|
16
|
+
* ts: number,
|
|
17
|
+
* dlqVersion: string
|
|
18
|
+
* }} DLQEntry
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @typedef {{
|
|
23
|
+
* taskId?: string,
|
|
24
|
+
* agent?: string,
|
|
25
|
+
* prompt?: string,
|
|
26
|
+
* task?: string,
|
|
27
|
+
* message?: string,
|
|
28
|
+
* error?: string,
|
|
29
|
+
* retries?: number,
|
|
30
|
+
* payload?: Object,
|
|
31
|
+
* correlationId?: string
|
|
32
|
+
* }} DLQTaskInput
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
import fs from "node:fs";
|
|
36
|
+
import path from "node:path";
|
|
37
|
+
import { SWARM_DLQ_DIR } from "./config.mjs";
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Write a failed task to the DLQ.
|
|
41
|
+
*
|
|
42
|
+
* @param {DLQTaskInput} task - Task details
|
|
43
|
+
* @returns {DLQEntry | null} DLQ entry or null on failure
|
|
44
|
+
*/
|
|
45
|
+
export function writeToDLQ(task) {
|
|
46
|
+
try {
|
|
47
|
+
// Ensure DLQ directory exists
|
|
48
|
+
fs.mkdirSync(SWARM_DLQ_DIR, { recursive: true });
|
|
49
|
+
|
|
50
|
+
const dlqEntry = {
|
|
51
|
+
taskId: task.taskId || `task-${Date.now()}`,
|
|
52
|
+
agent: task.agent || "unknown",
|
|
53
|
+
prompt: task.prompt || task.task || task.message || "",
|
|
54
|
+
error: task.error || "Unknown error",
|
|
55
|
+
retries: task.retries || 0,
|
|
56
|
+
correlationId: task.correlationId || null,
|
|
57
|
+
originalPayload: task.payload || {},
|
|
58
|
+
failedAt: new Date().toISOString(),
|
|
59
|
+
ts: Date.now(),
|
|
60
|
+
dlqVersion: "1.0",
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// Write to DLQ with taskId as filename
|
|
64
|
+
const dlqPath = path.join(SWARM_DLQ_DIR, `${dlqEntry.taskId}.json`);
|
|
65
|
+
fs.writeFileSync(dlqPath, JSON.stringify(dlqEntry, null, 2));
|
|
66
|
+
|
|
67
|
+
console.log(`[dlq] Task ${dlqEntry.taskId} written to DLQ (agent: ${dlqEntry.agent}, retries: ${dlqEntry.retries})`);
|
|
68
|
+
|
|
69
|
+
return dlqEntry;
|
|
70
|
+
} catch (e) {
|
|
71
|
+
console.error(`[dlq] Failed to write to DLQ: ${e.message}`);
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Check if a task should be written to DLQ.
|
|
78
|
+
*
|
|
79
|
+
* @param {DLQTaskInput} task - Task details
|
|
80
|
+
* @param {number} maxRetries - Maximum retries allowed
|
|
81
|
+
* @returns {boolean} True if task should go to DLQ
|
|
82
|
+
*/
|
|
83
|
+
export function shouldDLQ(task, maxRetries) {
|
|
84
|
+
// Write to DLQ if:
|
|
85
|
+
// 1. Max retries exceeded
|
|
86
|
+
if (task.retries >= maxRetries) return true;
|
|
87
|
+
|
|
88
|
+
// 2. Catastrophic errors (non-retryable)
|
|
89
|
+
const catastrophicErrors = [
|
|
90
|
+
"ENOENT",
|
|
91
|
+
"EACCES",
|
|
92
|
+
"Module not found",
|
|
93
|
+
"Syntax error",
|
|
94
|
+
"Invalid configuration",
|
|
95
|
+
];
|
|
96
|
+
|
|
97
|
+
const errorMsg = String(task.error || "").toLowerCase();
|
|
98
|
+
if (catastrophicErrors.some(e => errorMsg.includes(e.toLowerCase()))) {
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* List all DLQ entries.
|
|
107
|
+
*
|
|
108
|
+
* @returns {DLQEntry[]} Array of DLQ entries
|
|
109
|
+
*/
|
|
110
|
+
export function listDLQEntries() {
|
|
111
|
+
try {
|
|
112
|
+
if (!fs.existsSync(SWARM_DLQ_DIR)) return [];
|
|
113
|
+
|
|
114
|
+
const files = fs.readdirSync(SWARM_DLQ_DIR)
|
|
115
|
+
.filter(f => f.endsWith(".json"))
|
|
116
|
+
.sort()
|
|
117
|
+
.reverse(); // Newest first
|
|
118
|
+
|
|
119
|
+
return files.map(file => {
|
|
120
|
+
try {
|
|
121
|
+
const content = fs.readFileSync(path.join(SWARM_DLQ_DIR, file), "utf8");
|
|
122
|
+
return JSON.parse(content);
|
|
123
|
+
} catch {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
}).filter(Boolean);
|
|
127
|
+
} catch (e) {
|
|
128
|
+
console.error(`[dlq] Failed to list DLQ entries: ${e.message}`);
|
|
129
|
+
return [];
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Get a single DLQ entry by task ID.
|
|
135
|
+
*
|
|
136
|
+
* @param {string} taskId - Task ID
|
|
137
|
+
* @returns {DLQEntry | null} DLQ entry or null if not found
|
|
138
|
+
*/
|
|
139
|
+
export function getDLQEntry(taskId) {
|
|
140
|
+
try {
|
|
141
|
+
const dlqPath = path.join(SWARM_DLQ_DIR, `${taskId}.json`);
|
|
142
|
+
if (!fs.existsSync(dlqPath)) return null;
|
|
143
|
+
|
|
144
|
+
return JSON.parse(fs.readFileSync(dlqPath, "utf8"));
|
|
145
|
+
} catch (e) {
|
|
146
|
+
console.error(`[dlq] Failed to read DLQ entry ${taskId}: ${e.message}`);
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Delete a DLQ entry (after successful replay).
|
|
153
|
+
*
|
|
154
|
+
* @param {string} taskId - Task ID to remove from DLQ
|
|
155
|
+
* @returns {boolean} True if deleted successfully
|
|
156
|
+
*/
|
|
157
|
+
export function deleteDLQEntry(taskId) {
|
|
158
|
+
try {
|
|
159
|
+
const dlqPath = path.join(SWARM_DLQ_DIR, `${taskId}.json`);
|
|
160
|
+
if (fs.existsSync(dlqPath)) {
|
|
161
|
+
fs.unlinkSync(dlqPath);
|
|
162
|
+
console.log(`[dlq] Removed entry ${taskId} from DLQ`);
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
return false;
|
|
166
|
+
} catch (e) {
|
|
167
|
+
console.error(`[dlq] Failed to delete DLQ entry ${taskId}: ${e.message}`);
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log rotation utility — prevents unbounded growth of .jsonl files
|
|
3
|
+
* Implements simple size-based rotation: if file exceeds MAX_LOG_SIZE_MB,
|
|
4
|
+
* move it to .1, .2, etc. and keep only KEEP_ROTATIONS backups.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { existsSync, statSync, renameSync, unlinkSync, appendFileSync } from "fs";
|
|
8
|
+
import { appendFile } from "fs/promises";
|
|
9
|
+
|
|
10
|
+
const MAX_LOG_SIZE_MB = Number(process.env.CREWSWARM_LOG_MAX_SIZE_MB || "10");
|
|
11
|
+
const MAX_LOG_SIZE_BYTES = MAX_LOG_SIZE_MB * 1024 * 1024;
|
|
12
|
+
const KEEP_ROTATIONS = Number(process.env.CREWSWARM_LOG_KEEP_ROTATIONS || "3");
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Append a line to a log file with automatic rotation
|
|
16
|
+
* @param {string} filePath - Path to the log file
|
|
17
|
+
* @param {string} content - Content to append (should include newline)
|
|
18
|
+
*/
|
|
19
|
+
export async function appendWithRotation(filePath, content) {
|
|
20
|
+
// Check if rotation is needed
|
|
21
|
+
if (existsSync(filePath)) {
|
|
22
|
+
const stats = statSync(filePath);
|
|
23
|
+
if (stats.size > MAX_LOG_SIZE_BYTES) {
|
|
24
|
+
rotateLog(filePath);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
await appendFile(filePath, content, "utf8");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Synchronous version for non-async contexts
|
|
33
|
+
*/
|
|
34
|
+
export function appendWithRotationSync(filePath, content) {
|
|
35
|
+
if (existsSync(filePath)) {
|
|
36
|
+
const stats = statSync(filePath);
|
|
37
|
+
if (stats.size > MAX_LOG_SIZE_BYTES) {
|
|
38
|
+
rotateLog(filePath);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
appendFileSync(filePath, content, "utf8");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Rotate a log file: rename current to .1, .1 to .2, etc.
|
|
47
|
+
* Delete oldest rotation that exceeds KEEP_ROTATIONS
|
|
48
|
+
*/
|
|
49
|
+
function rotateLog(filePath) {
|
|
50
|
+
try {
|
|
51
|
+
// Delete the oldest rotation if it exists
|
|
52
|
+
const oldestRotation = `${filePath}.${KEEP_ROTATIONS}`;
|
|
53
|
+
if (existsSync(oldestRotation)) {
|
|
54
|
+
unlinkSync(oldestRotation);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Shift existing rotations: .2 → .3, .1 → .2, etc.
|
|
58
|
+
for (let i = KEEP_ROTATIONS - 1; i >= 1; i--) {
|
|
59
|
+
const from = `${filePath}.${i}`;
|
|
60
|
+
const to = `${filePath}.${i + 1}`;
|
|
61
|
+
if (existsSync(from)) {
|
|
62
|
+
renameSync(from, to);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Move current log to .1
|
|
67
|
+
renameSync(filePath, `${filePath}.1`);
|
|
68
|
+
|
|
69
|
+
console.log(`[LOG-ROTATION] Rotated ${filePath} (size exceeded ${MAX_LOG_SIZE_MB}MB)`);
|
|
70
|
+
} catch (err) {
|
|
71
|
+
console.error(`[LOG-ROTATION] Failed to rotate ${filePath}: ${err.message}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Manual rotation trigger (useful for testing or cron jobs)
|
|
77
|
+
*/
|
|
78
|
+
export function forceRotate(filePath) {
|
|
79
|
+
if (existsSync(filePath)) {
|
|
80
|
+
rotateLog(filePath);
|
|
81
|
+
}
|
|
82
|
+
}
|