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,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* logger.mjs — structured log utility for crewswarm
|
|
3
|
+
*
|
|
4
|
+
* By default emits human-readable prefixed lines.
|
|
5
|
+
* Set LOG_FORMAT=json to emit newline-delimited JSON (machine-parseable).
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* import { log } from "../lib/runtime/logger.mjs";
|
|
9
|
+
* log("info", "crew-lead", "RT connected", { port: 18889 });
|
|
10
|
+
* log("warn", "wave-dispatcher", "queue full", { depth: 50, agent: "crew-coder" });
|
|
11
|
+
* log("error", "pipeline-state", "save failed", { pipelineId, error: e.message });
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const JSON_MODE = process.env.LOG_FORMAT === "json";
|
|
15
|
+
|
|
16
|
+
const LEVEL_PREFIX = {
|
|
17
|
+
info: "",
|
|
18
|
+
warn: "⚠️ ",
|
|
19
|
+
error: "❌ ",
|
|
20
|
+
debug: "🔍 ",
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @param {"info"|"warn"|"error"|"debug"} level
|
|
25
|
+
* @param {string} component e.g. "crew-lead", "wave-dispatcher", "pipeline-state"
|
|
26
|
+
* @param {string} msg Human-readable message
|
|
27
|
+
* @param {object} [data] Optional structured fields (correlationId, agent, taskId, …)
|
|
28
|
+
*/
|
|
29
|
+
export function log(level, component, msg, data = {}) {
|
|
30
|
+
if (JSON_MODE) {
|
|
31
|
+
const entry = {
|
|
32
|
+
ts: new Date().toISOString(),
|
|
33
|
+
level,
|
|
34
|
+
component,
|
|
35
|
+
msg,
|
|
36
|
+
...data,
|
|
37
|
+
};
|
|
38
|
+
process.stdout.write(JSON.stringify(entry) + "\n");
|
|
39
|
+
} else {
|
|
40
|
+
const prefix = LEVEL_PREFIX[level] ?? "";
|
|
41
|
+
const extras = Object.keys(data).length
|
|
42
|
+
? " " + Object.entries(data).map(([k, v]) => `${k}=${JSON.stringify(v)}`).join(" ")
|
|
43
|
+
: "";
|
|
44
|
+
const line = `[${component}] ${prefix}${msg}${extras}`;
|
|
45
|
+
if (level === "error") console.error(line);
|
|
46
|
+
else console.log(line);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Convenience wrappers
|
|
52
|
+
*/
|
|
53
|
+
export const logger = {
|
|
54
|
+
info: (component, msg, data) => log("info", component, msg, data),
|
|
55
|
+
warn: (component, msg, data) => log("warn", component, msg, data),
|
|
56
|
+
error: (component, msg, data) => log("error", component, msg, data),
|
|
57
|
+
debug: (component, msg, data) => log("debug", component, msg, data),
|
|
58
|
+
};
|
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lib/runtime/memory.mjs
|
|
3
|
+
* Shared memory bundle loading, agent prompt loading, and task prompt assembly.
|
|
4
|
+
* Extracted from gateway-bridge.mjs.
|
|
5
|
+
*/
|
|
6
|
+
import fs from "node:fs";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import os from "node:os";
|
|
9
|
+
import { CREWSWARM_REPO_ROOT } from "./config.mjs";
|
|
10
|
+
import {
|
|
11
|
+
applySharedChatPromptOverlay,
|
|
12
|
+
getSharedChatPromptOverlay,
|
|
13
|
+
} from "../chat/shared-chat-prompt-overlay.mjs";
|
|
14
|
+
import { loadProjectMessages } from "../chat/project-messages.mjs";
|
|
15
|
+
|
|
16
|
+
// ── Constants ────────────────────────────────────────────────────────────────
|
|
17
|
+
|
|
18
|
+
export const SHARED_MEMORY_DIR = path.join(CREWSWARM_REPO_ROOT, "memory");
|
|
19
|
+
export const SHARED_MEMORY_MAX_FILE_CHARS = 8000;
|
|
20
|
+
export const SHARED_MEMORY_MAX_TOTAL_CHARS = 40000;
|
|
21
|
+
export const SHARED_MEMORY_FILES = [
|
|
22
|
+
"law.md", // Crew laws — no harm, no unauthorized access, don't break machine, create value
|
|
23
|
+
"current-state.md", // System overview — what crewswarm is, CRITICAL task guidance
|
|
24
|
+
"agent-handoff.md", // Current status, last completed work, agent rules
|
|
25
|
+
"orchestration-protocol.md", // Agent roster, tool permissions, dispatch syntax
|
|
26
|
+
"brain.md", // Accumulated project knowledge — read this to avoid repeating mistakes
|
|
27
|
+
// "decisions.md" // Architectural decisions — only load when needed
|
|
28
|
+
// "telegram-context.md" // Telegram chat history — too noisy for code tasks
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
// Extra memory files injected for specific agents (static) + dynamic agents by _role
|
|
32
|
+
export const _AGENT_EXTRA_MEMORY_STATIC = {
|
|
33
|
+
"crew-fixer": ["lessons.md"],
|
|
34
|
+
"crew-coder": ["lessons.md"],
|
|
35
|
+
"crew-coder-front": ["lessons.md"],
|
|
36
|
+
"crew-coder-back": ["lessons.md"],
|
|
37
|
+
};
|
|
38
|
+
export const _EXTRA_MEMORY_BY_ROLE = {
|
|
39
|
+
coder: ["lessons.md"],
|
|
40
|
+
ops: ["lessons.md"],
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// ── Injected dependencies ────────────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
let _telemetry = () => {};
|
|
46
|
+
let _ensureSharedMemoryFiles = () => ({ created: [], error: null });
|
|
47
|
+
let _loadAgentList = () => [];
|
|
48
|
+
let _loadAgentToolPermissions = () => new Set();
|
|
49
|
+
let _buildToolInstructions = () => "";
|
|
50
|
+
let _getOpencodeProjectDir = () => "";
|
|
51
|
+
|
|
52
|
+
export function initMemory({
|
|
53
|
+
telemetry,
|
|
54
|
+
ensureSharedMemoryFiles,
|
|
55
|
+
loadAgentList,
|
|
56
|
+
loadAgentToolPermissions,
|
|
57
|
+
buildToolInstructions,
|
|
58
|
+
getOpencodeProjectDir,
|
|
59
|
+
}) {
|
|
60
|
+
if (telemetry) _telemetry = telemetry;
|
|
61
|
+
if (ensureSharedMemoryFiles)
|
|
62
|
+
_ensureSharedMemoryFiles = ensureSharedMemoryFiles;
|
|
63
|
+
if (loadAgentList) _loadAgentList = loadAgentList;
|
|
64
|
+
if (loadAgentToolPermissions)
|
|
65
|
+
_loadAgentToolPermissions = loadAgentToolPermissions;
|
|
66
|
+
if (buildToolInstructions) _buildToolInstructions = buildToolInstructions;
|
|
67
|
+
if (getOpencodeProjectDir) _getOpencodeProjectDir = getOpencodeProjectDir;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ── Functions ────────────────────────────────────────────────────────────────
|
|
71
|
+
|
|
72
|
+
export function getAgentExtraMemory(agentId) {
|
|
73
|
+
const bareId = agentId.startsWith("crew-")
|
|
74
|
+
? `crew-${agentId.slice(5)}`
|
|
75
|
+
: agentId;
|
|
76
|
+
if (_AGENT_EXTRA_MEMORY_STATIC[agentId])
|
|
77
|
+
return _AGENT_EXTRA_MEMORY_STATIC[agentId];
|
|
78
|
+
if (_AGENT_EXTRA_MEMORY_STATIC[bareId])
|
|
79
|
+
return _AGENT_EXTRA_MEMORY_STATIC[bareId];
|
|
80
|
+
try {
|
|
81
|
+
const agents = _loadAgentList();
|
|
82
|
+
const cfg = agents.find((a) => a.id === agentId);
|
|
83
|
+
if (cfg?._role && _EXTRA_MEMORY_BY_ROLE[cfg._role])
|
|
84
|
+
return _EXTRA_MEMORY_BY_ROLE[cfg._role];
|
|
85
|
+
} catch {}
|
|
86
|
+
return [];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function loadSharedMemoryBundle() {
|
|
90
|
+
try {
|
|
91
|
+
const ensureResult = _ensureSharedMemoryFiles();
|
|
92
|
+
if (ensureResult.error) {
|
|
93
|
+
return {
|
|
94
|
+
text: "",
|
|
95
|
+
missing: SHARED_MEMORY_FILES,
|
|
96
|
+
included: [],
|
|
97
|
+
files: {},
|
|
98
|
+
bytes: 0,
|
|
99
|
+
loadFailed: true,
|
|
100
|
+
bootstrapCreated: ensureResult.created,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (!fs.existsSync(SHARED_MEMORY_DIR)) {
|
|
105
|
+
return {
|
|
106
|
+
text: "",
|
|
107
|
+
missing: SHARED_MEMORY_FILES,
|
|
108
|
+
included: [],
|
|
109
|
+
files: {},
|
|
110
|
+
bytes: 0,
|
|
111
|
+
loadFailed: true,
|
|
112
|
+
bootstrapCreated: ensureResult.created,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const included = [];
|
|
117
|
+
const missing = [];
|
|
118
|
+
const files = {};
|
|
119
|
+
const sections = [];
|
|
120
|
+
let totalChars = 0;
|
|
121
|
+
|
|
122
|
+
for (const fileName of SHARED_MEMORY_FILES) {
|
|
123
|
+
const fullPath = path.join(SHARED_MEMORY_DIR, fileName);
|
|
124
|
+
if (!fs.existsSync(fullPath)) {
|
|
125
|
+
missing.push(fileName);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
let content = fs.readFileSync(fullPath, "utf8");
|
|
130
|
+
if (content.length > SHARED_MEMORY_MAX_FILE_CHARS) {
|
|
131
|
+
// For append-only files keep the TAIL (newest entries); for others keep the HEAD
|
|
132
|
+
const TAIL_FIRST_FILES = new Set([
|
|
133
|
+
"brain.md",
|
|
134
|
+
"session-log.md",
|
|
135
|
+
"telegram-context.md",
|
|
136
|
+
]);
|
|
137
|
+
if (TAIL_FIRST_FILES.has(fileName)) {
|
|
138
|
+
content = `[…older entries trimmed]\n\n${content.slice(-SHARED_MEMORY_MAX_FILE_CHARS)}`;
|
|
139
|
+
} else {
|
|
140
|
+
content = `${content.slice(0, SHARED_MEMORY_MAX_FILE_CHARS)}\n\n[truncated]`;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
files[fileName] = content;
|
|
145
|
+
const section = `### ${fileName}\n${content}`;
|
|
146
|
+
if (totalChars + section.length > SHARED_MEMORY_MAX_TOTAL_CHARS) break;
|
|
147
|
+
|
|
148
|
+
sections.push(section);
|
|
149
|
+
included.push(fileName);
|
|
150
|
+
totalChars += section.length;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (!sections.length) {
|
|
154
|
+
return {
|
|
155
|
+
text: "",
|
|
156
|
+
missing,
|
|
157
|
+
included,
|
|
158
|
+
files,
|
|
159
|
+
bytes: 0,
|
|
160
|
+
loadFailed: false,
|
|
161
|
+
bootstrapCreated: ensureResult.created,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const text = [
|
|
166
|
+
"Persistent shared memory (load this before answering):",
|
|
167
|
+
...sections,
|
|
168
|
+
"End persistent memory.",
|
|
169
|
+
].join("\n\n");
|
|
170
|
+
return {
|
|
171
|
+
text,
|
|
172
|
+
missing,
|
|
173
|
+
included,
|
|
174
|
+
files,
|
|
175
|
+
bytes: Buffer.byteLength(text, "utf8"),
|
|
176
|
+
loadFailed: false,
|
|
177
|
+
bootstrapCreated: ensureResult.created,
|
|
178
|
+
};
|
|
179
|
+
} catch (err) {
|
|
180
|
+
_telemetry("shared_memory_load_error", {
|
|
181
|
+
message: err?.message ?? String(err),
|
|
182
|
+
});
|
|
183
|
+
return {
|
|
184
|
+
text: "",
|
|
185
|
+
missing: SHARED_MEMORY_FILES,
|
|
186
|
+
included: [],
|
|
187
|
+
files: {},
|
|
188
|
+
bytes: 0,
|
|
189
|
+
loadFailed: true,
|
|
190
|
+
bootstrapCreated: [],
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export function getLastHandoffTimestamp(sharedMemory) {
|
|
196
|
+
const handoff = sharedMemory?.files?.["agent-handoff.md"] || "";
|
|
197
|
+
const match = handoff.match(/^Last updated:\s*(.+)$/m);
|
|
198
|
+
return match ? match[1].trim() : "unknown";
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export function loadAgentPrompts() {
|
|
202
|
+
const candidates = [
|
|
203
|
+
path.join(os.homedir(), ".crewswarm", "agent-prompts.json"),
|
|
204
|
+
path.join(os.homedir(), ".openclaw", "agent-prompts.json"),
|
|
205
|
+
];
|
|
206
|
+
for (const p of candidates) {
|
|
207
|
+
try {
|
|
208
|
+
const prompts = JSON.parse(fs.readFileSync(p, "utf8"));
|
|
209
|
+
if (Object.keys(prompts).length > 0) {
|
|
210
|
+
const augmented = {};
|
|
211
|
+
for (const [key, value] of Object.entries(prompts)) {
|
|
212
|
+
augmented[key] = applySharedChatPromptOverlay(value, key);
|
|
213
|
+
}
|
|
214
|
+
return augmented;
|
|
215
|
+
}
|
|
216
|
+
} catch {}
|
|
217
|
+
}
|
|
218
|
+
return {};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function buildExecutionGuardrails(agentId = "") {
|
|
222
|
+
if (!agentId || agentId === "crew-lead") return "";
|
|
223
|
+
|
|
224
|
+
const isPM = agentId.startsWith("crew-pm");
|
|
225
|
+
const isQA = agentId === "crew-qa";
|
|
226
|
+
const isCoder =
|
|
227
|
+
agentId === "crew-coder" ||
|
|
228
|
+
agentId === "crew-coder-front" ||
|
|
229
|
+
agentId === "crew-coder-back" ||
|
|
230
|
+
agentId === "crew-fixer" ||
|
|
231
|
+
agentId === "crew-frontend";
|
|
232
|
+
|
|
233
|
+
const lines = [
|
|
234
|
+
"## Execution Guardrails",
|
|
235
|
+
"",
|
|
236
|
+
"OPERATING PRINCIPLES:",
|
|
237
|
+
"- Read before acting: @@READ_FILE any file before modifying or claiming its contents. Never guess what's in a file.",
|
|
238
|
+
"- Simplest approach first: do what was asked. Don't refactor surrounding code, add features, or over-engineer beyond the task.",
|
|
239
|
+
"- Match the request: a bug fix is just a bug fix. Don't clean up adjacent code, add docstrings to unchanged functions, or suggest a rewrite.",
|
|
240
|
+
"- Own mistakes: if something fails or you got it wrong, say so briefly and try a different approach. Don't repeat the same failing action.",
|
|
241
|
+
"",
|
|
242
|
+
"QUALITY:",
|
|
243
|
+
"- Retrieval-first: before a long or technical answer, gather real context from files/tool output first; do not rely on recollection.",
|
|
244
|
+
"- No stale claims: never assert runtime/model/service status unless verified in this turn by tool output or injected snapshot.",
|
|
245
|
+
"- Anti-loop: if the same failure pattern repeats twice, switch strategy (different tool path / narrower scope / fallback) and state the switch briefly.",
|
|
246
|
+
"- Never fabricate file contents, command output, or tool results. If you don't have data, use a tool to get it.",
|
|
247
|
+
"",
|
|
248
|
+
"STYLE:",
|
|
249
|
+
"- Lead with the answer or action, not the reasoning. Skip preamble and filler.",
|
|
250
|
+
"- Concise execution-first output (max 5 lines) unless the user or task asks for detail.",
|
|
251
|
+
];
|
|
252
|
+
|
|
253
|
+
if (isPM) {
|
|
254
|
+
lines.push(
|
|
255
|
+
"- PM has two modes:",
|
|
256
|
+
" - Conversational mode (research/ideation): personality and exploratory reasoning are encouraged.",
|
|
257
|
+
" - Execution mode (artifact-producing): strict, structured output required.",
|
|
258
|
+
"- Enter PM execution mode when task includes concrete delivery signals (e.g. file paths, `@@WRITE_FILE`, roadmap/spec updates, explicit acceptance criteria, 'deliver/finalize/write').",
|
|
259
|
+
"- PM execution mode contract: end with `Deliverables:` (exact file paths) and `Acceptance Criteria:` (testable bullets).",
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
if (isQA) {
|
|
263
|
+
lines.push(
|
|
264
|
+
"- QA output contract: findings must include Severity, Repro steps, and concrete fix suggestion.",
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
if (isCoder) {
|
|
268
|
+
lines.push(
|
|
269
|
+
"- Coding output contract: include changed file paths and verification command output (`@@RUN_CMD` result) before completion.",
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return lines.join("\n");
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export function buildTaskPrompt(taskText, sourceLabel, agentId, options = {}) {
|
|
277
|
+
const { projectDir: taskProjectDir, projectId: taskProjectId } = options;
|
|
278
|
+
const sharedMemory = loadSharedMemoryBundle();
|
|
279
|
+
if (sharedMemory.loadFailed) {
|
|
280
|
+
return { finalPrompt: "MEMORY_LOAD_FAILED", sharedMemory };
|
|
281
|
+
}
|
|
282
|
+
const lastHandoffTimestamp = getLastHandoffTimestamp(sharedMemory);
|
|
283
|
+
|
|
284
|
+
const contextNote = `[Shared memory loaded — UTC: ${new Date().toISOString().slice(0, 16).replace("T", " ")} | Last handoff: ${lastHandoffTimestamp.slice(0, 16) || "none"}]`;
|
|
285
|
+
|
|
286
|
+
// Inject agent-specific system prompt if one exists
|
|
287
|
+
const agentPrompts = loadAgentPrompts();
|
|
288
|
+
const bareId = agentId ? agentId.replace(/^crew-/, "") : null;
|
|
289
|
+
const agentSystemPrompt =
|
|
290
|
+
(agentId && agentPrompts[agentId]) ||
|
|
291
|
+
(bareId && agentPrompts[bareId]) ||
|
|
292
|
+
(agentId ? getSharedChatPromptOverlay(agentId) : null);
|
|
293
|
+
|
|
294
|
+
const agentAllowed = _loadAgentToolPermissions(agentId || "crew-main");
|
|
295
|
+
const toolInstructions = _buildToolInstructions(agentAllowed);
|
|
296
|
+
|
|
297
|
+
// Load global rules — injected into every agent if the file exists
|
|
298
|
+
const globalRulesPath = path.join(
|
|
299
|
+
os.homedir(),
|
|
300
|
+
".crewswarm",
|
|
301
|
+
"global-rules.md",
|
|
302
|
+
);
|
|
303
|
+
const globalRules = (() => {
|
|
304
|
+
try {
|
|
305
|
+
const txt = fs.readFileSync(globalRulesPath, "utf8").trim();
|
|
306
|
+
return txt ? `## Global Rules (apply to all agents)\n${txt}` : "";
|
|
307
|
+
} catch {
|
|
308
|
+
return "";
|
|
309
|
+
}
|
|
310
|
+
})();
|
|
311
|
+
|
|
312
|
+
// Load agent-specific extra memory (e.g. lessons.md for coders + fixer)
|
|
313
|
+
const extraMemoryFiles = getAgentExtraMemory(agentId);
|
|
314
|
+
const extraMemorySections = [];
|
|
315
|
+
for (const fileName of extraMemoryFiles) {
|
|
316
|
+
const fullPath = path.join(SHARED_MEMORY_DIR, fileName);
|
|
317
|
+
if (!fs.existsSync(fullPath)) continue;
|
|
318
|
+
try {
|
|
319
|
+
let content = fs.readFileSync(fullPath, "utf8").trim();
|
|
320
|
+
if (content.length > 6000) content = content.slice(-6000); // tail-trim
|
|
321
|
+
if (content) extraMemorySections.push(`### ${fileName}\n${content}`);
|
|
322
|
+
} catch {}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Inject agent identity — name, model, and ID so every agent knows who it is
|
|
326
|
+
let identityHeader = "";
|
|
327
|
+
if (agentId) {
|
|
328
|
+
const agentList = _loadAgentList();
|
|
329
|
+
const agentCfg = agentList.find((a) => a.id === agentId);
|
|
330
|
+
if (agentCfg) {
|
|
331
|
+
const displayName = agentCfg.identity?.name || agentCfg.name || agentId;
|
|
332
|
+
const emoji = agentCfg.identity?.emoji || agentCfg.emoji || "";
|
|
333
|
+
const role = agentCfg.identity?.theme || "";
|
|
334
|
+
const model = agentCfg.model || "unknown model";
|
|
335
|
+
identityHeader = `You are ${emoji ? emoji + " " : ""}${displayName} (agent ID: ${agentId}${role ? ", role: " + role : ""}, model: ${model}).`;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Fixer: when a path in the task doesn't exist, discover it by searching the project (so wrong paths like src/api/routers/main.py → find src/api/main.py)
|
|
340
|
+
const projectRoot =
|
|
341
|
+
taskProjectDir ||
|
|
342
|
+
(agentId === "crew-fixer" ? _getOpencodeProjectDir() : null);
|
|
343
|
+
const desktopProjectsHint = path.join(
|
|
344
|
+
os.homedir(),
|
|
345
|
+
"Desktop",
|
|
346
|
+
"<project-name>",
|
|
347
|
+
);
|
|
348
|
+
let projectDiscoveryRule = "";
|
|
349
|
+
if (agentId === "crew-fixer") {
|
|
350
|
+
if (projectRoot) {
|
|
351
|
+
projectDiscoveryRule = `## Project discovery (apply when a path in the task is missing or wrong)\nProject root: ${projectRoot}\n- If a path in the task does not exist, search the project first: use @@RUN_CMD find "${projectRoot}" -name '<filename>' (e.g. main.py) or ls to locate the file. Do not report "file not found" until you have tried to resolve the path within this project.`;
|
|
352
|
+
} else {
|
|
353
|
+
projectDiscoveryRule = `## Project discovery (external projects)\n- External projects (e.g. polymarket-ai-strat) are NOT inside the crewswarm repo. Their root is typically ${desktopProjectsHint}. If a path contains "crewswarm/<project-name>/", replace that with "${path.join(os.homedir(), "Desktop")}/<project-name>/". Example: polymarket-ai-strat main.py is at ${path.join(os.homedir(), "Desktop", "polymarket-ai-strat", "src/api/main.py")} (not under crewswarm, and not src/api/routers/main.py). Use @@RUN_CMD find to locate files if unsure.`;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Load per-project memory from <projectDir>/.crewswarm/context.md and brain.md
|
|
358
|
+
// context.md = static facts (GitHub, tech stack, danger zones) — human-authored
|
|
359
|
+
// brain.md = accumulated knowledge — agents append via @@BRAIN when project selected
|
|
360
|
+
const projectMemorySections = [];
|
|
361
|
+
if (taskProjectDir) {
|
|
362
|
+
const projectMemoryDir = path.join(taskProjectDir, ".crewswarm");
|
|
363
|
+
for (const fname of ["context.md", "brain.md"]) {
|
|
364
|
+
const fpath = path.join(projectMemoryDir, fname);
|
|
365
|
+
try {
|
|
366
|
+
let content = fs.readFileSync(fpath, "utf8").trim();
|
|
367
|
+
if (content.length > 8000) content = content.slice(-8000);
|
|
368
|
+
if (content)
|
|
369
|
+
projectMemorySections.push(
|
|
370
|
+
`### Project ${fname} (${taskProjectDir})\n${content}`,
|
|
371
|
+
);
|
|
372
|
+
} catch {
|
|
373
|
+
/* file doesn't exist — skip silently */
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const executionGuardrails = buildExecutionGuardrails(agentId);
|
|
379
|
+
|
|
380
|
+
const parts = [];
|
|
381
|
+
if (identityHeader) parts.push(identityHeader);
|
|
382
|
+
if (agentSystemPrompt) parts.push(agentSystemPrompt);
|
|
383
|
+
if (globalRules) parts.push(globalRules);
|
|
384
|
+
if (toolInstructions) parts.push(toolInstructions);
|
|
385
|
+
if (executionGuardrails) parts.push(executionGuardrails);
|
|
386
|
+
if (projectDiscoveryRule) parts.push(projectDiscoveryRule);
|
|
387
|
+
if (sharedMemory.text) parts.push(sharedMemory.text);
|
|
388
|
+
if (extraMemorySections.length > 0)
|
|
389
|
+
parts.push(extraMemorySections.join("\n\n"));
|
|
390
|
+
if (projectMemorySections.length > 0)
|
|
391
|
+
parts.push(projectMemorySections.join("\n\n"));
|
|
392
|
+
|
|
393
|
+
// Inject recent project conversation history so agents have context
|
|
394
|
+
if (taskProjectId) {
|
|
395
|
+
try {
|
|
396
|
+
const recentMessages = loadProjectMessages(taskProjectId, { limit: 20 });
|
|
397
|
+
if (recentMessages.length > 0) {
|
|
398
|
+
const historyLines = recentMessages.map((msg) => {
|
|
399
|
+
const who = msg.agent ? `[${msg.agent}]` : msg.role === "user" ? "[user]" : "[assistant]";
|
|
400
|
+
const text = String(msg.content || "").slice(0, 500);
|
|
401
|
+
return `${who} ${text}`;
|
|
402
|
+
});
|
|
403
|
+
// Cap total history to ~4000 chars to avoid blowing context
|
|
404
|
+
let historyText = historyLines.join("\n");
|
|
405
|
+
if (historyText.length > 4000) {
|
|
406
|
+
historyText = historyText.slice(-4000);
|
|
407
|
+
}
|
|
408
|
+
parts.push(`## Recent conversation history (project: ${taskProjectId})\n${historyText}`);
|
|
409
|
+
}
|
|
410
|
+
} catch {
|
|
411
|
+
/* project messages unavailable — skip silently */
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
parts.push(contextNote);
|
|
416
|
+
parts.push(taskText);
|
|
417
|
+
|
|
418
|
+
const finalPrompt = parts.join("\n\n");
|
|
419
|
+
|
|
420
|
+
return { finalPrompt, sharedMemory };
|
|
421
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized path resolution for crewswarm config and state directories.
|
|
3
|
+
* Supports test mode via environment variables for hermetic testing.
|
|
4
|
+
*
|
|
5
|
+
* Environment variables:
|
|
6
|
+
* - CREWSWARM_CONFIG_DIR: Override config directory (default: ~/.crewswarm)
|
|
7
|
+
* - CREWSWARM_STATE_DIR: Override state directory (default: ~/.crewswarm)
|
|
8
|
+
* - CREWSWARM_TEST_MODE: Set to "true" to automatically use temp directories
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import fs from "fs";
|
|
12
|
+
import path from "path";
|
|
13
|
+
import os from "os";
|
|
14
|
+
|
|
15
|
+
let _configDir = null;
|
|
16
|
+
let _stateDir = null;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Get the crewswarm configuration directory.
|
|
20
|
+
* Used for: crewswarm.json, config.json, etc.
|
|
21
|
+
*/
|
|
22
|
+
export function getConfigDir() {
|
|
23
|
+
if (_configDir) return _configDir;
|
|
24
|
+
|
|
25
|
+
if (process.env.CREWSWARM_TEST_MODE === "true") {
|
|
26
|
+
// Use a consistent temp dir for the entire test process (not per-call)
|
|
27
|
+
_configDir = path.join(os.tmpdir(), `crewswarm-test-${process.pid}`);
|
|
28
|
+
} else {
|
|
29
|
+
_configDir = process.env.CREWSWARM_CONFIG_DIR || path.join(os.homedir(), ".crewswarm");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
fs.mkdirSync(_configDir, { recursive: true });
|
|
33
|
+
return _configDir;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Get the crewswarm state directory.
|
|
38
|
+
* Used for: chat-history, spending.json, token-usage.json, logs, etc.
|
|
39
|
+
*/
|
|
40
|
+
export function getStateDir() {
|
|
41
|
+
if (_stateDir) return _stateDir;
|
|
42
|
+
|
|
43
|
+
if (process.env.CREWSWARM_TEST_MODE === "true") {
|
|
44
|
+
// Use a consistent temp dir for the entire test process (not per-call)
|
|
45
|
+
_stateDir = path.join(os.tmpdir(), `crewswarm-test-${process.pid}`);
|
|
46
|
+
} else {
|
|
47
|
+
_stateDir = process.env.CREWSWARM_STATE_DIR || path.join(os.homedir(), ".crewswarm");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
fs.mkdirSync(_stateDir, { recursive: true });
|
|
51
|
+
return _stateDir;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Get a path within the config directory.
|
|
56
|
+
* @param {...string} parts - Path components to join
|
|
57
|
+
*/
|
|
58
|
+
export function getConfigPath(...parts) {
|
|
59
|
+
return path.join(getConfigDir(), ...parts);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Get a path within the state directory.
|
|
64
|
+
* @param {...string} parts - Path components to join
|
|
65
|
+
*/
|
|
66
|
+
export function getStatePath(...parts) {
|
|
67
|
+
return path.join(getStateDir(), ...parts);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Reset cached paths (useful for testing).
|
|
72
|
+
*/
|
|
73
|
+
export function resetPaths() {
|
|
74
|
+
_configDir = null;
|
|
75
|
+
_stateDir = null;
|
|
76
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize user-supplied project / output directory paths.
|
|
3
|
+
* Fixes common dashboard typos (e.g. ~Desktop/foo instead of ~/Desktop/foo).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import os from "node:os";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {string|null|undefined} raw
|
|
11
|
+
* @returns {string|null} Absolute normalized path, or null if empty/invalid
|
|
12
|
+
*/
|
|
13
|
+
export function normalizeProjectDir(raw) {
|
|
14
|
+
if (raw == null) return null;
|
|
15
|
+
let s = String(raw).trim();
|
|
16
|
+
if (!s) return null;
|
|
17
|
+
|
|
18
|
+
const home = os.homedir();
|
|
19
|
+
|
|
20
|
+
// Typo: "~/Desktop/foo" pasted without slash → "~Desktop/foo"
|
|
21
|
+
if (/^~Desktop\//i.test(s)) {
|
|
22
|
+
s = path.join(home, "Desktop", s.replace(/^~Desktop\//i, ""));
|
|
23
|
+
} else if (/^~desktop$/i.test(s)) {
|
|
24
|
+
s = path.join(home, "Desktop");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Standard tilde expansion
|
|
28
|
+
if (s === "~") {
|
|
29
|
+
s = home;
|
|
30
|
+
} else if (s.startsWith("~/") || s.startsWith("~\\")) {
|
|
31
|
+
s = path.join(home, s.slice(2));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
if (path.isAbsolute(s)) {
|
|
36
|
+
return path.normalize(s);
|
|
37
|
+
}
|
|
38
|
+
// Relative paths: resolve from cwd (last resort)
|
|
39
|
+
return path.normalize(path.resolve(process.cwd(), s));
|
|
40
|
+
} catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* LLMs / sandboxes often embed the mistaken path `…/<repo>/~Desktop/<project>/` (missing `/` after `~`).
|
|
47
|
+
* Planning files land there while builds use the real `~/Desktop/<project>/`. Rewrite task text to the
|
|
48
|
+
* canonical project directory so @@READ_FILE paths resolve.
|
|
49
|
+
*
|
|
50
|
+
* @param {string} text
|
|
51
|
+
* @param {string} canonicalDir absolute project root (e.g. /Users/you/Desktop/stinky-1)
|
|
52
|
+
* @returns {string}
|
|
53
|
+
*/
|
|
54
|
+
export function rewriteWrongDesktopMirrorPaths(text, canonicalDir) {
|
|
55
|
+
if (!text || typeof text !== "string" || !canonicalDir) return text;
|
|
56
|
+
const canon = path.resolve(String(canonicalDir).trim()).replace(/\\/g, "/");
|
|
57
|
+
const base = path.basename(canon);
|
|
58
|
+
if (!base || base === "." || base === "..") return text;
|
|
59
|
+
|
|
60
|
+
const wrongUnderCwd = path
|
|
61
|
+
.join(process.cwd(), "~Desktop", base)
|
|
62
|
+
.replace(/\\/g, "/");
|
|
63
|
+
const wrongUnderCwdNorm = path
|
|
64
|
+
.normalize(path.join(process.cwd(), "~Desktop", base))
|
|
65
|
+
.replace(/\\/g, "/");
|
|
66
|
+
|
|
67
|
+
let out = text;
|
|
68
|
+
const pairs = [
|
|
69
|
+
[wrongUnderCwd, canon],
|
|
70
|
+
[wrongUnderCwdNorm, canon],
|
|
71
|
+
];
|
|
72
|
+
for (const [w, c] of pairs) {
|
|
73
|
+
if (w && w !== c && out.includes(w)) out = out.split(w).join(c);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Any absolute path segment `.../~Desktop/<basename>` (typo) → canon (keep suffix after basename)
|
|
77
|
+
const escapedBase = base.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
78
|
+
const re = new RegExp(
|
|
79
|
+
String.raw`([A-Za-z]:)?(?:/[^/\s"']*)*/\~Desktop/` + escapedBase + String.raw`(?=/|\s|"|'|$)`,
|
|
80
|
+
"gi",
|
|
81
|
+
);
|
|
82
|
+
out = out.replace(re, () => canon);
|
|
83
|
+
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* OpenCode (and similar sandboxes) treat absolute paths outside the active session root as
|
|
89
|
+
* `external_directory` and auto-reject in non-interactive mode. When cwd/projectDir is already
|
|
90
|
+
* the project root, rewrite obvious absolute/~/ paths to ./ so tools stay in-workspace.
|
|
91
|
+
*
|
|
92
|
+
* @param {string} taskText
|
|
93
|
+
* @param {string} projectDir
|
|
94
|
+
* @returns {string}
|
|
95
|
+
*/
|
|
96
|
+
export function rewriteTaskPathsRelativeToProjectRoot(taskText, projectDir) {
|
|
97
|
+
if (!taskText || typeof taskText !== "string" || !projectDir) return taskText;
|
|
98
|
+
let canon;
|
|
99
|
+
try {
|
|
100
|
+
canon = path.resolve(String(projectDir).trim()).replace(/\\/g, "/");
|
|
101
|
+
} catch {
|
|
102
|
+
return taskText;
|
|
103
|
+
}
|
|
104
|
+
const noTrail = canon.replace(/\/+$/, "");
|
|
105
|
+
const esc = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
106
|
+
let out = taskText;
|
|
107
|
+
out = out.replace(new RegExp(esc(noTrail) + "/", "g"), "./");
|
|
108
|
+
const base = path.basename(noTrail);
|
|
109
|
+
if (base && base !== "." && base !== "..") {
|
|
110
|
+
const homeDesk = path.join(os.homedir(), "Desktop", base).replace(/\\/g, "/");
|
|
111
|
+
if (homeDesk === noTrail) {
|
|
112
|
+
out = out.replace(
|
|
113
|
+
new RegExp(`~\\/Desktop\\/${esc(base)}\\/`, "g"),
|
|
114
|
+
"./",
|
|
115
|
+
);
|
|
116
|
+
out = out.replace(
|
|
117
|
+
new RegExp(`~/Desktop/${esc(base)}/`, "g"),
|
|
118
|
+
"./",
|
|
119
|
+
);
|
|
120
|
+
out = out.replace(
|
|
121
|
+
new RegExp(`~/Desktop/${esc(base)}(?=[/\\s"'\\)\\]>|$])`, "g"),
|
|
122
|
+
".",
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return out;
|
|
127
|
+
}
|