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,323 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# fresh-machine-smoke.sh — Clone-to-first-build verification on a clean environment.
|
|
3
|
+
#
|
|
4
|
+
# Simulates a brand-new machine: temp dir, no existing config, fresh install.
|
|
5
|
+
# Requires GROQ_API_KEY in the environment (only external dependency).
|
|
6
|
+
#
|
|
7
|
+
# Usage:
|
|
8
|
+
# GROQ_API_KEY=gsk_... bash scripts/fresh-machine-smoke.sh
|
|
9
|
+
#
|
|
10
|
+
# Exit codes:
|
|
11
|
+
# 0 — all checks passed
|
|
12
|
+
# 1 — one or more checks failed
|
|
13
|
+
#
|
|
14
|
+
# What it tests:
|
|
15
|
+
# 1. Prerequisites (Node ≥ 20, git)
|
|
16
|
+
# 2. Clone into a temp dir
|
|
17
|
+
# 3. npm ci
|
|
18
|
+
# 4. Bootstrap minimal config (token + Groq key)
|
|
19
|
+
# 5. openswitchctl doctor (config blockers only — services not started yet)
|
|
20
|
+
# 6. Start the full stack
|
|
21
|
+
# 7. Wait for agents to connect
|
|
22
|
+
# 8. Dispatch one task to crew-coder → verify output file
|
|
23
|
+
# 9. Dispatch one task to crew-main → verify text reply
|
|
24
|
+
# 10. Teardown
|
|
25
|
+
#
|
|
26
|
+
# Transcript is printed to stdout; pipe to tee to capture:
|
|
27
|
+
# GROQ_API_KEY=... bash scripts/fresh-machine-smoke.sh | tee /tmp/fresh-machine-run.txt
|
|
28
|
+
|
|
29
|
+
set -euo pipefail
|
|
30
|
+
|
|
31
|
+
# ── Colour helpers ──────────────────────────────────────────────────────────
|
|
32
|
+
GRN="\033[32m" RED="\033[31m" YLW="\033[33m" BLD="\033[1m" RST="\033[0m" DIM="\033[2m"
|
|
33
|
+
pass() { printf "${GRN}✅ ${RST}%s\n" "$1"; }
|
|
34
|
+
fail() { printf "${RED}❌ ${RST}${BLD}%s${RST}\n" "$1"; FAILED=$((FAILED+1)); }
|
|
35
|
+
warn() { printf "${YLW}⚠️ ${RST}%s\n" "$1"; }
|
|
36
|
+
step() { printf "\n${BLD}${DIM}── %s ──${RST}\n" "$1"; }
|
|
37
|
+
banner(){ printf "\n${BLD}%s${RST}\n" "$1"; }
|
|
38
|
+
FAILED=0
|
|
39
|
+
|
|
40
|
+
local_repo_path() {
|
|
41
|
+
local src="$1"
|
|
42
|
+
if [[ "$src" == file://* ]]; then
|
|
43
|
+
printf "%s\n" "${src#file://}"
|
|
44
|
+
return 0
|
|
45
|
+
fi
|
|
46
|
+
if [[ -d "$src/.git" ]]; then
|
|
47
|
+
printf "%s\n" "$src"
|
|
48
|
+
return 0
|
|
49
|
+
fi
|
|
50
|
+
return 1
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export_repo_snapshot() {
|
|
54
|
+
local src="$1"
|
|
55
|
+
local dest="$2"
|
|
56
|
+
local archive_file
|
|
57
|
+
archive_file="$(mktemp "${TMPDIR:-/tmp}/fresh-smoke-archive.XXXXXX.tar")"
|
|
58
|
+
mkdir -p "$dest"
|
|
59
|
+
git -C "$src" archive --format=tar -o "$archive_file" HEAD
|
|
60
|
+
tar -xf "$archive_file" -C "$dest"
|
|
61
|
+
rm -f "$archive_file"
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
run_npm_ci() {
|
|
65
|
+
local log_file="$1"
|
|
66
|
+
: > "$log_file"
|
|
67
|
+
npm ci --prefer-offline >"$log_file" 2>&1 &
|
|
68
|
+
local pid=$!
|
|
69
|
+
local ticks=0
|
|
70
|
+
printf " Installing dependencies"
|
|
71
|
+
while kill -0 "$pid" 2>/dev/null; do
|
|
72
|
+
printf "."
|
|
73
|
+
sleep 2
|
|
74
|
+
ticks=$((ticks + 1))
|
|
75
|
+
if (( ticks % 10 == 0 )); then
|
|
76
|
+
local last_line
|
|
77
|
+
last_line="$(tail -n 1 "$log_file" 2>/dev/null || true)"
|
|
78
|
+
if [[ -n "$last_line" ]]; then
|
|
79
|
+
printf "\n${DIM} %s${RST}\n" "$last_line"
|
|
80
|
+
printf " Installing dependencies"
|
|
81
|
+
fi
|
|
82
|
+
fi
|
|
83
|
+
done
|
|
84
|
+
wait "$pid"
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
# ── Config ──────────────────────────────────────────────────────────────────
|
|
88
|
+
REPO_URL="${FRESH_SMOKE_REPO:-https://github.com/CrewSwarm/CrewSwarm.git}"
|
|
89
|
+
GROQ_API_KEY="${GROQ_API_KEY:-}"
|
|
90
|
+
RT_TOKEN="fresh-smoke-$(openssl rand -hex 8 2>/dev/null || echo 'testtoken')"
|
|
91
|
+
TIMEOUT_AGENTS=120 # seconds to wait for agents to connect
|
|
92
|
+
TIMEOUT_TASK=90 # seconds to wait for smoke dispatch
|
|
93
|
+
RT_PORT="${FRESH_SMOKE_RT_PORT:-18989}"
|
|
94
|
+
CREW_LEAD_PORT="${FRESH_SMOKE_CREW_LEAD_PORT:-5110}"
|
|
95
|
+
|
|
96
|
+
banner "🧪 CrewSwarm Fresh-Machine Smoke $(date -u '+%Y-%m-%d %H:%M UTC')"
|
|
97
|
+
printf "${DIM}Repo: %s${RST}\n" "$REPO_URL"
|
|
98
|
+
printf "${DIM}Token: %s${RST}\n" "$RT_TOKEN"
|
|
99
|
+
|
|
100
|
+
# ── 1. Prerequisites ────────────────────────────────────────────────────────
|
|
101
|
+
step "1 · Prerequisites"
|
|
102
|
+
|
|
103
|
+
NODE="${NODE:-node}"
|
|
104
|
+
if ! command -v "$NODE" &>/dev/null; then
|
|
105
|
+
fail "Node.js not found — install v20+: https://nodejs.org"
|
|
106
|
+
exit 1
|
|
107
|
+
fi
|
|
108
|
+
NODE_VER=$("$NODE" --version | sed 's/v//')
|
|
109
|
+
NODE_MAJOR=$(echo "$NODE_VER" | cut -d. -f1)
|
|
110
|
+
if [[ "$NODE_MAJOR" -lt 20 ]]; then
|
|
111
|
+
fail "Node.js v$NODE_VER — need v20+"; exit 1
|
|
112
|
+
fi
|
|
113
|
+
pass "Node.js v$NODE_VER"
|
|
114
|
+
|
|
115
|
+
if ! command -v git &>/dev/null; then
|
|
116
|
+
fail "git not found"; exit 1
|
|
117
|
+
fi
|
|
118
|
+
pass "git $(git --version | awk '{print $3}')"
|
|
119
|
+
|
|
120
|
+
if [[ -z "$GROQ_API_KEY" ]]; then
|
|
121
|
+
warn "GROQ_API_KEY not set — LLM calls will fail. Set it and re-run."
|
|
122
|
+
warn " export GROQ_API_KEY=gsk_..."
|
|
123
|
+
# Don't exit — doctor/config checks can still run
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
# ── 2. Clone ────────────────────────────────────────────────────────────────
|
|
127
|
+
step "2 · Clone"
|
|
128
|
+
WORK_DIR=$(mktemp -d)
|
|
129
|
+
CLONE_DIR="$WORK_DIR/CrewSwarm"
|
|
130
|
+
export TMPDIR="$WORK_DIR/tmp"
|
|
131
|
+
mkdir -p "$TMPDIR"
|
|
132
|
+
trap 'echo ""; warn "Cleaning up $WORK_DIR ..."; kill $(jobs -p) 2>/dev/null || true; rm -rf "$WORK_DIR"' EXIT
|
|
133
|
+
|
|
134
|
+
printf "${DIM} Cloning into %s ...${RST}\n" "$CLONE_DIR"
|
|
135
|
+
if LOCAL_REPO="$(local_repo_path "$REPO_URL")"; then
|
|
136
|
+
if export_repo_snapshot "$LOCAL_REPO" "$CLONE_DIR"; then
|
|
137
|
+
pass "Exported local HEAD snapshot $LOCAL_REPO → $CLONE_DIR"
|
|
138
|
+
else
|
|
139
|
+
fail "local snapshot export failed"; exit 1
|
|
140
|
+
fi
|
|
141
|
+
elif git clone --depth=1 "$REPO_URL" "$CLONE_DIR" --quiet 2>&1; then
|
|
142
|
+
pass "Cloned $REPO_URL → $CLONE_DIR"
|
|
143
|
+
else
|
|
144
|
+
fail "git clone failed"; exit 1
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
cd "$CLONE_DIR"
|
|
148
|
+
|
|
149
|
+
# ── 3. npm install ──────────────────────────────────────────────────────────
|
|
150
|
+
step "3 · npm install"
|
|
151
|
+
NPM_LOG="$WORK_DIR/fresh-smoke-npm.log"
|
|
152
|
+
if run_npm_ci "$NPM_LOG"; then
|
|
153
|
+
printf "\n"
|
|
154
|
+
tail -3 "$NPM_LOG" 2>/dev/null || true
|
|
155
|
+
pass "npm ci succeeded"
|
|
156
|
+
else
|
|
157
|
+
printf "\n${DIM}npm log:${RST}\n"
|
|
158
|
+
tail -40 "$NPM_LOG" 2>/dev/null || true
|
|
159
|
+
fail "npm ci failed"; exit 1
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
# ── 4. Bootstrap config ─────────────────────────────────────────────────────
|
|
163
|
+
step "4 · Bootstrap config"
|
|
164
|
+
CFG_DIR="$WORK_DIR/.crewswarm"
|
|
165
|
+
mkdir -p "$CFG_DIR"
|
|
166
|
+
|
|
167
|
+
# Redirect config to temp dir for isolation
|
|
168
|
+
export HOME="$WORK_DIR"
|
|
169
|
+
export CREWSWARM_DIR="$CLONE_DIR"
|
|
170
|
+
export CREWSWARM_CONFIG_DIR="$CFG_DIR"
|
|
171
|
+
|
|
172
|
+
# config.json — RT token
|
|
173
|
+
printf '{"rt":{"authToken":"%s"}}\n' "$RT_TOKEN" > "$CFG_DIR/config.json"
|
|
174
|
+
pass "config.json — RT token written"
|
|
175
|
+
|
|
176
|
+
# crewswarm.json — Groq provider + 5 core agents
|
|
177
|
+
node -e "
|
|
178
|
+
const fs = require('fs');
|
|
179
|
+
const key = process.env.GROQ_API_KEY || '';
|
|
180
|
+
const cfg = {
|
|
181
|
+
_note: 'fresh-machine-smoke bootstrap',
|
|
182
|
+
agents: [
|
|
183
|
+
{ id: 'crew-lead', model: 'groq/llama-3.3-70b-versatile' },
|
|
184
|
+
{ id: 'crew-main', model: 'groq/llama-3.3-70b-versatile' },
|
|
185
|
+
{ id: 'crew-coder', model: 'groq/llama-3.3-70b-versatile' },
|
|
186
|
+
{ id: 'crew-qa', model: 'groq/llama-3.3-70b-versatile' },
|
|
187
|
+
{ id: 'crew-fixer', model: 'groq/llama-3.3-70b-versatile' },
|
|
188
|
+
{ id: 'crew-pm', model: 'groq/llama-3.3-70b-versatile' },
|
|
189
|
+
{ id: 'crew-orchestrator', model: 'groq/llama-3.3-70b-versatile' },
|
|
190
|
+
{ id: 'crew-judge', model: 'groq/llama-3.3-70b-versatile' },
|
|
191
|
+
],
|
|
192
|
+
providers: {
|
|
193
|
+
groq: { apiKey: key, baseUrl: 'https://api.groq.com/openai/v1' }
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
fs.writeFileSync(process.env.CREWSWARM_CONFIG_DIR + '/crewswarm.json', JSON.stringify(cfg, null, 2));
|
|
197
|
+
"
|
|
198
|
+
pass "crewswarm.json — Groq + 5 agents written"
|
|
199
|
+
|
|
200
|
+
# cmd-allowlist
|
|
201
|
+
printf '{"patterns":["npm *","node *","npx *"]}\n' > "$CFG_DIR/cmd-allowlist.json"
|
|
202
|
+
printf '{}' > "$CFG_DIR/agent-prompts.json"
|
|
203
|
+
pass "cmd-allowlist.json + agent-prompts.json written"
|
|
204
|
+
|
|
205
|
+
# ── 5. openswitchctl doctor (config only — services not started) ────────────
|
|
206
|
+
step "5 · openswitchctl doctor"
|
|
207
|
+
CTL="$CLONE_DIR/scripts/openswitchctl"
|
|
208
|
+
chmod +x "$CTL"
|
|
209
|
+
|
|
210
|
+
# doctor exits 1 if blockers exist; warnings about services down are expected here
|
|
211
|
+
if bash "$CTL" doctor 2>&1; then
|
|
212
|
+
pass "doctor — all config checks passed"
|
|
213
|
+
else
|
|
214
|
+
# Warnings about services not running are normal at this stage — check if any CONFIG blockers
|
|
215
|
+
doctor_out=$(bash "$CTL" doctor 2>&1 || true)
|
|
216
|
+
echo "$doctor_out"
|
|
217
|
+
if echo "$doctor_out" | grep -q "❌"; then
|
|
218
|
+
fail "doctor — config blockers present (see above)"
|
|
219
|
+
exit 1
|
|
220
|
+
else
|
|
221
|
+
pass "doctor — config OK (services not yet started, as expected)"
|
|
222
|
+
fi
|
|
223
|
+
fi
|
|
224
|
+
|
|
225
|
+
# ── 6. Start the stack ──────────────────────────────────────────────────────
|
|
226
|
+
step "6 · Start stack"
|
|
227
|
+
export CREWSWARM_RT_AUTH_TOKEN="$RT_TOKEN"
|
|
228
|
+
export CREWSWARM_RT_REQUIRE_TOKEN=1
|
|
229
|
+
export CREWSWARM_RT_PORT="$RT_PORT"
|
|
230
|
+
export CREWSWARM_RT_URL="ws://127.0.0.1:${RT_PORT}"
|
|
231
|
+
export CREWSWARM_OPENCODE_ENABLED=0
|
|
232
|
+
export CREW_LEAD_PORT="$CREW_LEAD_PORT"
|
|
233
|
+
export CREW_LEAD_URL="http://127.0.0.1:${CREW_LEAD_PORT}"
|
|
234
|
+
export CREWSWARM_DISABLE_PGREP_FALLBACK=1
|
|
235
|
+
|
|
236
|
+
"$NODE" "$CLONE_DIR/scripts/opencrew-rt-daemon.mjs" >> /tmp/fresh-smoke-rt.log 2>&1 &
|
|
237
|
+
sleep 3
|
|
238
|
+
"$NODE" "$CLONE_DIR/crew-lead.mjs" >> /tmp/fresh-smoke-lead.log 2>&1 &
|
|
239
|
+
sleep 2
|
|
240
|
+
"$NODE" "$CLONE_DIR/scripts/start-crew.mjs" >> /tmp/fresh-smoke-bridges.log 2>&1
|
|
241
|
+
sleep 5
|
|
242
|
+
pass "Stack processes started"
|
|
243
|
+
|
|
244
|
+
# ── 7. Wait for agents ──────────────────────────────────────────────────────
|
|
245
|
+
step "7 · Wait for agents to connect"
|
|
246
|
+
T_END=$((SECONDS + TIMEOUT_AGENTS))
|
|
247
|
+
CONNECTED=false
|
|
248
|
+
printf " Polling RT bus"
|
|
249
|
+
while [[ $SECONDS -lt $T_END ]]; do
|
|
250
|
+
STATUS=$(curl -sf "http://127.0.0.1:${RT_PORT}/status" 2>/dev/null || echo '{}')
|
|
251
|
+
if echo "$STATUS" | grep -q '"crew-coder"' && echo "$STATUS" | grep -q '"crew-main"'; then
|
|
252
|
+
CONNECTED=true
|
|
253
|
+
printf "\n"
|
|
254
|
+
break
|
|
255
|
+
fi
|
|
256
|
+
printf "."
|
|
257
|
+
sleep 3
|
|
258
|
+
done
|
|
259
|
+
|
|
260
|
+
if [[ "$CONNECTED" == "true" ]]; then
|
|
261
|
+
AGENT_COUNT=$(echo "$STATUS" | "$NODE" -e "let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{try{const j=JSON.parse(d);console.log((j.agents||[]).length);}catch{console.log(0);}})" 2>/dev/null || echo "?")
|
|
262
|
+
pass "Agents connected ($AGENT_COUNT online)"
|
|
263
|
+
else
|
|
264
|
+
fail "Agents did not connect within ${TIMEOUT_AGENTS}s"
|
|
265
|
+
printf "${DIM}RT log:${RST}\n"; tail -20 /tmp/fresh-smoke-rt.log || true
|
|
266
|
+
printf "${DIM}Bridge log:${RST}\n"; tail -20 /tmp/fresh-smoke-bridges.log || true
|
|
267
|
+
exit 1
|
|
268
|
+
fi
|
|
269
|
+
|
|
270
|
+
# ── 8. Dispatch → crew-coder ─────────────────────────────────────────────────
|
|
271
|
+
step "8 · Dispatch → crew-coder (file write)"
|
|
272
|
+
RUN_ID="fm$(date +%s | tail -c 6)"
|
|
273
|
+
OUT_FILE="$CLONE_DIR/test-output/fresh-smoke/coder-${RUN_ID}.txt"
|
|
274
|
+
EXPECTED="FRESH_SMOKE_OK_${RUN_ID}"
|
|
275
|
+
mkdir -p "$(dirname "$OUT_FILE")"
|
|
276
|
+
|
|
277
|
+
TASK_TEXT="Create this file with @@WRITE_FILE: ${OUT_FILE}
|
|
278
|
+
Write exactly one line: ${EXPECTED}
|
|
279
|
+
No extra text."
|
|
280
|
+
|
|
281
|
+
printf " Dispatching to crew-coder ...\n"
|
|
282
|
+
DISPATCH_REPLY=$(
|
|
283
|
+
timeout "$TIMEOUT_TASK" "$NODE" "$CLONE_DIR/gateway-bridge.mjs" \
|
|
284
|
+
--send crew-coder "$TASK_TEXT" 2>/dev/null || echo ""
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
# Give file system a moment
|
|
288
|
+
sleep 3
|
|
289
|
+
|
|
290
|
+
if [[ -f "$OUT_FILE" ]] && grep -q "$EXPECTED" "$OUT_FILE" 2>/dev/null; then
|
|
291
|
+
pass "crew-coder wrote $OUT_FILE with correct content"
|
|
292
|
+
else
|
|
293
|
+
fail "crew-coder did not produce $OUT_FILE with '$EXPECTED'"
|
|
294
|
+
printf "${DIM}Reply: %s${RST}\n" "${DISPATCH_REPLY:0:200}"
|
|
295
|
+
FAILED=$((FAILED+1))
|
|
296
|
+
fi
|
|
297
|
+
|
|
298
|
+
# ── 9. Dispatch → crew-main (text reply) ────────────────────────────────────
|
|
299
|
+
step "9 · Dispatch → crew-main (text reply)"
|
|
300
|
+
MARKER="MAIN_OK_${RUN_ID}"
|
|
301
|
+
printf " Dispatching to crew-main ...\n"
|
|
302
|
+
MAIN_REPLY=$(
|
|
303
|
+
timeout "$TIMEOUT_TASK" "$NODE" "$CLONE_DIR/gateway-bridge.mjs" \
|
|
304
|
+
--send crew-main "Reply with exactly: $MARKER" 2>/dev/null || echo ""
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
if echo "$MAIN_REPLY" | grep -q "$MARKER"; then
|
|
308
|
+
pass "crew-main replied with $MARKER"
|
|
309
|
+
else
|
|
310
|
+
fail "crew-main did not reply with '$MARKER'"
|
|
311
|
+
printf "${DIM}Reply: %s${RST}\n" "${MAIN_REPLY:0:200}"
|
|
312
|
+
FAILED=$((FAILED+1))
|
|
313
|
+
fi
|
|
314
|
+
|
|
315
|
+
# ── 10. Summary ──────────────────────────────────────────────────────────────
|
|
316
|
+
banner "━━━ Fresh-Machine Smoke Results ━━━"
|
|
317
|
+
if [[ "$FAILED" -eq 0 ]]; then
|
|
318
|
+
printf "${GRN}${BLD}✅ All checks passed — CrewSwarm works on a clean install.${RST}\n\n"
|
|
319
|
+
exit 0
|
|
320
|
+
else
|
|
321
|
+
printf "${RED}${BLD}❌ $FAILED check(s) failed.${RST}\n\n"
|
|
322
|
+
exit 1
|
|
323
|
+
fi
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { execFileSync } from 'node:child_process';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
|
|
7
|
+
const repoRoot = process.cwd();
|
|
8
|
+
const changelogPath = path.join(repoRoot, 'CHANGELOG.md');
|
|
9
|
+
const packagePath = path.join(repoRoot, 'package.json');
|
|
10
|
+
const args = new Set(process.argv.slice(2));
|
|
11
|
+
const releaseMode = args.has('--release');
|
|
12
|
+
|
|
13
|
+
const CATEGORY_MAP = new Map([
|
|
14
|
+
['feat', 'Added'],
|
|
15
|
+
['feature', 'Added'],
|
|
16
|
+
['fix', 'Fixed'],
|
|
17
|
+
['bugfix', 'Fixed'],
|
|
18
|
+
['perf', 'Changed'],
|
|
19
|
+
['refactor', 'Changed'],
|
|
20
|
+
['change', 'Changed'],
|
|
21
|
+
['chore', 'Changed'],
|
|
22
|
+
['docs', 'Documentation'],
|
|
23
|
+
['doc', 'Documentation'],
|
|
24
|
+
['test', 'Testing'],
|
|
25
|
+
['build', 'Infrastructure'],
|
|
26
|
+
['ci', 'Infrastructure'],
|
|
27
|
+
['infra', 'Infrastructure'],
|
|
28
|
+
['security', 'Security'],
|
|
29
|
+
['sec', 'Security'],
|
|
30
|
+
['deps', 'Changed']
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
function readJson(filePath) {
|
|
34
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function git(argsList) {
|
|
38
|
+
return execFileSync('git', argsList, { cwd: repoRoot, encoding: 'utf8' }).trim();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function escapeRegExp(value) {
|
|
42
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function getTrackedIssuesFromEvent() {
|
|
46
|
+
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
47
|
+
if (!eventPath || !fs.existsSync(eventPath)) {
|
|
48
|
+
return new Map();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
const payload = readJson(eventPath);
|
|
53
|
+
const issues = new Map();
|
|
54
|
+
const addIssue = (number, title) => {
|
|
55
|
+
if (!number || !title) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
issues.set(String(number), title.trim());
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
addIssue(payload.pull_request?.number, payload.pull_request?.title);
|
|
62
|
+
addIssue(payload.issue?.number, payload.issue?.title);
|
|
63
|
+
|
|
64
|
+
for (const commit of payload.commits ?? []) {
|
|
65
|
+
const matches = commit.message?.match(/#(\d+)/g) ?? [];
|
|
66
|
+
for (const match of matches) {
|
|
67
|
+
const issueNumber = match.slice(1);
|
|
68
|
+
addIssue(issueNumber, commit.message.split('\n')[0]);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return issues;
|
|
73
|
+
} catch {
|
|
74
|
+
return new Map();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function getLatestVersionSection(changelog) {
|
|
79
|
+
const matches = [...changelog.matchAll(/^## \[(?!Unreleased\])([^\]]+)\]/gm)];
|
|
80
|
+
return matches[0]?.[1] ?? null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function normalizeVersionTag(version) {
|
|
84
|
+
if (!version) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
return version.startsWith('v') ? version : `v${version}`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function getCommitRange(baseTag) {
|
|
91
|
+
if (!baseTag) {
|
|
92
|
+
return 'HEAD';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
git(['rev-parse', '--verify', baseTag]);
|
|
97
|
+
return `${baseTag}..HEAD`;
|
|
98
|
+
} catch {
|
|
99
|
+
return 'HEAD';
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function parseCommit(raw, eventIssues) {
|
|
104
|
+
const [hash, subject, date] = raw.split('\x1f');
|
|
105
|
+
const conventional = subject.match(/^([A-Za-z]+)(?:\(([^)]+)\))?!?:\s+(.+)$/);
|
|
106
|
+
const token = conventional?.[1]?.toLowerCase();
|
|
107
|
+
const scope = conventional?.[2]?.trim();
|
|
108
|
+
const summary = (conventional?.[3] ?? subject).trim();
|
|
109
|
+
const category = CATEGORY_MAP.get(token) ?? 'Changed';
|
|
110
|
+
const issueRefs = [...new Set((subject.match(/#(\d+)/g) ?? []).map((match) => match.slice(1)))];
|
|
111
|
+
const issueNotes = issueRefs.map((issue) => `#${issue}${eventIssues.get(issue) ? ` ${eventIssues.get(issue)}` : ''}`);
|
|
112
|
+
|
|
113
|
+
let line = `- ${summary}`;
|
|
114
|
+
if (scope) {
|
|
115
|
+
line += ` (${scope})`;
|
|
116
|
+
}
|
|
117
|
+
if (issueNotes.length > 0) {
|
|
118
|
+
line += ` — ${issueNotes.join(', ')}`;
|
|
119
|
+
}
|
|
120
|
+
line += ` (${date})`;
|
|
121
|
+
|
|
122
|
+
return { hash, category, line };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function buildSections(commits) {
|
|
126
|
+
const buckets = new Map();
|
|
127
|
+
|
|
128
|
+
for (const category of ['Added', 'Changed', 'Fixed', 'Security', 'Documentation', 'Testing', 'Infrastructure']) {
|
|
129
|
+
buckets.set(category, []);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
for (const commit of commits) {
|
|
133
|
+
buckets.get(commit.category)?.push(commit.line);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return [...buckets.entries()].filter(([, entries]) => entries.length > 0);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function buildUnreleasedSection(commits, generatedOn) {
|
|
140
|
+
const sections = buildSections(commits);
|
|
141
|
+
const lines = [
|
|
142
|
+
'## [Unreleased]',
|
|
143
|
+
'',
|
|
144
|
+
`> Auto-generated from git history${process.env.GITHUB_EVENT_NAME ? ' and GitHub event metadata' : ''}.`,
|
|
145
|
+
`> Last generated: ${generatedOn}. Run \`npm run changelog:generate\` to refresh this section.`,
|
|
146
|
+
''
|
|
147
|
+
];
|
|
148
|
+
|
|
149
|
+
if (sections.length === 0) {
|
|
150
|
+
lines.push('No unreleased changes detected since the last tagged release.', '');
|
|
151
|
+
return lines.join('\n');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
for (const [category, entries] of sections) {
|
|
155
|
+
lines.push(`### ${category}`, '');
|
|
156
|
+
lines.push(...entries, '');
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return lines.join('\n').trimEnd();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function replaceUnreleasedSection(changelog, newSection) {
|
|
163
|
+
const unreleasedPattern = /^## \[Unreleased\][\s\S]*?(?=^## \[|\Z)/m;
|
|
164
|
+
if (unreleasedPattern.test(changelog)) {
|
|
165
|
+
return changelog.replace(unreleasedPattern, newSection + '\n\n');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return changelog.replace(
|
|
169
|
+
/^(The format is based on .*?\.\n)/s,
|
|
170
|
+
`$1\n${newSection}\n\n`
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function finalizeRelease(changelog, version, releaseDate) {
|
|
175
|
+
const unreleasedPattern = /^## \[Unreleased\][\s\S]*?(?=^## \[|\Z)/m;
|
|
176
|
+
const unreleasedMatch = changelog.match(unreleasedPattern);
|
|
177
|
+
if (!unreleasedMatch) {
|
|
178
|
+
return changelog;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const unreleasedBody = unreleasedMatch[0]
|
|
182
|
+
.replace(/^## \[Unreleased\]\n*/m, '')
|
|
183
|
+
.replace(/^> .*$/gm, '')
|
|
184
|
+
.trim();
|
|
185
|
+
|
|
186
|
+
const releaseHeading = `## [${version}] - ${releaseDate}`;
|
|
187
|
+
const releaseBlock = unreleasedBody
|
|
188
|
+
? `${releaseHeading}\n\n${unreleasedBody}\n`
|
|
189
|
+
: `${releaseHeading}\n\n- No categorized changes.\n`;
|
|
190
|
+
|
|
191
|
+
return changelog.replace(
|
|
192
|
+
unreleasedPattern,
|
|
193
|
+
`## [Unreleased]\n\n> Auto-generated from git history and GitHub event metadata.\n> Last generated: ${releaseDate}. Run \`npm run changelog:generate\` to refresh this section.\n\n${releaseBlock}\n`
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const changelog = fs.readFileSync(changelogPath, 'utf8');
|
|
198
|
+
const pkg = readJson(packagePath);
|
|
199
|
+
const latestVersion = getLatestVersionSection(changelog);
|
|
200
|
+
const latestTag = normalizeVersionTag(latestVersion);
|
|
201
|
+
const commitRange = getCommitRange(latestTag);
|
|
202
|
+
const rawLog = git([
|
|
203
|
+
'log',
|
|
204
|
+
'--reverse',
|
|
205
|
+
'--date=short',
|
|
206
|
+
`--pretty=format:%H%x1f%s%x1f%ad`,
|
|
207
|
+
commitRange
|
|
208
|
+
]);
|
|
209
|
+
|
|
210
|
+
const eventIssues = getTrackedIssuesFromEvent();
|
|
211
|
+
const commits = rawLog
|
|
212
|
+
.split('\n')
|
|
213
|
+
.filter(Boolean)
|
|
214
|
+
.map((line) => parseCommit(line, eventIssues))
|
|
215
|
+
.filter((entry) => entry.hash);
|
|
216
|
+
|
|
217
|
+
const generatedOn = new Date().toISOString().slice(0, 10);
|
|
218
|
+
let nextChangelog = replaceUnreleasedSection(changelog, buildUnreleasedSection(commits, generatedOn));
|
|
219
|
+
|
|
220
|
+
if (releaseMode) {
|
|
221
|
+
nextChangelog = finalizeRelease(nextChangelog, pkg.version, generatedOn);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
fs.writeFileSync(changelogPath, nextChangelog);
|
|
225
|
+
process.stdout.write(
|
|
226
|
+
`Updated CHANGELOG.md using ${commits.length} commit${commits.length === 1 ? '' : 's'} from ${commitRange}.\n`
|
|
227
|
+
);
|