@zeyue0329/xiaoma-cli 1.0.49 → 1.6.4
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/.github/workflows/quality.yaml +116 -0
- package/.husky/pre-commit +26 -0
- package/.idea/codeStyles/Project.xml +60 -0
- package/.idea/codeStyles/codeStyleConfig.xml +5 -0
- package/.idea/jsLibraryMappings.xml +6 -0
- package/.idea/modules.xml +1 -1
- package/.idea/vcs.xml +0 -1
- package/.idea/workspace.xml +40 -24
- package/.markdownlint-cli2.yaml +41 -0
- package/.prettierignore +12 -0
- package/.vscode/settings.json +96 -0
- package/LICENSE +30 -0
- package/README.md +108 -2
- package/XIAOMA-CLI-GUIDE.md +512 -0
- package/{.idea/XiaoMa-Cli.iml → XiaoMa-Cli.iml} +1 -1
- package/custom/src/agents/commit-poet/commit-poet.agent.yaml +129 -0
- package/custom/src/agents/commit-poet/installation-guide.md +36 -0
- package/custom/src/agents/toolsmith/installation-guide.md +36 -0
- package/custom/src/agents/toolsmith/toolsmith-sidecar/instructions.md +70 -0
- package/custom/src/agents/toolsmith/toolsmith-sidecar/knowledge/bundlers.md +111 -0
- package/custom/src/agents/toolsmith/toolsmith-sidecar/knowledge/deploy.md +70 -0
- package/custom/src/agents/toolsmith/toolsmith-sidecar/knowledge/docs.md +114 -0
- package/custom/src/agents/toolsmith/toolsmith-sidecar/knowledge/installers.md +134 -0
- package/custom/src/agents/toolsmith/toolsmith-sidecar/knowledge/modules.md +160 -0
- package/custom/src/agents/toolsmith/toolsmith-sidecar/knowledge/tests.md +103 -0
- package/custom/src/agents/toolsmith/toolsmith-sidecar/memories.md +17 -0
- package/custom/src/agents/toolsmith/toolsmith.agent.yaml +108 -0
- package/docs/BUNDLE_DISTRIBUTION_SETUP.md +95 -0
- package/docs/agent-customization-guide.md +208 -0
- package/docs/custom-agent-installation.md +183 -0
- package/docs/document-sharding-guide.md +449 -0
- package/docs/explanation/advanced-elicitation.md +49 -0
- package/docs/explanation/adversarial-review.md +59 -0
- package/docs/explanation/brainstorming.md +33 -0
- package/docs/explanation/established-projects-faq.md +50 -0
- package/docs/explanation/party-mode.md +59 -0
- package/docs/explanation/preventing-agent-conflicts.md +112 -0
- package/docs/explanation/project-context.md +157 -0
- package/docs/explanation/quick-dev-new-preview.md +73 -0
- package/docs/explanation/quick-flow.md +77 -0
- package/docs/explanation/why-solutioning-matters.md +77 -0
- package/docs/how-to/customize-xiaoma.md +172 -0
- package/docs/how-to/established-projects.md +117 -0
- package/docs/how-to/get-answers-about-xiaoma.md +134 -0
- package/docs/how-to/install-xiaoma.md +107 -0
- package/docs/how-to/non-interactive-installation.md +171 -0
- package/docs/how-to/project-context.md +136 -0
- package/docs/how-to/quick-fixes.md +123 -0
- package/docs/how-to/shard-large-documents.md +78 -0
- package/docs/how-to/upgrade-to-v6.md +100 -0
- package/docs/ide-info/auggie.md +31 -0
- package/docs/ide-info/claude-code.md +25 -0
- package/docs/ide-info/cline.md +31 -0
- package/docs/ide-info/codex.md +21 -0
- package/docs/ide-info/crush.md +30 -0
- package/docs/ide-info/cursor.md +25 -0
- package/docs/ide-info/gemini.md +25 -0
- package/docs/ide-info/github-copilot.md +26 -0
- package/docs/ide-info/iflow.md +33 -0
- package/docs/ide-info/kilo.md +24 -0
- package/docs/ide-info/opencode.md +24 -0
- package/docs/ide-info/qwen.md +25 -0
- package/docs/ide-info/roo.md +27 -0
- package/docs/ide-info/rovo-dev.md +388 -0
- package/docs/ide-info/trae.md +25 -0
- package/docs/ide-info/windsurf.md +22 -0
- package/docs/index.md +60 -0
- package/docs/installers-bundlers/ide-injections.md +186 -0
- package/docs/installers-bundlers/installers-modules-platforms-reference.md +379 -0
- package/docs/rag/rag.md +856 -0
- package/docs/reference/agents.md +28 -0
- package/docs/reference/commands.md +145 -0
- package/docs/reference/modules.md +76 -0
- package/docs/reference/testing.md +106 -0
- package/docs/reference/workflow-map.md +89 -0
- package/docs/roadmap.mdx +136 -0
- package/docs/superpowers/plans/2026-03-11-upstream-sync-with-branding.md +586 -0
- package/docs/tutorials/getting-started.md +273 -0
- package/docs/v4-to-v6-upgrade.md +220 -0
- package/docs/v6-open-items.md +17 -0
- package/docs/web-bundles-gemini-gpt-guide.md +468 -0
- package/docs/zh-cn/404.md +9 -0
- package/docs/zh-cn/_STYLE_GUIDE.md +370 -0
- package/docs/zh-cn/explanation/advanced-elicitation.md +62 -0
- package/docs/zh-cn/explanation/adversarial-review.md +71 -0
- package/docs/zh-cn/explanation/brainstorming.md +43 -0
- package/docs/zh-cn/explanation/established-projects-faq.md +60 -0
- package/docs/zh-cn/explanation/party-mode.md +79 -0
- package/docs/zh-cn/explanation/preventing-agent-conflicts.md +137 -0
- package/docs/zh-cn/explanation/project-context.md +176 -0
- package/docs/zh-cn/explanation/quick-flow.md +93 -0
- package/docs/zh-cn/explanation/why-solutioning-matters.md +90 -0
- package/docs/zh-cn/how-to/customize-xiaoma.md +182 -0
- package/docs/zh-cn/how-to/established-projects.md +134 -0
- package/docs/zh-cn/how-to/get-answers-about-xiaoma.md +144 -0
- package/docs/zh-cn/how-to/install-xiaoma.md +105 -0
- package/docs/zh-cn/how-to/non-interactive-installation.md +181 -0
- package/docs/zh-cn/how-to/project-context.md +152 -0
- package/docs/zh-cn/how-to/quick-fixes.md +140 -0
- package/docs/zh-cn/how-to/shard-large-documents.md +86 -0
- package/docs/zh-cn/how-to/upgrade-to-v6.md +120 -0
- package/docs/zh-cn/index.md +69 -0
- package/docs/zh-cn/reference/agents.md +41 -0
- package/docs/zh-cn/reference/commands.md +166 -0
- package/docs/zh-cn/reference/modules.md +94 -0
- package/docs/zh-cn/reference/testing.md +122 -0
- package/docs/zh-cn/reference/workflow-map.md +104 -0
- package/docs/zh-cn/roadmap.mdx +152 -0
- package/docs/zh-cn/tutorials/getting-started.md +300 -0
- package/eslint.config.mjs +144 -0
- package/package.json +56 -58
- package/prettier.config.mjs +32 -0
- package/src/core/_module-installer/install-config.yaml +29 -0
- package/src/core/_module-installer/installer.js +60 -0
- package/src/core/agents/xiaoma-master.agent.yaml +30 -0
- package/src/core/agents/xiaoma-skill-manifest.yaml +3 -0
- package/src/core/agents/xiaoma-web-orchestrator.agent.xml +113 -0
- package/src/core/module-help.csv +10 -0
- package/src/core/module.yaml +25 -0
- package/src/core/resources/excalidraw/README.md +160 -0
- package/src/core/resources/excalidraw/excalidraw-helpers.md +127 -0
- package/src/core/resources/excalidraw/library-loader.md +50 -0
- package/src/core/resources/excalidraw/validate-json-instructions.md +79 -0
- package/src/core/tasks/advanced-elicitation-methods.csv +51 -0
- package/src/core/tasks/advanced-elicitation.xml +116 -0
- package/src/core/tasks/editorial-review-prose.xml +102 -0
- package/src/core/tasks/editorial-review-structure.xml +208 -0
- package/src/core/tasks/help.md +92 -0
- package/src/core/tasks/index-docs.xml +65 -0
- package/src/core/tasks/review-adversarial-general.xml +49 -0
- package/src/core/tasks/review-edge-case-hunter.xml +63 -0
- package/src/core/tasks/shard-doc.xml +108 -0
- package/src/core/tasks/validate-workflow.xml +89 -0
- package/src/core/tasks/workflow.xml +235 -0
- package/src/core/tasks/xiaoma-help/SKILL.md +6 -0
- package/src/core/tasks/xiaoma-help/workflow.md +88 -0
- package/src/core/tasks/xiaoma-help/xiaoma-skill-manifest.yaml +1 -0
- package/src/core/tasks/xiaoma-review-adversarial-general/SKILL.md +6 -0
- package/src/core/tasks/xiaoma-review-adversarial-general/workflow.md +32 -0
- package/src/core/tasks/xiaoma-review-adversarial-general/xiaoma-skill-manifest.yaml +1 -0
- package/src/core/tasks/xiaoma-review-edge-case-hunter/SKILL.md +6 -0
- package/src/core/tasks/xiaoma-review-edge-case-hunter/workflow.md +62 -0
- package/src/core/tasks/xiaoma-review-edge-case-hunter/xiaoma-skill-manifest.yaml +1 -0
- package/src/core/tasks/xiaoma-skill-manifest.yaml +19 -0
- package/src/core/tools/shard-doc.xml +109 -0
- package/src/core/workflows/advanced-elicitation/methods.csv +51 -0
- package/src/core/workflows/advanced-elicitation/workflow.md +138 -0
- package/src/core/workflows/advanced-elicitation/workflow.xml +118 -0
- package/src/core/workflows/advanced-elicitation/xiaoma-skill-manifest.yaml +3 -0
- package/src/core/workflows/brainstorming/brain-methods.csv +62 -0
- package/src/core/workflows/brainstorming/steps/step-01-session-setup.md +210 -0
- package/src/core/workflows/brainstorming/steps/step-01b-continue.md +122 -0
- package/src/core/workflows/brainstorming/steps/step-02a-user-selected.md +225 -0
- package/src/core/workflows/brainstorming/steps/step-02b-ai-recommended.md +237 -0
- package/src/core/workflows/brainstorming/steps/step-02c-random-selection.md +209 -0
- package/src/core/workflows/brainstorming/steps/step-02d-progressive-flow.md +264 -0
- package/src/core/workflows/brainstorming/steps/step-03-technique-execution.md +399 -0
- package/src/core/workflows/brainstorming/steps/step-04-idea-organization.md +303 -0
- package/src/core/workflows/brainstorming/template.md +15 -0
- package/src/core/workflows/brainstorming/workflow.md +60 -0
- package/src/core/workflows/brainstorming/xiaoma-skill-manifest.yaml +3 -0
- package/src/core/workflows/party-mode/steps/step-01-agent-loading.md +138 -0
- package/src/core/workflows/party-mode/steps/step-02-discussion-orchestration.md +187 -0
- package/src/core/workflows/party-mode/steps/step-03-graceful-exit.md +168 -0
- package/src/core/workflows/party-mode/workflow.md +194 -0
- package/src/core/workflows/party-mode/xiaoma-skill-manifest.yaml +3 -0
- package/src/utility/agent-components/activation-rules.txt +6 -0
- package/src/utility/agent-components/activation-steps.txt +14 -0
- package/src/utility/agent-components/agent-command-header.md +1 -0
- package/src/utility/agent-components/agent.customize.template.yaml +41 -0
- package/src/utility/agent-components/handler-action.txt +4 -0
- package/src/utility/agent-components/handler-data.txt +5 -0
- package/src/utility/agent-components/handler-exec.txt +6 -0
- package/src/utility/agent-components/handler-multi.txt +13 -0
- package/src/utility/agent-components/handler-tmpl.txt +5 -0
- package/src/utility/agent-components/handler-validate-workflow.txt +7 -0
- package/src/utility/agent-components/handler-workflow.txt +10 -0
- package/src/utility/agent-components/menu-handlers.txt +6 -0
- package/src/utility/models/action-command-header.md +0 -0
- package/src/utility/models/agent-activation-ide.xml +51 -0
- package/src/utility/models/agent-activation-web.xml +50 -0
- package/src/utility/models/agent-command-header.md +1 -0
- package/src/utility/models/agent-config-template.md +23 -0
- package/src/utility/models/agent-in-team-activation.xml +3 -0
- package/src/utility/models/fragments/activation-rules.xml +7 -0
- package/src/utility/models/fragments/activation-steps.xml +16 -0
- package/src/utility/models/fragments/handler-action.xml +4 -0
- package/src/utility/models/fragments/handler-data.xml +5 -0
- package/src/utility/models/fragments/handler-exec.xml +6 -0
- package/src/utility/models/fragments/handler-multi.xml +14 -0
- package/src/utility/models/fragments/handler-tmpl.xml +5 -0
- package/src/utility/models/fragments/handler-validate-workflow.xml +7 -0
- package/src/utility/models/fragments/handler-workflow.xml +9 -0
- package/src/utility/models/fragments/menu-handlers.xml +6 -0
- package/src/utility/models/fragments/web-bundle-activation-steps.xml +32 -0
- package/src/utility/templates/agent.customize.template.yaml +42 -0
- package/src/xmc/_module-installer/install-config.yaml +53 -0
- package/src/xmc/_module-installer/installer.js +131 -0
- package/src/xmc/_module-installer/platform-specifics/claude-code.js +35 -0
- package/src/xmc/_module-installer/platform-specifics/windsurf.js +32 -0
- package/src/xmc/agents/analyst.agent.yaml +43 -0
- package/src/xmc/agents/architect.agent.yaml +29 -0
- package/src/xmc/agents/dev.agent.yaml +38 -0
- package/src/xmc/agents/pm.agent.yaml +44 -0
- package/src/xmc/agents/qa.agent.yaml +58 -0
- package/src/xmc/agents/quick-flow-solo-dev.agent.yaml +36 -0
- package/src/xmc/agents/sm.agent.yaml +37 -0
- package/src/xmc/agents/tech-writer/tech-writer-sidecar/documentation-standards.md +224 -0
- package/src/xmc/agents/tech-writer/tech-writer.agent.yaml +46 -0
- package/src/xmc/agents/tech-writer/xiaoma-skill-manifest.yaml +3 -0
- package/src/xmc/agents/ux-designer.agent.yaml +27 -0
- package/src/xmc/agents/xiaoma-skill-manifest.yaml +39 -0
- package/src/xmc/data/project-context-template.md +26 -0
- package/src/xmc/module-help.csv +32 -0
- package/src/xmc/module.yaml +50 -0
- package/src/xmc/sub-modules/claude-code/config.yaml +5 -0
- package/src/xmc/sub-modules/claude-code/injections.yaml +242 -0
- package/src/xmc/sub-modules/claude-code/readme.md +87 -0
- package/src/xmc/sub-modules/claude-code/sub-agents/xiaoma-analysis/api-documenter.md +102 -0
- package/src/xmc/sub-modules/claude-code/sub-agents/xiaoma-analysis/codebase-analyzer.md +82 -0
- package/src/xmc/sub-modules/claude-code/sub-agents/xiaoma-analysis/data-analyst.md +101 -0
- package/src/xmc/sub-modules/claude-code/sub-agents/xiaoma-analysis/pattern-detector.md +84 -0
- package/src/xmc/sub-modules/claude-code/sub-agents/xiaoma-planning/dependency-mapper.md +83 -0
- package/src/xmc/sub-modules/claude-code/sub-agents/xiaoma-planning/epic-optimizer.md +81 -0
- package/src/xmc/sub-modules/claude-code/sub-agents/xiaoma-planning/requirements-analyst.md +61 -0
- package/src/xmc/sub-modules/claude-code/sub-agents/xiaoma-planning/technical-decisions-curator.md +168 -0
- package/src/xmc/sub-modules/claude-code/sub-agents/xiaoma-planning/trend-spotter.md +115 -0
- package/src/xmc/sub-modules/claude-code/sub-agents/xiaoma-planning/user-journey-mapper.md +123 -0
- package/src/xmc/sub-modules/claude-code/sub-agents/xiaoma-planning/user-researcher.md +72 -0
- package/src/xmc/sub-modules/claude-code/sub-agents/xiaoma-research/market-researcher.md +51 -0
- package/src/xmc/sub-modules/claude-code/sub-agents/xiaoma-research/tech-debt-auditor.md +106 -0
- package/src/xmc/sub-modules/claude-code/sub-agents/xiaoma-review/document-reviewer.md +102 -0
- package/src/xmc/sub-modules/claude-code/sub-agents/xiaoma-review/technical-evaluator.md +68 -0
- package/src/xmc/sub-modules/claude-code/sub-agents/xiaoma-review/test-coverage-analyzer.md +108 -0
- package/src/xmc/teams/default-party.csv +20 -0
- package/src/xmc/teams/team-fullstack.yaml +12 -0
- package/src/xmc/testarch/knowledge/api-request.md +303 -0
- package/src/xmc/testarch/knowledge/auth-session.md +356 -0
- package/src/xmc/testarch/knowledge/burn-in.md +273 -0
- package/src/xmc/testarch/knowledge/ci-burn-in.md +675 -0
- package/src/xmc/testarch/knowledge/component-tdd.md +486 -0
- package/src/xmc/testarch/knowledge/contract-testing.md +957 -0
- package/src/xmc/testarch/knowledge/data-factories.md +500 -0
- package/src/xmc/testarch/knowledge/email-auth.md +721 -0
- package/src/xmc/testarch/knowledge/error-handling.md +725 -0
- package/src/xmc/testarch/knowledge/feature-flags.md +750 -0
- package/src/xmc/testarch/knowledge/file-utils.md +260 -0
- package/src/xmc/testarch/knowledge/fixture-architecture.md +401 -0
- package/src/xmc/testarch/knowledge/fixtures-composition.md +382 -0
- package/src/xmc/testarch/knowledge/intercept-network-call.md +280 -0
- package/src/xmc/testarch/knowledge/log.md +294 -0
- package/src/xmc/testarch/knowledge/network-error-monitor.md +272 -0
- package/src/xmc/testarch/knowledge/network-first.md +486 -0
- package/src/xmc/testarch/knowledge/network-recorder.md +265 -0
- package/src/xmc/testarch/knowledge/nfr-criteria.md +670 -0
- package/src/xmc/testarch/knowledge/overview.md +284 -0
- package/src/xmc/testarch/knowledge/playwright-config.md +730 -0
- package/src/xmc/testarch/knowledge/probability-impact.md +601 -0
- package/src/xmc/testarch/knowledge/recurse.md +296 -0
- package/src/xmc/testarch/knowledge/risk-governance.md +615 -0
- package/src/xmc/testarch/knowledge/selective-testing.md +732 -0
- package/src/xmc/testarch/knowledge/selector-resilience.md +527 -0
- package/src/xmc/testarch/knowledge/test-healing-patterns.md +644 -0
- package/src/xmc/testarch/knowledge/test-levels-framework.md +473 -0
- package/src/xmc/testarch/knowledge/test-priorities-matrix.md +373 -0
- package/src/xmc/testarch/knowledge/test-quality.md +664 -0
- package/src/xmc/testarch/knowledge/timing-debugging.md +372 -0
- package/src/xmc/testarch/knowledge/visual-debugging.md +524 -0
- package/src/xmc/testarch/tea-index.csv +33 -0
- package/src/xmc/workflows/1-analysis/create-product-brief/product-brief.template.md +10 -0
- package/src/xmc/workflows/1-analysis/create-product-brief/steps/step-01-init.md +177 -0
- package/src/xmc/workflows/1-analysis/create-product-brief/steps/step-01b-continue.md +161 -0
- package/src/xmc/workflows/1-analysis/create-product-brief/steps/step-02-vision.md +199 -0
- package/src/xmc/workflows/1-analysis/create-product-brief/steps/step-03-users.md +202 -0
- package/src/xmc/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md +205 -0
- package/src/xmc/workflows/1-analysis/create-product-brief/steps/step-05-scope.md +219 -0
- package/src/xmc/workflows/1-analysis/create-product-brief/steps/step-06-complete.md +162 -0
- package/src/xmc/workflows/1-analysis/create-product-brief/workflow.md +57 -0
- package/src/xmc/workflows/1-analysis/create-product-brief/xiaoma-skill-manifest.yaml +3 -0
- package/src/xmc/workflows/1-analysis/research/domain-steps/step-01-init.md +137 -0
- package/src/xmc/workflows/1-analysis/research/domain-steps/step-02-domain-analysis.md +229 -0
- package/src/xmc/workflows/1-analysis/research/domain-steps/step-03-competitive-landscape.md +238 -0
- package/src/xmc/workflows/1-analysis/research/domain-steps/step-04-regulatory-focus.md +206 -0
- package/src/xmc/workflows/1-analysis/research/domain-steps/step-05-technical-trends.md +234 -0
- package/src/xmc/workflows/1-analysis/research/domain-steps/step-06-research-synthesis.md +444 -0
- package/src/xmc/workflows/1-analysis/research/market-steps/step-01-init.md +182 -0
- package/src/xmc/workflows/1-analysis/research/market-steps/step-02-customer-behavior.md +237 -0
- package/src/xmc/workflows/1-analysis/research/market-steps/step-03-customer-pain-points.md +249 -0
- package/src/xmc/workflows/1-analysis/research/market-steps/step-04-customer-decisions.md +259 -0
- package/src/xmc/workflows/1-analysis/research/market-steps/step-05-competitive-analysis.md +177 -0
- package/src/xmc/workflows/1-analysis/research/market-steps/step-06-research-completion.md +476 -0
- package/src/xmc/workflows/1-analysis/research/research.template.md +29 -0
- package/src/xmc/workflows/1-analysis/research/technical-steps/step-01-init.md +137 -0
- package/src/xmc/workflows/1-analysis/research/technical-steps/step-02-technical-overview.md +239 -0
- package/src/xmc/workflows/1-analysis/research/technical-steps/step-03-integration-patterns.md +248 -0
- package/src/xmc/workflows/1-analysis/research/technical-steps/step-04-architectural-patterns.md +202 -0
- package/src/xmc/workflows/1-analysis/research/technical-steps/step-05-implementation-research.md +233 -0
- package/src/xmc/workflows/1-analysis/research/technical-steps/step-06-research-synthesis.md +487 -0
- package/src/xmc/workflows/1-analysis/research/workflow-domain-research.md +54 -0
- package/src/xmc/workflows/1-analysis/research/workflow-market-research.md +54 -0
- package/src/xmc/workflows/1-analysis/research/workflow-technical-research.md +54 -0
- package/src/xmc/workflows/1-analysis/research/xiaoma-skill-manifest.yaml +14 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/data/domain-complexity.csv +15 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/data/prd-purpose.md +197 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/data/project-types.csv +11 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-c/step-01-init.md +191 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-c/step-01b-continue.md +152 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-c/step-02-discovery.md +224 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-c/step-02b-vision.md +154 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-c/step-02c-executive-summary.md +170 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-c/step-03-success.md +226 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md +213 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-c/step-05-domain.md +207 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-c/step-06-innovation.md +226 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-c/step-07-project-type.md +237 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-c/step-08-scoping.md +228 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-c/step-09-functional.md +231 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-c/step-10-nonfunctional.md +242 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-c/step-11-polish.md +217 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-c/step-12-complete.md +124 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-e/step-e-01-discovery.md +247 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-e/step-e-01b-legacy-conversion.md +208 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-e/step-e-02-review.md +249 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-e/step-e-03-edit.md +253 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-e/step-e-04-complete.md +168 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md +226 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-v/step-v-02-format-detection.md +191 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-v/step-v-02b-parity-check.md +209 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-v/step-v-03-density-validation.md +174 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-v/step-v-04-brief-coverage-validation.md +214 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-v/step-v-05-measurability-validation.md +228 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-v/step-v-06-traceability-validation.md +217 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-v/step-v-07-implementation-leakage-validation.md +205 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-v/step-v-08-domain-compliance-validation.md +243 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-v/step-v-09-project-type-validation.md +263 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-v/step-v-10-smart-validation.md +209 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-v/step-v-11-holistic-quality-validation.md +264 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-v/step-v-12-completeness-validation.md +242 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/steps-v/step-v-13-report-complete.md +231 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/templates/prd-template.md +10 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/workflow-create-prd.md +63 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/workflow-edit-prd.md +65 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/workflow-validate-prd.md +63 -0
- package/src/xmc/workflows/2-plan-workflows/create-prd/xiaoma-skill-manifest.yaml +14 -0
- package/src/xmc/workflows/2-plan-workflows/create-ux-design/steps/step-01-init.md +135 -0
- package/src/xmc/workflows/2-plan-workflows/create-ux-design/steps/step-01b-continue.md +127 -0
- package/src/xmc/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md +190 -0
- package/src/xmc/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md +216 -0
- package/src/xmc/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md +219 -0
- package/src/xmc/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md +234 -0
- package/src/xmc/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md +252 -0
- package/src/xmc/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md +254 -0
- package/src/xmc/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md +224 -0
- package/src/xmc/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md +224 -0
- package/src/xmc/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md +241 -0
- package/src/xmc/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md +248 -0
- package/src/xmc/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md +237 -0
- package/src/xmc/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md +264 -0
- package/src/xmc/workflows/2-plan-workflows/create-ux-design/steps/step-14-complete.md +171 -0
- package/src/xmc/workflows/2-plan-workflows/create-ux-design/ux-design-template.md +13 -0
- package/src/xmc/workflows/2-plan-workflows/create-ux-design/workflow.md +42 -0
- package/src/xmc/workflows/2-plan-workflows/create-ux-design/xiaoma-skill-manifest.yaml +3 -0
- package/src/xmc/workflows/3-solutioning/check-implementation-readiness/steps/step-01-document-discovery.md +184 -0
- package/src/xmc/workflows/3-solutioning/check-implementation-readiness/steps/step-02-prd-analysis.md +172 -0
- package/src/xmc/workflows/3-solutioning/check-implementation-readiness/steps/step-03-epic-coverage-validation.md +173 -0
- package/src/xmc/workflows/3-solutioning/check-implementation-readiness/steps/step-04-ux-alignment.md +133 -0
- package/src/xmc/workflows/3-solutioning/check-implementation-readiness/steps/step-05-epic-quality-review.md +245 -0
- package/src/xmc/workflows/3-solutioning/check-implementation-readiness/steps/step-06-final-assessment.md +129 -0
- package/src/xmc/workflows/3-solutioning/check-implementation-readiness/templates/readiness-report-template.md +4 -0
- package/src/xmc/workflows/3-solutioning/check-implementation-readiness/workflow.md +54 -0
- package/src/xmc/workflows/3-solutioning/check-implementation-readiness/xiaoma-skill-manifest.yaml +3 -0
- package/src/xmc/workflows/3-solutioning/create-architecture/architecture-decision-template.md +12 -0
- package/src/xmc/workflows/3-solutioning/create-architecture/data/domain-complexity.csv +13 -0
- package/src/xmc/workflows/3-solutioning/create-architecture/data/project-types.csv +7 -0
- package/src/xmc/workflows/3-solutioning/create-architecture/steps/step-01-init.md +153 -0
- package/src/xmc/workflows/3-solutioning/create-architecture/steps/step-01b-continue.md +173 -0
- package/src/xmc/workflows/3-solutioning/create-architecture/steps/step-02-context.md +224 -0
- package/src/xmc/workflows/3-solutioning/create-architecture/steps/step-03-starter.md +329 -0
- package/src/xmc/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md +318 -0
- package/src/xmc/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md +359 -0
- package/src/xmc/workflows/3-solutioning/create-architecture/steps/step-06-structure.md +379 -0
- package/src/xmc/workflows/3-solutioning/create-architecture/steps/step-07-validation.md +359 -0
- package/src/xmc/workflows/3-solutioning/create-architecture/steps/step-08-complete.md +76 -0
- package/src/xmc/workflows/3-solutioning/create-architecture/workflow.md +49 -0
- package/src/xmc/workflows/3-solutioning/create-architecture/xiaoma-skill-manifest.yaml +3 -0
- package/src/xmc/workflows/3-solutioning/create-epics-and-stories/steps/step-01-validate-prerequisites.md +259 -0
- package/src/xmc/workflows/3-solutioning/create-epics-and-stories/steps/step-02-design-epics.md +233 -0
- package/src/xmc/workflows/3-solutioning/create-epics-and-stories/steps/step-03-create-stories.md +272 -0
- package/src/xmc/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md +149 -0
- package/src/xmc/workflows/3-solutioning/create-epics-and-stories/templates/epics-template.md +57 -0
- package/src/xmc/workflows/3-solutioning/create-epics-and-stories/workflow.md +58 -0
- package/src/xmc/workflows/3-solutioning/create-epics-and-stories/xiaoma-skill-manifest.yaml +3 -0
- package/src/xmc/workflows/4-implementation/code-review/checklist.md +23 -0
- package/src/xmc/workflows/4-implementation/code-review/discover-inputs.md +88 -0
- package/src/xmc/workflows/4-implementation/code-review/workflow.md +271 -0
- package/src/xmc/workflows/4-implementation/code-review/xiaoma-skill-manifest.yaml +3 -0
- package/src/xmc/workflows/4-implementation/correct-course/checklist.md +288 -0
- package/src/xmc/workflows/4-implementation/correct-course/workflow.md +274 -0
- package/src/xmc/workflows/4-implementation/correct-course/xiaoma-skill-manifest.yaml +3 -0
- package/src/xmc/workflows/4-implementation/create-story/checklist.md +357 -0
- package/src/xmc/workflows/4-implementation/create-story/discover-inputs.md +88 -0
- package/src/xmc/workflows/4-implementation/create-story/template.md +49 -0
- package/src/xmc/workflows/4-implementation/create-story/workflow.md +388 -0
- package/src/xmc/workflows/4-implementation/create-story/xiaoma-skill-manifest.yaml +3 -0
- package/src/xmc/workflows/4-implementation/dev-story/checklist.md +80 -0
- package/src/xmc/workflows/4-implementation/dev-story/workflow.md +457 -0
- package/src/xmc/workflows/4-implementation/dev-story/xiaoma-skill-manifest.yaml +3 -0
- package/src/xmc/workflows/4-implementation/retrospective/workflow.md +1485 -0
- package/src/xmc/workflows/4-implementation/retrospective/xiaoma-skill-manifest.yaml +3 -0
- package/src/xmc/workflows/4-implementation/sprint-planning/checklist.md +33 -0
- package/src/xmc/workflows/4-implementation/sprint-planning/sprint-status-template.yaml +56 -0
- package/src/xmc/workflows/4-implementation/sprint-planning/workflow.md +271 -0
- package/src/xmc/workflows/4-implementation/sprint-planning/xiaoma-skill-manifest.yaml +3 -0
- package/src/xmc/workflows/4-implementation/sprint-status/workflow.md +267 -0
- package/src/xmc/workflows/4-implementation/sprint-status/xiaoma-skill-manifest.yaml +3 -0
- package/src/xmc/workflows/document-project/checklist.md +245 -0
- package/src/xmc/workflows/document-project/documentation-requirements.csv +12 -0
- package/src/xmc/workflows/document-project/instructions.md +128 -0
- package/src/xmc/workflows/document-project/templates/deep-dive-template.md +345 -0
- package/src/xmc/workflows/document-project/templates/index-template.md +169 -0
- package/src/xmc/workflows/document-project/templates/project-overview-template.md +103 -0
- package/src/xmc/workflows/document-project/templates/project-scan-report-schema.json +160 -0
- package/src/xmc/workflows/document-project/templates/source-tree-template.md +135 -0
- package/src/xmc/workflows/document-project/workflow.md +39 -0
- package/src/xmc/workflows/document-project/workflows/deep-dive-instructions.md +297 -0
- package/src/xmc/workflows/document-project/workflows/deep-dive-workflow.md +42 -0
- package/src/xmc/workflows/document-project/workflows/full-scan-instructions.md +1105 -0
- package/src/xmc/workflows/document-project/workflows/full-scan-workflow.md +42 -0
- package/src/xmc/workflows/document-project/xiaoma-skill-manifest.yaml +3 -0
- package/src/xmc/workflows/generate-project-context/project-context-template.md +21 -0
- package/src/xmc/workflows/generate-project-context/steps/step-01-discover.md +184 -0
- package/src/xmc/workflows/generate-project-context/steps/step-02-generate.md +318 -0
- package/src/xmc/workflows/generate-project-context/steps/step-03-complete.md +278 -0
- package/src/xmc/workflows/generate-project-context/workflow.md +49 -0
- package/src/xmc/workflows/generate-project-context/xiaoma-skill-manifest.yaml +3 -0
- package/src/xmc/workflows/qa-generate-e2e-tests/checklist.md +33 -0
- package/src/xmc/workflows/qa-generate-e2e-tests/workflow.md +143 -0
- package/src/xmc/workflows/qa-generate-e2e-tests/xiaoma-skill-manifest.yaml +3 -0
- package/src/xmc/workflows/xiaoma-quick-flow/quick-dev/steps/step-01-mode-detection.md +174 -0
- package/src/xmc/workflows/xiaoma-quick-flow/quick-dev/steps/step-02-context-gathering.md +118 -0
- package/src/xmc/workflows/xiaoma-quick-flow/quick-dev/steps/step-03-execute.md +111 -0
- package/src/xmc/workflows/xiaoma-quick-flow/quick-dev/steps/step-04-self-check.md +111 -0
- package/src/xmc/workflows/xiaoma-quick-flow/quick-dev/steps/step-05-adversarial-review.md +98 -0
- package/src/xmc/workflows/xiaoma-quick-flow/quick-dev/steps/step-06-resolve-findings.md +146 -0
- package/src/xmc/workflows/xiaoma-quick-flow/quick-dev/workflow.md +50 -0
- package/src/xmc/workflows/xiaoma-quick-flow/quick-dev/xiaoma-skill-manifest.yaml +3 -0
- package/src/xmc/workflows/xiaoma-quick-flow/quick-spec/steps/step-01-understand.md +189 -0
- package/src/xmc/workflows/xiaoma-quick-flow/quick-spec/steps/step-02-investigate.md +143 -0
- package/src/xmc/workflows/xiaoma-quick-flow/quick-spec/steps/step-03-generate.md +126 -0
- package/src/xmc/workflows/xiaoma-quick-flow/quick-spec/steps/step-04-review.md +198 -0
- package/src/xmc/workflows/xiaoma-quick-flow/quick-spec/tech-spec-template.md +74 -0
- package/src/xmc/workflows/xiaoma-quick-flow/quick-spec/workflow.md +79 -0
- package/src/xmc/workflows/xiaoma-quick-flow/quick-spec/xiaoma-skill-manifest.yaml +3 -0
- package/src/xmc/workflows/xiaoma-quick-flow/xiaoma-quick-dev-new-preview/SKILL.md +6 -0
- package/src/xmc/workflows/xiaoma-quick-flow/xiaoma-quick-dev-new-preview/steps/step-01-clarify-and-route.md +54 -0
- package/src/xmc/workflows/xiaoma-quick-flow/xiaoma-quick-dev-new-preview/steps/step-02-plan.md +39 -0
- package/src/xmc/workflows/xiaoma-quick-flow/xiaoma-quick-dev-new-preview/steps/step-03-implement.md +35 -0
- package/src/xmc/workflows/xiaoma-quick-flow/xiaoma-quick-dev-new-preview/steps/step-04-review.md +55 -0
- package/src/xmc/workflows/xiaoma-quick-flow/xiaoma-quick-dev-new-preview/steps/step-05-present.md +19 -0
- package/src/xmc/workflows/xiaoma-quick-flow/xiaoma-quick-dev-new-preview/tech-spec-template.md +90 -0
- package/src/xmc/workflows/xiaoma-quick-flow/xiaoma-quick-dev-new-preview/workflow.md +84 -0
- package/src/xmc/workflows/xiaoma-quick-flow/xiaoma-quick-dev-new-preview/xiaoma-skill-manifest.yaml +1 -0
- package/test/README.md +295 -0
- package/test/adversarial-review-tests/README.md +56 -0
- package/test/adversarial-review-tests/sample-content.md +46 -0
- package/test/adversarial-review-tests/test-cases.yaml +103 -0
- package/test/fixtures/agent-schema/invalid/critical-actions/actions-as-string.agent.yaml +27 -0
- package/test/fixtures/agent-schema/invalid/critical-actions/empty-string-in-actions.agent.yaml +30 -0
- package/test/fixtures/agent-schema/invalid/menu/empty-menu.agent.yaml +22 -0
- package/test/fixtures/agent-schema/invalid/menu/missing-menu.agent.yaml +20 -0
- package/test/fixtures/agent-schema/invalid/menu-commands/empty-command-target.agent.yaml +25 -0
- package/test/fixtures/agent-schema/invalid/menu-commands/no-command-target.agent.yaml +24 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/camel-case.agent.yaml +25 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/compound-invalid-format.agent.yaml +25 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/compound-mismatched-kebab.agent.yaml +25 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/duplicate-triggers.agent.yaml +31 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/empty-trigger.agent.yaml +25 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/leading-asterisk.agent.yaml +25 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/snake-case.agent.yaml +25 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/trigger-with-spaces.agent.yaml +25 -0
- package/test/fixtures/agent-schema/invalid/metadata/empty-module-string.agent.yaml +26 -0
- package/test/fixtures/agent-schema/invalid/metadata/empty-name.agent.yaml +24 -0
- package/test/fixtures/agent-schema/invalid/metadata/extra-metadata-fields.agent.yaml +27 -0
- package/test/fixtures/agent-schema/invalid/metadata/missing-id.agent.yaml +23 -0
- package/test/fixtures/agent-schema/invalid/persona/empty-principles-array.agent.yaml +24 -0
- package/test/fixtures/agent-schema/invalid/persona/empty-string-in-principles.agent.yaml +27 -0
- package/test/fixtures/agent-schema/invalid/persona/extra-persona-fields.agent.yaml +27 -0
- package/test/fixtures/agent-schema/invalid/persona/missing-role.agent.yaml +24 -0
- package/test/fixtures/agent-schema/invalid/prompts/empty-content.agent.yaml +29 -0
- package/test/fixtures/agent-schema/invalid/prompts/extra-prompt-fields.agent.yaml +31 -0
- package/test/fixtures/agent-schema/invalid/prompts/missing-content.agent.yaml +28 -0
- package/test/fixtures/agent-schema/invalid/prompts/missing-id.agent.yaml +28 -0
- package/test/fixtures/agent-schema/invalid/top-level/empty-file.agent.yaml +5 -0
- package/test/fixtures/agent-schema/invalid/top-level/extra-top-level-keys.agent.yaml +28 -0
- package/test/fixtures/agent-schema/invalid/top-level/missing-agent-key.agent.yaml +11 -0
- package/test/fixtures/agent-schema/invalid/yaml-errors/invalid-indentation.agent.yaml +19 -0
- package/test/fixtures/agent-schema/invalid/yaml-errors/malformed-yaml.agent.yaml +18 -0
- package/test/fixtures/agent-schema/valid/critical-actions/empty-critical-actions.agent.yaml +24 -0
- package/test/fixtures/agent-schema/valid/critical-actions/no-critical-actions.agent.yaml +22 -0
- package/test/fixtures/agent-schema/valid/critical-actions/valid-critical-actions.agent.yaml +27 -0
- package/test/fixtures/agent-schema/valid/menu/multiple-menu-items.agent.yaml +31 -0
- package/test/fixtures/agent-schema/valid/menu/single-menu-item.agent.yaml +22 -0
- package/test/fixtures/agent-schema/valid/menu-commands/all-command-types.agent.yaml +38 -0
- package/test/fixtures/agent-schema/valid/menu-commands/multiple-commands.agent.yaml +23 -0
- package/test/fixtures/agent-schema/valid/menu-triggers/compound-triggers.agent.yaml +31 -0
- package/test/fixtures/agent-schema/valid/menu-triggers/kebab-case-triggers.agent.yaml +34 -0
- package/test/fixtures/agent-schema/valid/metadata/core-agent-with-module.agent.yaml +24 -0
- package/test/fixtures/agent-schema/valid/metadata/empty-module-name-in-path.agent.yaml +24 -0
- package/test/fixtures/agent-schema/valid/metadata/malformed-path-treated-as-core.agent.yaml +24 -0
- package/test/fixtures/agent-schema/valid/metadata/module-agent-correct.agent.yaml +24 -0
- package/test/fixtures/agent-schema/valid/metadata/module-agent-missing-module.agent.yaml +23 -0
- package/test/fixtures/agent-schema/valid/metadata/wrong-module-value.agent.yaml +24 -0
- package/test/fixtures/agent-schema/valid/persona/complete-persona.agent.yaml +24 -0
- package/test/fixtures/agent-schema/valid/prompts/empty-prompts.agent.yaml +24 -0
- package/test/fixtures/agent-schema/valid/prompts/no-prompts.agent.yaml +22 -0
- package/test/fixtures/agent-schema/valid/prompts/valid-prompts-minimal.agent.yaml +28 -0
- package/test/fixtures/agent-schema/valid/prompts/valid-prompts-with-description.agent.yaml +30 -0
- package/test/fixtures/agent-schema/valid/top-level/minimal-core-agent.agent.yaml +24 -0
- package/test/fixtures/file-refs-csv/invalid/all-empty-workflow.csv +3 -0
- package/test/fixtures/file-refs-csv/invalid/empty-data.csv +1 -0
- package/test/fixtures/file-refs-csv/invalid/no-workflow-column.csv +3 -0
- package/test/fixtures/file-refs-csv/invalid/unresolvable-vars.csv +3 -0
- package/test/fixtures/file-refs-csv/valid/core-style.csv +3 -0
- package/test/fixtures/file-refs-csv/valid/minimal.csv +2 -0
- package/test/fixtures/file-refs-csv/valid/xmc-style.csv +3 -0
- package/test/test-agent-schema.js +387 -0
- package/test/test-cli-integration.sh +159 -0
- package/test/test-file-refs-csv.js +133 -0
- package/test/test-install-to-xiaoma.js +154 -0
- package/test/test-installation-components.js +1802 -0
- package/test/test-rehype-plugins.mjs +1050 -0
- package/test/test-workflow-path-regex.js +88 -0
- package/test/unit-test-schema.js +133 -0
- package/tools/build-docs.mjs +464 -0
- package/tools/cli/README.md +60 -0
- package/tools/cli/bundlers/bundle-web.js +179 -0
- package/tools/cli/bundlers/bundlers/bundle-web.js +179 -0
- package/tools/cli/bundlers/bundlers/test-analyst.js +28 -0
- package/tools/cli/bundlers/bundlers/test-bundler.js +119 -0
- package/tools/cli/bundlers/bundlers/web-bundler.js +1754 -0
- package/tools/cli/bundlers/test-analyst.js +28 -0
- package/tools/cli/bundlers/test-bundler.js +119 -0
- package/tools/cli/bundlers/web-bundler.js +1754 -0
- package/tools/cli/commands/agent-install.js +409 -0
- package/tools/cli/commands/build.js +458 -0
- package/tools/cli/commands/cleanup.js +144 -0
- package/tools/cli/commands/install.js +87 -0
- package/tools/cli/commands/list.js +43 -0
- package/tools/cli/commands/status.js +65 -0
- package/tools/cli/commands/uninstall.js +167 -0
- package/tools/cli/commands/update.js +28 -0
- package/tools/cli/external-official-modules.yaml +53 -0
- package/tools/cli/installers/install-messages.yaml +39 -0
- package/tools/cli/installers/lib/core/config-collector.js +1285 -0
- package/tools/cli/installers/lib/core/custom-module-cache.js +260 -0
- package/tools/cli/installers/lib/core/dependency-resolver.js +743 -0
- package/tools/cli/installers/lib/core/detector.js +223 -0
- package/tools/cli/installers/lib/core/ide-config-manager.js +157 -0
- package/tools/cli/installers/lib/core/installer.js +3195 -0
- package/tools/cli/installers/lib/core/manifest-generator.js +1374 -0
- package/tools/cli/installers/lib/core/manifest.js +1038 -0
- package/tools/cli/installers/lib/custom/handler.js +358 -0
- package/tools/cli/installers/lib/ide/_base-ide.js +674 -0
- package/tools/cli/installers/lib/ide/_config-driven.js +1053 -0
- package/tools/cli/installers/lib/ide/antigravity.js +510 -0
- package/tools/cli/installers/lib/ide/auggie.js +232 -0
- package/tools/cli/installers/lib/ide/claude-code.js +512 -0
- package/tools/cli/installers/lib/ide/cline.js +269 -0
- package/tools/cli/installers/lib/ide/codex.js +440 -0
- package/tools/cli/installers/lib/ide/crush.js +287 -0
- package/tools/cli/installers/lib/ide/cursor.js +400 -0
- package/tools/cli/installers/lib/ide/gemini.js +253 -0
- package/tools/cli/installers/lib/ide/github-copilot.js +699 -0
- package/tools/cli/installers/lib/ide/iflow.js +172 -0
- package/tools/cli/installers/lib/ide/kilo.js +269 -0
- package/tools/cli/installers/lib/ide/manager.js +304 -0
- package/tools/cli/installers/lib/ide/opencode.js +257 -0
- package/tools/cli/installers/lib/ide/platform-codes.js +100 -0
- package/tools/cli/installers/lib/ide/platform-codes.yaml +321 -0
- package/tools/cli/installers/lib/ide/qwen.js +372 -0
- package/tools/cli/installers/lib/ide/roo.js +324 -0
- package/tools/cli/installers/lib/ide/rovo-dev.js +290 -0
- package/tools/cli/installers/lib/ide/rovodev.js +257 -0
- package/tools/cli/installers/lib/ide/shared/agent-command-generator.js +181 -0
- package/tools/cli/installers/lib/ide/shared/module-injections.js +136 -0
- package/tools/cli/installers/lib/ide/shared/path-utils.js +364 -0
- package/tools/cli/installers/lib/ide/shared/skill-manifest.js +90 -0
- package/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js +368 -0
- package/tools/cli/installers/lib/ide/shared/workflow-command-generator.js +179 -0
- package/tools/cli/installers/lib/ide/shared/xiaoma-artifacts.js +181 -0
- package/tools/cli/installers/lib/ide/templates/agent-command-template.md +14 -0
- package/tools/cli/installers/lib/ide/templates/combined/antigravity.md +8 -0
- package/tools/cli/installers/lib/ide/templates/combined/default-agent.md +15 -0
- package/tools/cli/installers/lib/ide/templates/combined/default-task.md +10 -0
- package/tools/cli/installers/lib/ide/templates/combined/default-tool.md +10 -0
- package/tools/cli/installers/lib/ide/templates/combined/default-workflow-yaml.md +14 -0
- package/tools/cli/installers/lib/ide/templates/combined/default-workflow.md +6 -0
- package/tools/cli/installers/lib/ide/templates/combined/gemini-agent.toml +14 -0
- package/tools/cli/installers/lib/ide/templates/combined/gemini-task.toml +11 -0
- package/tools/cli/installers/lib/ide/templates/combined/gemini-tool.toml +11 -0
- package/tools/cli/installers/lib/ide/templates/combined/gemini-workflow-yaml.toml +16 -0
- package/tools/cli/installers/lib/ide/templates/combined/gemini-workflow.toml +14 -0
- package/tools/cli/installers/lib/ide/templates/combined/kiro-agent.md +16 -0
- package/tools/cli/installers/lib/ide/templates/combined/kiro-task.md +9 -0
- package/tools/cli/installers/lib/ide/templates/combined/kiro-tool.md +9 -0
- package/tools/cli/installers/lib/ide/templates/combined/kiro-workflow-yaml.md +15 -0
- package/tools/cli/installers/lib/ide/templates/combined/kiro-workflow.md +7 -0
- package/tools/cli/installers/lib/ide/templates/combined/opencode-agent.md +15 -0
- package/tools/cli/installers/lib/ide/templates/combined/opencode-task.md +13 -0
- package/tools/cli/installers/lib/ide/templates/combined/opencode-tool.md +13 -0
- package/tools/cli/installers/lib/ide/templates/combined/opencode-workflow-yaml.md +16 -0
- package/tools/cli/installers/lib/ide/templates/combined/opencode-workflow.md +16 -0
- package/tools/cli/installers/lib/ide/templates/combined/rovodev.md +9 -0
- package/tools/cli/installers/lib/ide/templates/combined/trae.md +9 -0
- package/tools/cli/installers/lib/ide/templates/combined/windsurf-workflow.md +10 -0
- package/tools/cli/installers/lib/ide/templates/gemini-agent-command.toml +14 -0
- package/tools/cli/installers/lib/ide/templates/gemini-task-command.toml +12 -0
- package/tools/cli/installers/lib/ide/templates/split/.gitkeep +0 -0
- package/tools/cli/installers/lib/ide/templates/workflow-command-template.md +13 -0
- package/tools/cli/installers/lib/ide/templates/workflow-commander.md +5 -0
- package/tools/cli/installers/lib/ide/trae.js +313 -0
- package/tools/cli/installers/lib/ide/windsurf.js +258 -0
- package/tools/cli/installers/lib/message-loader.js +83 -0
- package/tools/cli/installers/lib/modules/external-manager.js +136 -0
- package/tools/cli/installers/lib/modules/manager.js +1382 -0
- package/tools/cli/lib/activation-builder.js +165 -0
- package/tools/cli/lib/agent/compiler.js +516 -0
- package/tools/cli/lib/agent/installer.js +680 -0
- package/tools/cli/lib/agent/template-engine.js +152 -0
- package/tools/cli/lib/agent-analyzer.js +97 -0
- package/tools/cli/lib/agent-party-generator.js +194 -0
- package/tools/cli/lib/cli-utils.js +182 -0
- package/tools/cli/lib/config.js +213 -0
- package/tools/cli/lib/file-ops.js +204 -0
- package/tools/cli/lib/platform-codes.js +116 -0
- package/tools/cli/lib/project-root.js +77 -0
- package/tools/cli/lib/prompts.js +809 -0
- package/tools/cli/lib/replace-project-root.js +239 -0
- package/tools/cli/lib/ui.js +1940 -0
- package/tools/cli/lib/xml-handler.js +177 -0
- package/tools/cli/lib/xml-to-markdown.js +82 -0
- package/tools/{yaml-format.js → cli/lib/yaml-format.js} +39 -71
- package/tools/cli/lib/yaml-xml-builder.js +570 -0
- package/tools/cli/regenerate-manifests.js +28 -0
- package/tools/cli/test-yaml-builder.js +43 -0
- package/tools/cli/xiaoma-cli.js +106 -0
- package/tools/docs/_prompt-external-modules-page.md +59 -0
- package/tools/docs/fix-refs.md +91 -0
- package/tools/docs/native-skills-migration-checklist.md +281 -0
- package/tools/fix-doc-links.js +285 -0
- package/tools/flattener/aggregate.js +12 -30
- package/tools/flattener/binary.js +43 -46
- package/tools/flattener/discovery.js +15 -23
- package/tools/flattener/files.js +6 -6
- package/tools/flattener/flattener/aggregate.js +76 -0
- package/tools/flattener/flattener/binary.js +80 -0
- package/tools/flattener/flattener/discovery.js +71 -0
- package/tools/flattener/flattener/files.js +35 -0
- package/tools/flattener/flattener/ignoreRules.js +172 -0
- package/tools/flattener/flattener/main.js +483 -0
- package/tools/flattener/flattener/projectRoot.js +201 -0
- package/tools/flattener/flattener/prompts.js +44 -0
- package/tools/flattener/flattener/stats.helpers.js +368 -0
- package/tools/flattener/flattener/stats.js +75 -0
- package/tools/flattener/flattener/test-matrix.js +409 -0
- package/tools/flattener/flattener/xml.js +88 -0
- package/tools/flattener/ignoreRules.js +122 -127
- package/tools/flattener/main.js +140 -330
- package/tools/flattener/projectRoot.js +71 -81
- package/tools/flattener/prompts.js +10 -12
- package/tools/flattener/stats.helpers.js +63 -119
- package/tools/flattener/stats.js +2 -7
- package/tools/flattener/test-matrix.js +169 -228
- package/tools/flattener/xml.js +23 -31
- package/tools/format-workflow-md.js +263 -0
- package/tools/lib/xml-utils.js +13 -0
- package/tools/migrate-custom-module-paths.js +124 -0
- package/tools/platform-codes.yaml +157 -0
- package/tools/schema/agent.js +489 -0
- package/tools/validate-agent-schema.js +110 -0
- package/tools/validate-bundles.js +87 -0
- package/tools/validate-doc-links.js +409 -0
- package/tools/validate-file-refs.js +556 -0
- package/tools/validate-svg-changes.sh +356 -0
- package/tools/xiaoma-npx-wrapper.js +18 -24
- package/web-bundles/xmc/agents/analyst.xml +109 -0
- package/web-bundles/xmc/agents/architect.xml +101 -0
- package/web-bundles/xmc/agents/dev.xml +106 -0
- package/web-bundles/xmc/agents/pm.xml +112 -0
- package/web-bundles/xmc/agents/qa.xml +126 -0
- package/web-bundles/xmc/agents/quick-flow-solo-dev.xml +104 -0
- package/web-bundles/xmc/agents/sm.xml +109 -0
- package/web-bundles/xmc/agents/ux-designer.xml +100 -0
- package/web-bundles/xmc/teams/team-fullstack.xml +1192 -0
- package/.claude/agents/tech-translator.md +0 -124
- package/.claude/settings.local.json +0 -37
- package/.idea/misc.xml +0 -6
- package/.xiaoma-core/.coordinator-state.json +0 -19
- package/CLAUDE.md +0 -283
- package/JAVA-BACKEND-COMMANDS-REFERENCE.md +0 -300
- package/JAVA-BACKEND-ITERATION-GUIDE.md +0 -2116
- package/common/tasks/create-doc.md +0 -103
- package/common/tasks/execute-checklist.md +0 -88
- package/common/utils/bmad-doc-template.md +0 -327
- package/common/utils/workflow-management.md +0 -71
- package/dist/agents/analyst.txt +0 -6308
- package/dist/agents/architect.txt +0 -5046
- package/dist/agents/automation-orchestrator.txt +0 -396
- package/dist/agents/dev.txt +0 -1180
- package/dist/agents/full-requirement-orchestrator.txt +0 -505
- package/dist/agents/pm.txt +0 -3078
- package/dist/agents/po.txt +0 -1358
- package/dist/agents/qa.txt +0 -2002
- package/dist/agents/sm.txt +0 -3044
- package/dist/agents/ux-expert.txt +0 -707
- package/dist/agents/workflow-executor.txt +0 -1029
- package/dist/agents/workflow-helper.txt +0 -93
- package/dist/agents/xiaoma-master.txt +0 -9008
- package/dist/agents/xiaoma-orchestrator.txt +0 -1523
- package/dist/teams/team-all.txt +0 -23101
- package/dist/teams/team-fullstack-with-database.txt +0 -25076
- package/dist/teams/team-fullstack.txt +0 -15820
- package/dist/teams/team-ide-minimal.txt +0 -8285
- package/dist/teams/team-no-ui.txt +0 -14368
- package/docs/GUIDING-PRINCIPLES.md +0 -91
- package/docs/architecture/workflow-coordinator-implementation.md +0 -1188
- package/docs/architecture-sharding-modification.md +0 -623
- package/docs/automated-requirements-analysis-outputs.md +0 -896
- package/docs/core-architecture.md +0 -219
- package/docs/enhanced-ide-development-workflow.md +0 -248
- package/docs/prd/workflow-coordinator-prd.md +0 -1214
- package/docs/user-guide.md +0 -530
- package/docs/versioning-and-releases.md +0 -155
- package/docs/versions.md +0 -48
- package/docs/working-in-the-brownfield.md +0 -597
- package/tools/api-server.js +0 -367
- package/tools/builders/web-builder.js +0 -830
- package/tools/bump-all-versions.js +0 -133
- package/tools/cli.js +0 -157
- package/tools/installer/README.md +0 -8
- package/tools/installer/bin/xiaoma.js +0 -477
- package/tools/installer/config/ide-agent-config.yaml +0 -58
- package/tools/installer/config/install.config.yaml +0 -164
- package/tools/installer/lib/config-loader.js +0 -286
- package/tools/installer/lib/file-manager.js +0 -446
- package/tools/installer/lib/ide-base-setup.js +0 -238
- package/tools/installer/lib/ide-setup.js +0 -2027
- package/tools/installer/lib/installer.js +0 -2333
- package/tools/installer/lib/memory-profiler.js +0 -235
- package/tools/installer/lib/module-manager.js +0 -116
- package/tools/installer/lib/resource-locator.js +0 -334
- package/tools/installer/package-lock.json +0 -715
- package/tools/installer/package.json +0 -44
- package/tools/lib/dependency-resolver.js +0 -186
- package/tools/lib/yaml-utils.js +0 -34
- package/tools/md-assets/web-agent-startup-instructions.md +0 -39
- package/tools/preview-release-notes.js +0 -74
- package/tools/setup-hooks.sh +0 -37
- package/tools/shared/bannerArt.js +0 -105
- package/tools/sync-installer-version.js +0 -41
- package/tools/sync-version.sh +0 -23
- package/tools/upgraders/v3-to-v4-upgrader.js +0 -753
- package/tools/version-bump.js +0 -100
- package/tools/workflow-coordinator/README.md +0 -38
- package/tools/workflow-coordinator/USAGE.md +0 -548
- package/tools/workflow-coordinator/package-lock.json +0 -4868
- package/tools/workflow-coordinator/package.json +0 -35
- package/tools/workflow-coordinator/src/api/server.js +0 -207
- package/tools/workflow-coordinator/src/controller/workflow-controller.js +0 -263
- package/tools/workflow-coordinator/src/index.js +0 -113
- package/tools/workflow-coordinator/src/parser/workflow-parser.js +0 -144
- package/tools/workflow-coordinator/src/utils/state-manager.js +0 -59
- package/tools/workflow-coordinator/src/utils/validator.js +0 -86
- package/tools/workflow-coordinator/test/integration-test.js +0 -266
- package/tools/workflow-coordinator/test/quick-test.js +0 -127
- package/xiaoma-core/agent-teams/team-all.yaml +0 -15
- package/xiaoma-core/agent-teams/team-fullstack-with-database.yaml +0 -27
- package/xiaoma-core/agent-teams/team-fullstack.yaml +0 -19
- package/xiaoma-core/agent-teams/team-ide-minimal.yaml +0 -11
- package/xiaoma-core/agent-teams/team-no-ui.yaml +0 -14
- package/xiaoma-core/agents/analyst.md +0 -91
- package/xiaoma-core/agents/architect.md +0 -88
- package/xiaoma-core/agents/automated-fix-validator.yaml +0 -579
- package/xiaoma-core/agents/automated-quality-validator.yaml +0 -549
- package/xiaoma-core/agents/automation-orchestrator.md +0 -353
- package/xiaoma-core/agents/dev.md +0 -144
- package/xiaoma-core/agents/enhanced-workflow-orchestrator.yaml +0 -304
- package/xiaoma-core/agents/full-requirement-orchestrator.md +0 -462
- package/xiaoma-core/agents/global-requirements-auditor.yaml +0 -520
- package/xiaoma-core/agents/intelligent-template-adapter.yaml +0 -389
- package/xiaoma-core/agents/issue-dispatcher.yaml +0 -627
- package/xiaoma-core/agents/master-execution-engine.yaml +0 -543
- package/xiaoma-core/agents/pm.md +0 -85
- package/xiaoma-core/agents/po.md +0 -77
- package/xiaoma-core/agents/qa.md +0 -88
- package/xiaoma-core/agents/requirements-coverage-auditor.yaml +0 -373
- package/xiaoma-core/agents/sm.md +0 -125
- package/xiaoma-core/agents/ux-expert.md +0 -67
- package/xiaoma-core/agents/workflow-executor.md +0 -1031
- package/xiaoma-core/agents/workflow-helper.md +0 -481
- package/xiaoma-core/agents/xiaoma-master.md +0 -108
- package/xiaoma-core/agents/xiaoma-orchestrator.md +0 -145
- package/xiaoma-core/checklists/architect-checklist.md +0 -440
- package/xiaoma-core/checklists/change-checklist.md +0 -184
- package/xiaoma-core/checklists/dev-completion-checklist.md +0 -324
- package/xiaoma-core/checklists/pm-checklist.md +0 -372
- package/xiaoma-core/checklists/po-master-checklist.md +0 -434
- package/xiaoma-core/checklists/po-story-validation-checklist.md +0 -219
- package/xiaoma-core/checklists/qa-approval-checklist.md +0 -393
- package/xiaoma-core/checklists/story-dod-checklist.md +0 -96
- package/xiaoma-core/checklists/story-draft-checklist.md +0 -155
- package/xiaoma-core/core-config.yaml +0 -23
- package/xiaoma-core/data/bmad-kb.md +0 -809
- package/xiaoma-core/data/brainstorming-techniques.md +0 -38
- package/xiaoma-core/data/elicitation-methods.md +0 -156
- package/xiaoma-core/data/technical-preferences.md +0 -5
- package/xiaoma-core/data/test-levels-framework.md +0 -148
- package/xiaoma-core/data/test-priorities-matrix.md +0 -174
- package/xiaoma-core/scripts/build-validation/pre-dev-validation.sh +0 -71
- package/xiaoma-core/scripts/build-validation/progressive-validation.sh +0 -88
- package/xiaoma-core/scripts/build-validation/quick-check.sh +0 -69
- package/xiaoma-core/tasks/advanced-elicitation.md +0 -119
- package/xiaoma-core/tasks/analyze-existing-database.md +0 -155
- package/xiaoma-core/tasks/apply-qa-fixes.md +0 -150
- package/xiaoma-core/tasks/automated-story-cycle.md +0 -370
- package/xiaoma-core/tasks/batch-story-generation.md +0 -354
- package/xiaoma-core/tasks/brownfield-create-epic.md +0 -162
- package/xiaoma-core/tasks/brownfield-create-story.md +0 -149
- package/xiaoma-core/tasks/correct-course.md +0 -72
- package/xiaoma-core/tasks/create-brownfield-story.md +0 -314
- package/xiaoma-core/tasks/create-database-design.md +0 -161
- package/xiaoma-core/tasks/create-deep-research-prompt.md +0 -280
- package/xiaoma-core/tasks/create-enhanced-story-with-database.md +0 -250
- package/xiaoma-core/tasks/create-incremental-architecture.md +0 -525
- package/xiaoma-core/tasks/create-next-story.md +0 -114
- package/xiaoma-core/tasks/create-prd-from-rag.md +0 -435
- package/xiaoma-core/tasks/create-story-with-rag.md +0 -559
- package/xiaoma-core/tasks/develop-story-with-rag.md +0 -536
- package/xiaoma-core/tasks/document-project.md +0 -345
- package/xiaoma-core/tasks/facilitate-brainstorming-session.md +0 -138
- package/xiaoma-core/tasks/generate-ai-frontend-prompt.md +0 -53
- package/xiaoma-core/tasks/generate-database-ddl.md +0 -240
- package/xiaoma-core/tasks/generate-database-entities.md +0 -501
- package/xiaoma-core/tasks/generate-rag-questions.md +0 -312
- package/xiaoma-core/tasks/index-docs.md +0 -175
- package/xiaoma-core/tasks/kb-mode-interaction.md +0 -77
- package/xiaoma-core/tasks/nfr-assess.md +0 -345
- package/xiaoma-core/tasks/project-integration-testing.md +0 -477
- package/xiaoma-core/tasks/qa-gate.md +0 -163
- package/xiaoma-core/tasks/requirement-analysis-with-rag.md +0 -1318
- package/xiaoma-core/tasks/requirements-coverage-audit.md +0 -198
- package/xiaoma-core/tasks/review-story.md +0 -316
- package/xiaoma-core/tasks/risk-profile.md +0 -355
- package/xiaoma-core/tasks/serial-development-orchestration.md +0 -426
- package/xiaoma-core/tasks/shard-doc.md +0 -187
- package/xiaoma-core/tasks/test-design.md +0 -176
- package/xiaoma-core/tasks/trace-requirements.md +0 -266
- package/xiaoma-core/tasks/validate-next-story.md +0 -136
- package/xiaoma-core/templates/api-design-tmpl.yaml +0 -704
- package/xiaoma-core/templates/architecture-tmpl.yaml +0 -650
- package/xiaoma-core/templates/brainstorming-output-tmpl.yaml +0 -156
- package/xiaoma-core/templates/brownfield-architecture-tmpl.yaml +0 -476
- package/xiaoma-core/templates/brownfield-prd-tmpl.yaml +0 -280
- package/xiaoma-core/templates/competitor-analysis-tmpl.yaml +0 -336
- package/xiaoma-core/templates/database-design-tmpl.yaml +0 -266
- package/xiaoma-core/templates/enhanced-story-with-database-tmpl.yaml +0 -428
- package/xiaoma-core/templates/front-end-architecture-tmpl.yaml +0 -272
- package/xiaoma-core/templates/front-end-spec-tmpl.yaml +0 -354
- package/xiaoma-core/templates/fullstack-architecture-tmpl.yaml +0 -925
- package/xiaoma-core/templates/global-qa-monitoring-tmpl.yaml +0 -443
- package/xiaoma-core/templates/incremental-architecture-tmpl.yaml +0 -601
- package/xiaoma-core/templates/market-research-tmpl.yaml +0 -252
- package/xiaoma-core/templates/maven-lombok-template.xml +0 -111
- package/xiaoma-core/templates/prd-from-rag-tmpl.yaml +0 -410
- package/xiaoma-core/templates/prd-tmpl.yaml +0 -202
- package/xiaoma-core/templates/project-brief-tmpl.yaml +0 -221
- package/xiaoma-core/templates/qa-gate-tmpl.yaml +0 -102
- package/xiaoma-core/templates/rag-knowledge-tmpl.yaml +0 -569
- package/xiaoma-core/templates/rag-questions-tmpl.yaml +0 -949
- package/xiaoma-core/templates/requirements-coverage-audit.yaml +0 -330
- package/xiaoma-core/templates/start-enhanced-workflow.yaml +0 -347
- package/xiaoma-core/templates/story-tmpl.yaml +0 -137
- package/xiaoma-core/templates/story-with-rag-tmpl.yaml +0 -360
- package/xiaoma-core/workflows/automated-requirements-analysis.yaml +0 -2149
- package/xiaoma-core/workflows/automated-requirements-development.yaml +0 -739
- package/xiaoma-core/workflows/automated-story-development.yaml +0 -1264
- package/xiaoma-core/workflows/brownfield-fullstack.yaml +0 -298
- package/xiaoma-core/workflows/brownfield-service.yaml +0 -188
- package/xiaoma-core/workflows/brownfield-ui.yaml +0 -198
- package/xiaoma-core/workflows/enhanced-fullstack-with-database.yaml +0 -427
- package/xiaoma-core/workflows/enhanced-fullstack-with-qa-loop.yaml +0 -766
- package/xiaoma-core/workflows/full-requirement-automation.yaml +0 -1305
- package/xiaoma-core/workflows/greenfield-fullstack.yaml +0 -241
- package/xiaoma-core/workflows/greenfield-service.yaml +0 -207
- package/xiaoma-core/workflows/greenfield-ui.yaml +0 -236
|
@@ -0,0 +1,1374 @@
|
|
|
1
|
+
const path = require('node:path');
|
|
2
|
+
const fs = require('fs-extra');
|
|
3
|
+
const yaml = require('yaml');
|
|
4
|
+
const crypto = require('node:crypto');
|
|
5
|
+
const csv = require('csv-parse/sync');
|
|
6
|
+
const { getSourcePath, getModulePath } = require('../../../lib/project-root');
|
|
7
|
+
const prompts = require('../../../lib/prompts');
|
|
8
|
+
const {
|
|
9
|
+
loadSkillManifest: loadSkillManifestShared,
|
|
10
|
+
getCanonicalId: getCanonicalIdShared,
|
|
11
|
+
getArtifactType: getArtifactTypeShared,
|
|
12
|
+
getInstallToXiaoMa: getInstallToXiaoMaShared,
|
|
13
|
+
} = require('../ide/shared/skill-manifest');
|
|
14
|
+
|
|
15
|
+
// Load package.json for version info
|
|
16
|
+
const packageJson = require('../../../../../package.json');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Generates manifest files for installed workflows, agents, and tasks
|
|
20
|
+
*/
|
|
21
|
+
class ManifestGenerator {
|
|
22
|
+
constructor() {
|
|
23
|
+
this.workflows = [];
|
|
24
|
+
this.skills = [];
|
|
25
|
+
this.agents = [];
|
|
26
|
+
this.tasks = [];
|
|
27
|
+
this.tools = [];
|
|
28
|
+
this.modules = [];
|
|
29
|
+
this.files = [];
|
|
30
|
+
this.selectedIdes = [];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Delegate to shared skill-manifest module */
|
|
34
|
+
async loadSkillManifest(dirPath) {
|
|
35
|
+
return loadSkillManifestShared(dirPath);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Delegate to shared skill-manifest module */
|
|
39
|
+
getCanonicalId(manifest, filename) {
|
|
40
|
+
return getCanonicalIdShared(manifest, filename);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Delegate to shared skill-manifest module */
|
|
44
|
+
getArtifactType(manifest, filename) {
|
|
45
|
+
return getArtifactTypeShared(manifest, filename);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Delegate to shared skill-manifest module */
|
|
49
|
+
getInstallToXiaoMa(manifest, filename) {
|
|
50
|
+
return getInstallToXiaoMaShared(manifest, filename);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Clean text for CSV output by normalizing whitespace.
|
|
55
|
+
* Note: Quote escaping is handled by escapeCsv() at write time.
|
|
56
|
+
* @param {string} text - Text to clean
|
|
57
|
+
* @returns {string} Cleaned text
|
|
58
|
+
*/
|
|
59
|
+
cleanForCSV(text) {
|
|
60
|
+
if (!text) return '';
|
|
61
|
+
return text.trim().replaceAll(/\s+/g, ' '); // Normalize all whitespace (including newlines) to single space
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Generate all manifests for the installation
|
|
66
|
+
* @param {string} xiaomaDir - _xiaoma
|
|
67
|
+
* @param {Array} selectedModules - Selected modules for installation
|
|
68
|
+
* @param {Array} installedFiles - All installed files (optional, for hash tracking)
|
|
69
|
+
*/
|
|
70
|
+
async generateManifests(xiaomaDir, selectedModules, installedFiles = [], options = {}) {
|
|
71
|
+
// Create _config directory if it doesn't exist
|
|
72
|
+
const cfgDir = path.join(xiaomaDir, '_config');
|
|
73
|
+
await fs.ensureDir(cfgDir);
|
|
74
|
+
|
|
75
|
+
// Store modules list (all modules including preserved ones)
|
|
76
|
+
const preservedModules = options.preservedModules || [];
|
|
77
|
+
|
|
78
|
+
// Scan the xiaoma directory to find all actually installed modules
|
|
79
|
+
const installedModules = await this.scanInstalledModules(xiaomaDir);
|
|
80
|
+
|
|
81
|
+
// Since custom modules are now installed the same way as regular modules,
|
|
82
|
+
// we don't need to exclude them from manifest generation
|
|
83
|
+
const allModules = [...new Set(['core', ...selectedModules, ...preservedModules, ...installedModules])];
|
|
84
|
+
|
|
85
|
+
this.modules = allModules;
|
|
86
|
+
this.updatedModules = allModules; // Include ALL modules (including custom) for scanning
|
|
87
|
+
|
|
88
|
+
// For CSV manifests, we need to include ALL modules that are installed
|
|
89
|
+
// preservedModules controls which modules stay as-is in the CSV (don't get rescanned)
|
|
90
|
+
// But all modules should be included in the final manifest
|
|
91
|
+
this.preservedModules = allModules; // Include ALL modules (including custom)
|
|
92
|
+
this.xiaomaDir = xiaomaDir;
|
|
93
|
+
this.xiaomaFolderName = path.basename(xiaomaDir); // Get the actual folder name (e.g., '_xiaoma' or 'xiaoma')
|
|
94
|
+
this.allInstalledFiles = installedFiles;
|
|
95
|
+
|
|
96
|
+
if (!Object.prototype.hasOwnProperty.call(options, 'ides')) {
|
|
97
|
+
throw new Error('ManifestGenerator requires `options.ides` to be provided – installer should supply the selected IDEs array.');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const resolvedIdes = options.ides ?? [];
|
|
101
|
+
if (!Array.isArray(resolvedIdes)) {
|
|
102
|
+
throw new TypeError('ManifestGenerator expected `options.ides` to be an array.');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Filter out any undefined/null values from IDE list
|
|
106
|
+
this.selectedIdes = resolvedIdes.filter((ide) => ide && typeof ide === 'string');
|
|
107
|
+
|
|
108
|
+
// Reset files list (defensive: prevent stale data if instance is reused)
|
|
109
|
+
this.files = [];
|
|
110
|
+
|
|
111
|
+
// Collect skills first (populates skillClaimedDirs before legacy collectors run)
|
|
112
|
+
await this.collectSkills();
|
|
113
|
+
|
|
114
|
+
// Collect workflow data
|
|
115
|
+
await this.collectWorkflows(selectedModules);
|
|
116
|
+
|
|
117
|
+
// Collect agent data - use updatedModules which includes all installed modules
|
|
118
|
+
await this.collectAgents(this.updatedModules);
|
|
119
|
+
|
|
120
|
+
// Collect task data
|
|
121
|
+
await this.collectTasks(this.updatedModules);
|
|
122
|
+
|
|
123
|
+
// Collect tool data
|
|
124
|
+
await this.collectTools(this.updatedModules);
|
|
125
|
+
|
|
126
|
+
// Write manifest files and collect their paths
|
|
127
|
+
const manifestFiles = [
|
|
128
|
+
await this.writeMainManifest(cfgDir),
|
|
129
|
+
await this.writeWorkflowManifest(cfgDir),
|
|
130
|
+
await this.writeSkillManifest(cfgDir),
|
|
131
|
+
await this.writeAgentManifest(cfgDir),
|
|
132
|
+
await this.writeTaskManifest(cfgDir),
|
|
133
|
+
await this.writeToolManifest(cfgDir),
|
|
134
|
+
await this.writeFilesManifest(cfgDir),
|
|
135
|
+
];
|
|
136
|
+
|
|
137
|
+
return {
|
|
138
|
+
skills: this.skills.length,
|
|
139
|
+
workflows: this.workflows.length,
|
|
140
|
+
agents: this.agents.length,
|
|
141
|
+
tasks: this.tasks.length,
|
|
142
|
+
tools: this.tools.length,
|
|
143
|
+
files: this.files.length,
|
|
144
|
+
manifestFiles: manifestFiles,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Recursively walk a module directory tree, collecting skill directories.
|
|
150
|
+
* A skill directory is one that contains both a xiaoma-skill-manifest.yaml with
|
|
151
|
+
* type: skill AND a SKILL.md file with name/description frontmatter.
|
|
152
|
+
* Populates this.skills[] and this.skillClaimedDirs (Set of absolute paths).
|
|
153
|
+
*/
|
|
154
|
+
async collectSkills() {
|
|
155
|
+
this.skills = [];
|
|
156
|
+
this.skillClaimedDirs = new Set();
|
|
157
|
+
const debug = process.env.XiaoMa_DEBUG_MANIFEST === 'true';
|
|
158
|
+
|
|
159
|
+
for (const moduleName of this.updatedModules) {
|
|
160
|
+
const modulePath = path.join(this.xiaomaDir, moduleName);
|
|
161
|
+
if (!(await fs.pathExists(modulePath))) continue;
|
|
162
|
+
|
|
163
|
+
// Recursive walk skipping . and _ prefixed dirs
|
|
164
|
+
const walk = async (dir) => {
|
|
165
|
+
let entries;
|
|
166
|
+
try {
|
|
167
|
+
entries = await fs.readdir(dir, { withFileTypes: true });
|
|
168
|
+
} catch {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Check this directory for skill manifest
|
|
173
|
+
const manifest = await this.loadSkillManifest(dir);
|
|
174
|
+
|
|
175
|
+
// Determine if this directory is a skill (type: skill in manifest)
|
|
176
|
+
const skillFile = 'SKILL.md';
|
|
177
|
+
const artifactType = this.getArtifactType(manifest, skillFile);
|
|
178
|
+
|
|
179
|
+
if (artifactType === 'skill') {
|
|
180
|
+
const skillMdPath = path.join(dir, 'SKILL.md');
|
|
181
|
+
const dirName = path.basename(dir);
|
|
182
|
+
|
|
183
|
+
// Validate and parse SKILL.md
|
|
184
|
+
const skillMeta = await this.parseSkillMd(skillMdPath, dir, dirName, debug);
|
|
185
|
+
|
|
186
|
+
if (skillMeta) {
|
|
187
|
+
// Build path relative from module root (points to SKILL.md — the permanent entrypoint)
|
|
188
|
+
const relativePath = path.relative(modulePath, dir).split(path.sep).join('/');
|
|
189
|
+
const installPath = relativePath
|
|
190
|
+
? `${this.xiaomaFolderName}/${moduleName}/${relativePath}/${skillFile}`
|
|
191
|
+
: `${this.xiaomaFolderName}/${moduleName}/${skillFile}`;
|
|
192
|
+
|
|
193
|
+
// Skills derive canonicalId from directory name — never from manifest
|
|
194
|
+
if (manifest && manifest.__single && manifest.__single.canonicalId) {
|
|
195
|
+
console.warn(
|
|
196
|
+
`Warning: Skill manifest at ${dir}/xiaoma-skill-manifest.yaml contains canonicalId — this field is ignored for skills (directory name is the canonical ID)`,
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
const canonicalId = dirName;
|
|
200
|
+
|
|
201
|
+
this.skills.push({
|
|
202
|
+
name: skillMeta.name,
|
|
203
|
+
description: this.cleanForCSV(skillMeta.description),
|
|
204
|
+
module: moduleName,
|
|
205
|
+
path: installPath,
|
|
206
|
+
canonicalId,
|
|
207
|
+
install_to_xiaoma: this.getInstallToXiaoMa(manifest, skillFile),
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// Add to files list
|
|
211
|
+
this.files.push({
|
|
212
|
+
type: 'skill',
|
|
213
|
+
name: skillMeta.name,
|
|
214
|
+
module: moduleName,
|
|
215
|
+
path: installPath,
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
this.skillClaimedDirs.add(dir);
|
|
219
|
+
|
|
220
|
+
if (debug) {
|
|
221
|
+
console.log(`[DEBUG] collectSkills: claimed skill "${skillMeta.name}" as ${canonicalId} at ${dir}`);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Warn if manifest says type:skill but directory was not claimed
|
|
227
|
+
if (manifest && !this.skillClaimedDirs.has(dir)) {
|
|
228
|
+
let hasSkillType = false;
|
|
229
|
+
if (manifest.__single) {
|
|
230
|
+
hasSkillType = manifest.__single.type === 'skill';
|
|
231
|
+
} else {
|
|
232
|
+
for (const key of Object.keys(manifest)) {
|
|
233
|
+
if (manifest[key]?.type === 'skill') {
|
|
234
|
+
hasSkillType = true;
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
if (hasSkillType && debug) {
|
|
240
|
+
console.log(`[DEBUG] collectSkills: dir has type:skill manifest but failed validation: ${dir}`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Recurse into subdirectories
|
|
245
|
+
for (const entry of entries) {
|
|
246
|
+
if (!entry.isDirectory()) continue;
|
|
247
|
+
if (entry.name.startsWith('.') || entry.name.startsWith('_')) continue;
|
|
248
|
+
await walk(path.join(dir, entry.name));
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
await walk(modulePath);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (debug) {
|
|
256
|
+
console.log(`[DEBUG] collectSkills: total skills found: ${this.skills.length}, claimed dirs: ${this.skillClaimedDirs.size}`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Parse and validate SKILL.md for a skill directory.
|
|
262
|
+
* Returns parsed frontmatter object with name/description, or null if invalid.
|
|
263
|
+
* @param {string} skillMdPath - Absolute path to SKILL.md
|
|
264
|
+
* @param {string} dir - Skill directory path (for error messages)
|
|
265
|
+
* @param {string} dirName - Expected name (must match frontmatter name)
|
|
266
|
+
* @param {boolean} debug - Whether to emit debug-level messages
|
|
267
|
+
* @returns {Promise<Object|null>} Parsed frontmatter or null
|
|
268
|
+
*/
|
|
269
|
+
async parseSkillMd(skillMdPath, dir, dirName, debug = false) {
|
|
270
|
+
if (!(await fs.pathExists(skillMdPath))) {
|
|
271
|
+
if (debug) console.log(`[DEBUG] parseSkillMd: "${dir}" is missing SKILL.md — skipping`);
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
try {
|
|
276
|
+
const rawContent = await fs.readFile(skillMdPath, 'utf8');
|
|
277
|
+
const content = rawContent.replaceAll('\r\n', '\n').replaceAll('\r', '\n');
|
|
278
|
+
|
|
279
|
+
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
280
|
+
if (frontmatterMatch) {
|
|
281
|
+
const skillMeta = yaml.parse(frontmatterMatch[1]);
|
|
282
|
+
|
|
283
|
+
if (
|
|
284
|
+
!skillMeta ||
|
|
285
|
+
typeof skillMeta !== 'object' ||
|
|
286
|
+
typeof skillMeta.name !== 'string' ||
|
|
287
|
+
typeof skillMeta.description !== 'string' ||
|
|
288
|
+
!skillMeta.name ||
|
|
289
|
+
!skillMeta.description
|
|
290
|
+
) {
|
|
291
|
+
if (debug) console.log(`[DEBUG] parseSkillMd: SKILL.md in "${dir}" is missing name or description (or wrong type) — skipping`);
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (skillMeta.name !== dirName) {
|
|
296
|
+
console.error(`Error: SKILL.md name "${skillMeta.name}" does not match directory name "${dirName}" — skipping`);
|
|
297
|
+
return null;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return skillMeta;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (debug) console.log(`[DEBUG] parseSkillMd: SKILL.md in "${dir}" has no frontmatter — skipping`);
|
|
304
|
+
return null;
|
|
305
|
+
} catch (error) {
|
|
306
|
+
if (debug) console.log(`[DEBUG] parseSkillMd: failed to parse SKILL.md in "${dir}": ${error.message} — skipping`);
|
|
307
|
+
return null;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Collect all workflows from core and selected modules
|
|
313
|
+
* Scans the INSTALLED xiaoma directory, not the source
|
|
314
|
+
*/
|
|
315
|
+
async collectWorkflows(selectedModules) {
|
|
316
|
+
this.workflows = [];
|
|
317
|
+
|
|
318
|
+
// Use updatedModules which already includes deduplicated 'core' + selectedModules
|
|
319
|
+
for (const moduleName of this.updatedModules) {
|
|
320
|
+
const modulePath = path.join(this.xiaomaDir, moduleName);
|
|
321
|
+
|
|
322
|
+
if (await fs.pathExists(modulePath)) {
|
|
323
|
+
const moduleWorkflows = await this.getWorkflowsFromPath(modulePath, moduleName);
|
|
324
|
+
this.workflows.push(...moduleWorkflows);
|
|
325
|
+
|
|
326
|
+
// Also scan tasks/ for type:skill entries (skills can live anywhere)
|
|
327
|
+
const tasksSkills = await this.getWorkflowsFromPath(modulePath, moduleName, 'tasks');
|
|
328
|
+
this.workflows.push(...tasksSkills);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Recursively find and parse workflow.md files
|
|
335
|
+
*/
|
|
336
|
+
async getWorkflowsFromPath(basePath, moduleName, subDir = 'workflows') {
|
|
337
|
+
const workflows = [];
|
|
338
|
+
const workflowsPath = path.join(basePath, subDir);
|
|
339
|
+
const debug = process.env.XiaoMa_DEBUG_MANIFEST === 'true';
|
|
340
|
+
|
|
341
|
+
if (debug) {
|
|
342
|
+
console.log(`[DEBUG] Scanning workflows in: ${workflowsPath}`);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (!(await fs.pathExists(workflowsPath))) {
|
|
346
|
+
if (debug) {
|
|
347
|
+
console.log(`[DEBUG] Workflows path does not exist: ${workflowsPath}`);
|
|
348
|
+
}
|
|
349
|
+
return workflows;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Recursively find workflow.md files
|
|
353
|
+
const findWorkflows = async (dir, relativePath = '') => {
|
|
354
|
+
// Skip directories already claimed as skills
|
|
355
|
+
if (this.skillClaimedDirs && this.skillClaimedDirs.has(dir)) return;
|
|
356
|
+
|
|
357
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
358
|
+
// Load skill manifest for this directory (if present)
|
|
359
|
+
const skillManifest = await this.loadSkillManifest(dir);
|
|
360
|
+
|
|
361
|
+
for (const entry of entries) {
|
|
362
|
+
const fullPath = path.join(dir, entry.name);
|
|
363
|
+
|
|
364
|
+
if (entry.isDirectory()) {
|
|
365
|
+
// Skip directories claimed by collectSkills
|
|
366
|
+
if (this.skillClaimedDirs && this.skillClaimedDirs.has(fullPath)) continue;
|
|
367
|
+
// Recurse into subdirectories
|
|
368
|
+
const newRelativePath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
|
|
369
|
+
await findWorkflows(fullPath, newRelativePath);
|
|
370
|
+
} else if (entry.name === 'workflow.md' || (entry.name.startsWith('workflow-') && entry.name.endsWith('.md'))) {
|
|
371
|
+
// Parse workflow file (both YAML and MD formats)
|
|
372
|
+
if (debug) {
|
|
373
|
+
console.log(`[DEBUG] Found workflow file: ${fullPath}`);
|
|
374
|
+
}
|
|
375
|
+
try {
|
|
376
|
+
// Read and normalize line endings (fix Windows CRLF issues)
|
|
377
|
+
const rawContent = await fs.readFile(fullPath, 'utf8');
|
|
378
|
+
const content = rawContent.replaceAll('\r\n', '\n').replaceAll('\r', '\n');
|
|
379
|
+
|
|
380
|
+
// Parse MD workflow with YAML frontmatter
|
|
381
|
+
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
382
|
+
if (!frontmatterMatch) {
|
|
383
|
+
if (debug) {
|
|
384
|
+
console.log(`[DEBUG] Skipped (no frontmatter): ${fullPath}`);
|
|
385
|
+
}
|
|
386
|
+
continue; // Skip MD files without frontmatter
|
|
387
|
+
}
|
|
388
|
+
const workflow = yaml.parse(frontmatterMatch[1]);
|
|
389
|
+
|
|
390
|
+
if (debug) {
|
|
391
|
+
console.log(`[DEBUG] Parsed: name="${workflow.name}", description=${workflow.description ? 'OK' : 'MISSING'}`);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Skip template workflows (those with placeholder values)
|
|
395
|
+
if (workflow.name && workflow.name.includes('{') && workflow.name.includes('}')) {
|
|
396
|
+
if (debug) {
|
|
397
|
+
console.log(`[DEBUG] Skipped (template placeholder): ${workflow.name}`);
|
|
398
|
+
}
|
|
399
|
+
continue;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// Skip workflows marked as non-standalone (reference/example workflows)
|
|
403
|
+
if (workflow.standalone === false) {
|
|
404
|
+
if (debug) {
|
|
405
|
+
console.log(`[DEBUG] Skipped (standalone=false): ${workflow.name}`);
|
|
406
|
+
}
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
if (workflow.name && workflow.description) {
|
|
411
|
+
// Build relative path for installation
|
|
412
|
+
const installPath =
|
|
413
|
+
moduleName === 'core'
|
|
414
|
+
? `${this.xiaomaFolderName}/core/${subDir}/${relativePath}/${entry.name}`
|
|
415
|
+
: `${this.xiaomaFolderName}/${moduleName}/${subDir}/${relativePath}/${entry.name}`;
|
|
416
|
+
|
|
417
|
+
// Workflows with standalone: false are filtered out above
|
|
418
|
+
workflows.push({
|
|
419
|
+
name: workflow.name,
|
|
420
|
+
description: this.cleanForCSV(workflow.description),
|
|
421
|
+
module: moduleName,
|
|
422
|
+
path: installPath,
|
|
423
|
+
canonicalId: this.getCanonicalId(skillManifest, entry.name),
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
// Add to files list
|
|
427
|
+
this.files.push({
|
|
428
|
+
type: 'workflow',
|
|
429
|
+
name: workflow.name,
|
|
430
|
+
module: moduleName,
|
|
431
|
+
path: installPath,
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
if (debug) {
|
|
435
|
+
console.log(`[DEBUG] ✓ Added workflow: ${workflow.name} (${moduleName})`);
|
|
436
|
+
}
|
|
437
|
+
} else {
|
|
438
|
+
if (debug) {
|
|
439
|
+
console.log(`[DEBUG] Skipped (missing name or description): ${fullPath}`);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
} catch (error) {
|
|
443
|
+
await prompts.log.warn(`Failed to parse workflow at ${fullPath}: ${error.message}`);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
await findWorkflows(workflowsPath);
|
|
450
|
+
|
|
451
|
+
if (debug) {
|
|
452
|
+
console.log(`[DEBUG] Total workflows found in ${moduleName}: ${workflows.length}`);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
return workflows;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Collect all agents from core and selected modules
|
|
460
|
+
* Scans the INSTALLED xiaoma directory, not the source
|
|
461
|
+
*/
|
|
462
|
+
async collectAgents(selectedModules) {
|
|
463
|
+
this.agents = [];
|
|
464
|
+
|
|
465
|
+
// Use updatedModules which already includes deduplicated 'core' + selectedModules
|
|
466
|
+
for (const moduleName of this.updatedModules) {
|
|
467
|
+
const agentsPath = path.join(this.xiaomaDir, moduleName, 'agents');
|
|
468
|
+
|
|
469
|
+
if (await fs.pathExists(agentsPath)) {
|
|
470
|
+
const moduleAgents = await this.getAgentsFromDir(agentsPath, moduleName);
|
|
471
|
+
this.agents.push(...moduleAgents);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Get standalone agents from xiaoma/agents/ directory
|
|
476
|
+
const standaloneAgentsDir = path.join(this.xiaomaDir, 'agents');
|
|
477
|
+
if (await fs.pathExists(standaloneAgentsDir)) {
|
|
478
|
+
const agentDirs = await fs.readdir(standaloneAgentsDir, { withFileTypes: true });
|
|
479
|
+
|
|
480
|
+
for (const agentDir of agentDirs) {
|
|
481
|
+
if (!agentDir.isDirectory()) continue;
|
|
482
|
+
|
|
483
|
+
const agentDirPath = path.join(standaloneAgentsDir, agentDir.name);
|
|
484
|
+
const standaloneAgents = await this.getAgentsFromDir(agentDirPath, 'standalone');
|
|
485
|
+
this.agents.push(...standaloneAgents);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Get agents from a directory recursively
|
|
492
|
+
* Only includes compiled .md files (not .agent.yaml source files)
|
|
493
|
+
*/
|
|
494
|
+
async getAgentsFromDir(dirPath, moduleName, relativePath = '') {
|
|
495
|
+
// Skip directories claimed by collectSkills
|
|
496
|
+
if (this.skillClaimedDirs && this.skillClaimedDirs.has(dirPath)) return [];
|
|
497
|
+
const agents = [];
|
|
498
|
+
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
499
|
+
// Load skill manifest for this directory (if present)
|
|
500
|
+
const skillManifest = await this.loadSkillManifest(dirPath);
|
|
501
|
+
|
|
502
|
+
for (const entry of entries) {
|
|
503
|
+
const fullPath = path.join(dirPath, entry.name);
|
|
504
|
+
|
|
505
|
+
if (entry.isDirectory()) {
|
|
506
|
+
// Skip directories claimed by collectSkills
|
|
507
|
+
if (this.skillClaimedDirs && this.skillClaimedDirs.has(fullPath)) continue;
|
|
508
|
+
// Recurse into subdirectories
|
|
509
|
+
const newRelativePath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
|
|
510
|
+
const subDirAgents = await this.getAgentsFromDir(fullPath, moduleName, newRelativePath);
|
|
511
|
+
agents.push(...subDirAgents);
|
|
512
|
+
} else if (entry.name.endsWith('.md') && !entry.name.endsWith('.agent.yaml') && entry.name.toLowerCase() !== 'readme.md') {
|
|
513
|
+
const content = await fs.readFile(fullPath, 'utf8');
|
|
514
|
+
|
|
515
|
+
// Skip files that don't contain <agent> tag (e.g., README files)
|
|
516
|
+
if (!content.includes('<agent')) {
|
|
517
|
+
continue;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// Skip web-only agents
|
|
521
|
+
if (content.includes('localskip="true"')) {
|
|
522
|
+
continue;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// Extract agent metadata from the XML structure
|
|
526
|
+
const nameMatch = content.match(/name="([^"]+)"/);
|
|
527
|
+
const titleMatch = content.match(/title="([^"]+)"/);
|
|
528
|
+
const iconMatch = content.match(/icon="([^"]+)"/);
|
|
529
|
+
const capabilitiesMatch = content.match(/capabilities="([^"]+)"/);
|
|
530
|
+
|
|
531
|
+
// Extract persona fields
|
|
532
|
+
const roleMatch = content.match(/<role>([^<]+)<\/role>/);
|
|
533
|
+
const identityMatch = content.match(/<identity>([\s\S]*?)<\/identity>/);
|
|
534
|
+
const styleMatch = content.match(/<communication_style>([\s\S]*?)<\/communication_style>/);
|
|
535
|
+
const principlesMatch = content.match(/<principles>([\s\S]*?)<\/principles>/);
|
|
536
|
+
|
|
537
|
+
// Build relative path for installation
|
|
538
|
+
const fileRelativePath = relativePath ? `${relativePath}/${entry.name}` : entry.name;
|
|
539
|
+
const installPath =
|
|
540
|
+
moduleName === 'core'
|
|
541
|
+
? `${this.xiaomaFolderName}/core/agents/${fileRelativePath}`
|
|
542
|
+
: `${this.xiaomaFolderName}/${moduleName}/agents/${fileRelativePath}`;
|
|
543
|
+
|
|
544
|
+
const agentName = entry.name.replace('.md', '');
|
|
545
|
+
|
|
546
|
+
agents.push({
|
|
547
|
+
name: agentName,
|
|
548
|
+
displayName: nameMatch ? nameMatch[1] : agentName,
|
|
549
|
+
title: titleMatch ? titleMatch[1] : '',
|
|
550
|
+
icon: iconMatch ? iconMatch[1] : '',
|
|
551
|
+
capabilities: capabilitiesMatch ? this.cleanForCSV(capabilitiesMatch[1]) : '',
|
|
552
|
+
role: roleMatch ? this.cleanForCSV(roleMatch[1]) : '',
|
|
553
|
+
identity: identityMatch ? this.cleanForCSV(identityMatch[1]) : '',
|
|
554
|
+
communicationStyle: styleMatch ? this.cleanForCSV(styleMatch[1]) : '',
|
|
555
|
+
principles: principlesMatch ? this.cleanForCSV(principlesMatch[1]) : '',
|
|
556
|
+
module: moduleName,
|
|
557
|
+
path: installPath,
|
|
558
|
+
canonicalId: this.getCanonicalId(skillManifest, entry.name),
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
// Add to files list
|
|
562
|
+
this.files.push({
|
|
563
|
+
type: 'agent',
|
|
564
|
+
name: agentName,
|
|
565
|
+
module: moduleName,
|
|
566
|
+
path: installPath,
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
return agents;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Collect all tasks from core and selected modules
|
|
576
|
+
* Scans the INSTALLED xiaoma directory, not the source
|
|
577
|
+
*/
|
|
578
|
+
async collectTasks(selectedModules) {
|
|
579
|
+
this.tasks = [];
|
|
580
|
+
|
|
581
|
+
// Use updatedModules which already includes deduplicated 'core' + selectedModules
|
|
582
|
+
for (const moduleName of this.updatedModules) {
|
|
583
|
+
const tasksPath = path.join(this.xiaomaDir, moduleName, 'tasks');
|
|
584
|
+
|
|
585
|
+
if (await fs.pathExists(tasksPath)) {
|
|
586
|
+
const moduleTasks = await this.getTasksFromDir(tasksPath, moduleName);
|
|
587
|
+
this.tasks.push(...moduleTasks);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* Get tasks from a directory
|
|
594
|
+
*/
|
|
595
|
+
async getTasksFromDir(dirPath, moduleName) {
|
|
596
|
+
// Skip directories claimed by collectSkills
|
|
597
|
+
if (this.skillClaimedDirs && this.skillClaimedDirs.has(dirPath)) return [];
|
|
598
|
+
const tasks = [];
|
|
599
|
+
const files = await fs.readdir(dirPath);
|
|
600
|
+
// Load skill manifest for this directory (if present)
|
|
601
|
+
const skillManifest = await this.loadSkillManifest(dirPath);
|
|
602
|
+
|
|
603
|
+
for (const file of files) {
|
|
604
|
+
// Check for both .xml and .md files
|
|
605
|
+
if (file.endsWith('.xml') || file.endsWith('.md')) {
|
|
606
|
+
const filePath = path.join(dirPath, file);
|
|
607
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
608
|
+
|
|
609
|
+
// Skip internal/engine files (not user-facing tasks)
|
|
610
|
+
if (content.includes('internal="true"')) {
|
|
611
|
+
continue;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
let name = file.replace(/\.(xml|md)$/, '');
|
|
615
|
+
let displayName = name;
|
|
616
|
+
let description = '';
|
|
617
|
+
let standalone = false;
|
|
618
|
+
|
|
619
|
+
if (file.endsWith('.md')) {
|
|
620
|
+
// Parse YAML frontmatter for .md tasks
|
|
621
|
+
const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
622
|
+
if (frontmatterMatch) {
|
|
623
|
+
try {
|
|
624
|
+
const frontmatter = yaml.parse(frontmatterMatch[1]);
|
|
625
|
+
name = frontmatter.name || name;
|
|
626
|
+
displayName = frontmatter.displayName || frontmatter.name || name;
|
|
627
|
+
description = this.cleanForCSV(frontmatter.description || '');
|
|
628
|
+
// Tasks are standalone by default unless explicitly false (internal=true is already filtered above)
|
|
629
|
+
standalone = frontmatter.standalone !== false && frontmatter.standalone !== 'false';
|
|
630
|
+
} catch {
|
|
631
|
+
// If YAML parsing fails, use defaults
|
|
632
|
+
standalone = true; // Default to standalone
|
|
633
|
+
}
|
|
634
|
+
} else {
|
|
635
|
+
standalone = true; // No frontmatter means standalone
|
|
636
|
+
}
|
|
637
|
+
} else {
|
|
638
|
+
// For .xml tasks, extract from tag attributes
|
|
639
|
+
const nameMatch = content.match(/name="([^"]+)"/);
|
|
640
|
+
displayName = nameMatch ? nameMatch[1] : name;
|
|
641
|
+
|
|
642
|
+
const descMatch = content.match(/description="([^"]+)"/);
|
|
643
|
+
const objMatch = content.match(/<objective>([^<]+)<\/objective>/);
|
|
644
|
+
description = this.cleanForCSV(descMatch ? descMatch[1] : objMatch ? objMatch[1].trim() : '');
|
|
645
|
+
|
|
646
|
+
const standaloneFalseMatch = content.match(/<task[^>]+standalone="false"/);
|
|
647
|
+
standalone = !standaloneFalseMatch;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// Build relative path for installation
|
|
651
|
+
const installPath =
|
|
652
|
+
moduleName === 'core' ? `${this.xiaomaFolderName}/core/tasks/${file}` : `${this.xiaomaFolderName}/${moduleName}/tasks/${file}`;
|
|
653
|
+
|
|
654
|
+
tasks.push({
|
|
655
|
+
name: name,
|
|
656
|
+
displayName: displayName,
|
|
657
|
+
description: description,
|
|
658
|
+
module: moduleName,
|
|
659
|
+
path: installPath,
|
|
660
|
+
standalone: standalone,
|
|
661
|
+
canonicalId: this.getCanonicalId(skillManifest, file),
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
// Add to files list
|
|
665
|
+
this.files.push({
|
|
666
|
+
type: 'task',
|
|
667
|
+
name: name,
|
|
668
|
+
module: moduleName,
|
|
669
|
+
path: installPath,
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
return tasks;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* Collect all tools from core and selected modules
|
|
679
|
+
* Scans the INSTALLED xiaoma directory, not the source
|
|
680
|
+
*/
|
|
681
|
+
async collectTools(selectedModules) {
|
|
682
|
+
this.tools = [];
|
|
683
|
+
|
|
684
|
+
// Use updatedModules which already includes deduplicated 'core' + selectedModules
|
|
685
|
+
for (const moduleName of this.updatedModules) {
|
|
686
|
+
const toolsPath = path.join(this.xiaomaDir, moduleName, 'tools');
|
|
687
|
+
|
|
688
|
+
if (await fs.pathExists(toolsPath)) {
|
|
689
|
+
const moduleTools = await this.getToolsFromDir(toolsPath, moduleName);
|
|
690
|
+
this.tools.push(...moduleTools);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
/**
|
|
696
|
+
* Get tools from a directory
|
|
697
|
+
*/
|
|
698
|
+
async getToolsFromDir(dirPath, moduleName) {
|
|
699
|
+
// Skip directories claimed by collectSkills
|
|
700
|
+
if (this.skillClaimedDirs && this.skillClaimedDirs.has(dirPath)) return [];
|
|
701
|
+
const tools = [];
|
|
702
|
+
const files = await fs.readdir(dirPath);
|
|
703
|
+
// Load skill manifest for this directory (if present)
|
|
704
|
+
const skillManifest = await this.loadSkillManifest(dirPath);
|
|
705
|
+
|
|
706
|
+
for (const file of files) {
|
|
707
|
+
// Check for both .xml and .md files
|
|
708
|
+
if (file.endsWith('.xml') || file.endsWith('.md')) {
|
|
709
|
+
const filePath = path.join(dirPath, file);
|
|
710
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
711
|
+
|
|
712
|
+
// Skip internal tools (same as tasks)
|
|
713
|
+
if (content.includes('internal="true"')) {
|
|
714
|
+
continue;
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
let name = file.replace(/\.(xml|md)$/, '');
|
|
718
|
+
let displayName = name;
|
|
719
|
+
let description = '';
|
|
720
|
+
let standalone = false;
|
|
721
|
+
|
|
722
|
+
if (file.endsWith('.md')) {
|
|
723
|
+
// Parse YAML frontmatter for .md tools
|
|
724
|
+
const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
725
|
+
if (frontmatterMatch) {
|
|
726
|
+
try {
|
|
727
|
+
const frontmatter = yaml.parse(frontmatterMatch[1]);
|
|
728
|
+
name = frontmatter.name || name;
|
|
729
|
+
displayName = frontmatter.displayName || frontmatter.name || name;
|
|
730
|
+
description = this.cleanForCSV(frontmatter.description || '');
|
|
731
|
+
// Tools are standalone by default unless explicitly false (internal=true is already filtered above)
|
|
732
|
+
standalone = frontmatter.standalone !== false && frontmatter.standalone !== 'false';
|
|
733
|
+
} catch {
|
|
734
|
+
// If YAML parsing fails, use defaults
|
|
735
|
+
standalone = true; // Default to standalone
|
|
736
|
+
}
|
|
737
|
+
} else {
|
|
738
|
+
standalone = true; // No frontmatter means standalone
|
|
739
|
+
}
|
|
740
|
+
} else {
|
|
741
|
+
// For .xml tools, extract from tag attributes
|
|
742
|
+
const nameMatch = content.match(/name="([^"]+)"/);
|
|
743
|
+
displayName = nameMatch ? nameMatch[1] : name;
|
|
744
|
+
|
|
745
|
+
const descMatch = content.match(/description="([^"]+)"/);
|
|
746
|
+
const objMatch = content.match(/<objective>([^<]+)<\/objective>/);
|
|
747
|
+
description = this.cleanForCSV(descMatch ? descMatch[1] : objMatch ? objMatch[1].trim() : '');
|
|
748
|
+
|
|
749
|
+
const standaloneFalseMatch = content.match(/<tool[^>]+standalone="false"/);
|
|
750
|
+
standalone = !standaloneFalseMatch;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
// Build relative path for installation
|
|
754
|
+
const installPath =
|
|
755
|
+
moduleName === 'core' ? `${this.xiaomaFolderName}/core/tools/${file}` : `${this.xiaomaFolderName}/${moduleName}/tools/${file}`;
|
|
756
|
+
|
|
757
|
+
tools.push({
|
|
758
|
+
name: name,
|
|
759
|
+
displayName: displayName,
|
|
760
|
+
description: description,
|
|
761
|
+
module: moduleName,
|
|
762
|
+
path: installPath,
|
|
763
|
+
standalone: standalone,
|
|
764
|
+
canonicalId: this.getCanonicalId(skillManifest, file),
|
|
765
|
+
});
|
|
766
|
+
|
|
767
|
+
// Add to files list
|
|
768
|
+
this.files.push({
|
|
769
|
+
type: 'tool',
|
|
770
|
+
name: name,
|
|
771
|
+
module: moduleName,
|
|
772
|
+
path: installPath,
|
|
773
|
+
});
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
return tools;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
/**
|
|
781
|
+
* Write main manifest as YAML with installation info only
|
|
782
|
+
* Fetches fresh version info for all modules
|
|
783
|
+
* @returns {string} Path to the manifest file
|
|
784
|
+
*/
|
|
785
|
+
async writeMainManifest(cfgDir) {
|
|
786
|
+
const manifestPath = path.join(cfgDir, 'manifest.yaml');
|
|
787
|
+
|
|
788
|
+
// Read existing manifest to preserve install date
|
|
789
|
+
let existingInstallDate = null;
|
|
790
|
+
const existingModulesMap = new Map();
|
|
791
|
+
|
|
792
|
+
if (await fs.pathExists(manifestPath)) {
|
|
793
|
+
try {
|
|
794
|
+
const existingContent = await fs.readFile(manifestPath, 'utf8');
|
|
795
|
+
const existingManifest = yaml.parse(existingContent);
|
|
796
|
+
|
|
797
|
+
// Preserve original install date
|
|
798
|
+
if (existingManifest.installation?.installDate) {
|
|
799
|
+
existingInstallDate = existingManifest.installation.installDate;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
// Build map of existing modules for quick lookup
|
|
803
|
+
if (existingManifest.modules && Array.isArray(existingManifest.modules)) {
|
|
804
|
+
for (const m of existingManifest.modules) {
|
|
805
|
+
if (typeof m === 'object' && m.name) {
|
|
806
|
+
existingModulesMap.set(m.name, m);
|
|
807
|
+
} else if (typeof m === 'string') {
|
|
808
|
+
existingModulesMap.set(m, { installDate: existingInstallDate });
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
} catch {
|
|
813
|
+
// If we can't read existing manifest, continue with defaults
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
// Fetch fresh version info for all modules
|
|
818
|
+
const { Manifest } = require('./manifest');
|
|
819
|
+
const manifestObj = new Manifest();
|
|
820
|
+
const updatedModules = [];
|
|
821
|
+
|
|
822
|
+
for (const moduleName of this.modules) {
|
|
823
|
+
// Get fresh version info from source
|
|
824
|
+
const versionInfo = await manifestObj.getModuleVersionInfo(moduleName, this.xiaomaDir);
|
|
825
|
+
|
|
826
|
+
// Get existing install date if available
|
|
827
|
+
const existing = existingModulesMap.get(moduleName);
|
|
828
|
+
|
|
829
|
+
updatedModules.push({
|
|
830
|
+
name: moduleName,
|
|
831
|
+
version: versionInfo.version,
|
|
832
|
+
installDate: existing?.installDate || new Date().toISOString(),
|
|
833
|
+
lastUpdated: new Date().toISOString(),
|
|
834
|
+
source: versionInfo.source,
|
|
835
|
+
npmPackage: versionInfo.npmPackage,
|
|
836
|
+
repoUrl: versionInfo.repoUrl,
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
const manifest = {
|
|
841
|
+
installation: {
|
|
842
|
+
version: packageJson.version,
|
|
843
|
+
installDate: existingInstallDate || new Date().toISOString(),
|
|
844
|
+
lastUpdated: new Date().toISOString(),
|
|
845
|
+
},
|
|
846
|
+
modules: updatedModules,
|
|
847
|
+
ides: this.selectedIdes,
|
|
848
|
+
};
|
|
849
|
+
|
|
850
|
+
// Clean the manifest to remove any non-serializable values
|
|
851
|
+
const cleanManifest = structuredClone(manifest);
|
|
852
|
+
|
|
853
|
+
const yamlStr = yaml.stringify(cleanManifest, {
|
|
854
|
+
indent: 2,
|
|
855
|
+
lineWidth: 0,
|
|
856
|
+
sortKeys: false,
|
|
857
|
+
});
|
|
858
|
+
|
|
859
|
+
// Ensure POSIX-compliant final newline
|
|
860
|
+
const content = yamlStr.endsWith('\n') ? yamlStr : yamlStr + '\n';
|
|
861
|
+
await fs.writeFile(manifestPath, content);
|
|
862
|
+
return manifestPath;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
/**
|
|
866
|
+
* Read existing CSV and preserve rows for modules NOT being updated
|
|
867
|
+
* @param {string} csvPath - Path to existing CSV file
|
|
868
|
+
* @param {number} moduleColumnIndex - Which column contains the module name (0-indexed)
|
|
869
|
+
* @param {Array<string>} expectedColumns - Expected column names in order
|
|
870
|
+
* @param {Object} defaultValues - Default values for missing columns
|
|
871
|
+
* @returns {Array} Preserved CSV rows (without header), upgraded to match expected columns
|
|
872
|
+
*/
|
|
873
|
+
async getPreservedCsvRows(csvPath, moduleColumnIndex, expectedColumns, defaultValues = {}) {
|
|
874
|
+
if (!(await fs.pathExists(csvPath)) || this.preservedModules.length === 0) {
|
|
875
|
+
return [];
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
try {
|
|
879
|
+
const content = await fs.readFile(csvPath, 'utf8');
|
|
880
|
+
const lines = content.trim().split('\n');
|
|
881
|
+
|
|
882
|
+
if (lines.length < 2) {
|
|
883
|
+
return []; // No data rows
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
// Parse header to understand old schema
|
|
887
|
+
const header = lines[0];
|
|
888
|
+
const headerColumns = header.match(/(".*?"|[^",\s]+)(?=\s*,|\s*$)/g) || [];
|
|
889
|
+
const oldColumns = headerColumns.map((c) => c.replaceAll(/^"|"$/g, ''));
|
|
890
|
+
|
|
891
|
+
// Skip header row for data
|
|
892
|
+
const dataRows = lines.slice(1);
|
|
893
|
+
const preservedRows = [];
|
|
894
|
+
|
|
895
|
+
for (const row of dataRows) {
|
|
896
|
+
// Simple CSV parsing (handles quoted values)
|
|
897
|
+
const columns = row.match(/(".*?"|[^",\s]+)(?=\s*,|\s*$)/g) || [];
|
|
898
|
+
const cleanColumns = columns.map((c) => c.replaceAll(/^"|"$/g, ''));
|
|
899
|
+
|
|
900
|
+
const moduleValue = cleanColumns[moduleColumnIndex];
|
|
901
|
+
|
|
902
|
+
// Keep this row if it belongs to a preserved module
|
|
903
|
+
if (this.preservedModules.includes(moduleValue)) {
|
|
904
|
+
// Upgrade row to match expected schema
|
|
905
|
+
const upgradedRow = this.upgradeRowToSchema(cleanColumns, oldColumns, expectedColumns, defaultValues);
|
|
906
|
+
preservedRows.push(upgradedRow);
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
return preservedRows;
|
|
911
|
+
} catch (error) {
|
|
912
|
+
await prompts.log.warn(`Failed to read existing CSV ${csvPath}: ${error.message}`);
|
|
913
|
+
return [];
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
/**
|
|
918
|
+
* Upgrade a CSV row from old schema to new schema
|
|
919
|
+
* @param {Array<string>} rowValues - Values from old row
|
|
920
|
+
* @param {Array<string>} oldColumns - Old column names
|
|
921
|
+
* @param {Array<string>} newColumns - New column names
|
|
922
|
+
* @param {Object} defaultValues - Default values for missing columns
|
|
923
|
+
* @returns {string} Upgraded CSV row
|
|
924
|
+
*/
|
|
925
|
+
upgradeRowToSchema(rowValues, oldColumns, newColumns, defaultValues) {
|
|
926
|
+
const upgradedValues = [];
|
|
927
|
+
|
|
928
|
+
for (const newCol of newColumns) {
|
|
929
|
+
const oldIndex = oldColumns.indexOf(newCol);
|
|
930
|
+
|
|
931
|
+
if (oldIndex !== -1 && oldIndex < rowValues.length) {
|
|
932
|
+
// Column exists in old schema, use its value
|
|
933
|
+
upgradedValues.push(rowValues[oldIndex]);
|
|
934
|
+
} else if (defaultValues[newCol] === undefined) {
|
|
935
|
+
// Column missing, no default provided
|
|
936
|
+
upgradedValues.push('');
|
|
937
|
+
} else {
|
|
938
|
+
// Column missing, use default value
|
|
939
|
+
upgradedValues.push(defaultValues[newCol]);
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
// Properly quote values and join
|
|
944
|
+
return upgradedValues.map((v) => `"${v}"`).join(',');
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
/**
|
|
948
|
+
* Write workflow manifest CSV
|
|
949
|
+
* @returns {string} Path to the manifest file
|
|
950
|
+
*/
|
|
951
|
+
async writeWorkflowManifest(cfgDir) {
|
|
952
|
+
const csvPath = path.join(cfgDir, 'workflow-manifest.csv');
|
|
953
|
+
const escapeCsv = (value) => `"${String(value ?? '').replaceAll('"', '""')}"`;
|
|
954
|
+
|
|
955
|
+
// Create CSV header - standalone column removed, canonicalId added as optional column
|
|
956
|
+
let csv = 'name,description,module,path,canonicalId\n';
|
|
957
|
+
|
|
958
|
+
// Build workflows map from discovered workflows only
|
|
959
|
+
// Old entries are NOT preserved - the manifest reflects what actually exists on disk
|
|
960
|
+
const allWorkflows = new Map();
|
|
961
|
+
|
|
962
|
+
// Only add workflows that were actually discovered in this scan
|
|
963
|
+
for (const workflow of this.workflows) {
|
|
964
|
+
const key = `${workflow.module}:${workflow.name}`;
|
|
965
|
+
allWorkflows.set(key, {
|
|
966
|
+
name: workflow.name,
|
|
967
|
+
description: workflow.description,
|
|
968
|
+
module: workflow.module,
|
|
969
|
+
path: workflow.path,
|
|
970
|
+
canonicalId: workflow.canonicalId || '',
|
|
971
|
+
});
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
// Write all workflows
|
|
975
|
+
for (const [, value] of allWorkflows) {
|
|
976
|
+
const row = [
|
|
977
|
+
escapeCsv(value.name),
|
|
978
|
+
escapeCsv(value.description),
|
|
979
|
+
escapeCsv(value.module),
|
|
980
|
+
escapeCsv(value.path),
|
|
981
|
+
escapeCsv(value.canonicalId),
|
|
982
|
+
].join(',');
|
|
983
|
+
csv += row + '\n';
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
await fs.writeFile(csvPath, csv);
|
|
987
|
+
return csvPath;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
/**
|
|
991
|
+
* Write skill manifest CSV
|
|
992
|
+
* @returns {string} Path to the manifest file
|
|
993
|
+
*/
|
|
994
|
+
async writeSkillManifest(cfgDir) {
|
|
995
|
+
const csvPath = path.join(cfgDir, 'skill-manifest.csv');
|
|
996
|
+
const escapeCsv = (value) => `"${String(value ?? '').replaceAll('"', '""')}"`;
|
|
997
|
+
|
|
998
|
+
let csvContent = 'canonicalId,name,description,module,path,install_to_xiaoma\n';
|
|
999
|
+
|
|
1000
|
+
for (const skill of this.skills) {
|
|
1001
|
+
const row = [
|
|
1002
|
+
escapeCsv(skill.canonicalId),
|
|
1003
|
+
escapeCsv(skill.name),
|
|
1004
|
+
escapeCsv(skill.description),
|
|
1005
|
+
escapeCsv(skill.module),
|
|
1006
|
+
escapeCsv(skill.path),
|
|
1007
|
+
escapeCsv(skill.install_to_xiaoma),
|
|
1008
|
+
].join(',');
|
|
1009
|
+
csvContent += row + '\n';
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
await fs.writeFile(csvPath, csvContent);
|
|
1013
|
+
return csvPath;
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
/**
|
|
1017
|
+
* Write agent manifest CSV
|
|
1018
|
+
* @returns {string} Path to the manifest file
|
|
1019
|
+
*/
|
|
1020
|
+
async writeAgentManifest(cfgDir) {
|
|
1021
|
+
const csvPath = path.join(cfgDir, 'agent-manifest.csv');
|
|
1022
|
+
const escapeCsv = (value) => `"${String(value ?? '').replaceAll('"', '""')}"`;
|
|
1023
|
+
|
|
1024
|
+
// Read existing manifest to preserve entries
|
|
1025
|
+
const existingEntries = new Map();
|
|
1026
|
+
if (await fs.pathExists(csvPath)) {
|
|
1027
|
+
const content = await fs.readFile(csvPath, 'utf8');
|
|
1028
|
+
const records = csv.parse(content, {
|
|
1029
|
+
columns: true,
|
|
1030
|
+
skip_empty_lines: true,
|
|
1031
|
+
});
|
|
1032
|
+
for (const record of records) {
|
|
1033
|
+
existingEntries.set(`${record.module}:${record.name}`, record);
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
// Create CSV header with persona fields and canonicalId
|
|
1038
|
+
let csvContent = 'name,displayName,title,icon,capabilities,role,identity,communicationStyle,principles,module,path,canonicalId\n';
|
|
1039
|
+
|
|
1040
|
+
// Combine existing and new agents, preferring new data for duplicates
|
|
1041
|
+
const allAgents = new Map();
|
|
1042
|
+
|
|
1043
|
+
// Add existing entries
|
|
1044
|
+
for (const [key, value] of existingEntries) {
|
|
1045
|
+
allAgents.set(key, value);
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
// Add/update new agents
|
|
1049
|
+
for (const agent of this.agents) {
|
|
1050
|
+
const key = `${agent.module}:${agent.name}`;
|
|
1051
|
+
allAgents.set(key, {
|
|
1052
|
+
name: agent.name,
|
|
1053
|
+
displayName: agent.displayName,
|
|
1054
|
+
title: agent.title,
|
|
1055
|
+
icon: agent.icon,
|
|
1056
|
+
capabilities: agent.capabilities,
|
|
1057
|
+
role: agent.role,
|
|
1058
|
+
identity: agent.identity,
|
|
1059
|
+
communicationStyle: agent.communicationStyle,
|
|
1060
|
+
principles: agent.principles,
|
|
1061
|
+
module: agent.module,
|
|
1062
|
+
path: agent.path,
|
|
1063
|
+
canonicalId: agent.canonicalId || '',
|
|
1064
|
+
});
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
// Write all agents
|
|
1068
|
+
for (const [, record] of allAgents) {
|
|
1069
|
+
const row = [
|
|
1070
|
+
escapeCsv(record.name),
|
|
1071
|
+
escapeCsv(record.displayName),
|
|
1072
|
+
escapeCsv(record.title),
|
|
1073
|
+
escapeCsv(record.icon),
|
|
1074
|
+
escapeCsv(record.capabilities),
|
|
1075
|
+
escapeCsv(record.role),
|
|
1076
|
+
escapeCsv(record.identity),
|
|
1077
|
+
escapeCsv(record.communicationStyle),
|
|
1078
|
+
escapeCsv(record.principles),
|
|
1079
|
+
escapeCsv(record.module),
|
|
1080
|
+
escapeCsv(record.path),
|
|
1081
|
+
escapeCsv(record.canonicalId),
|
|
1082
|
+
].join(',');
|
|
1083
|
+
csvContent += row + '\n';
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
await fs.writeFile(csvPath, csvContent);
|
|
1087
|
+
return csvPath;
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
/**
|
|
1091
|
+
* Write task manifest CSV
|
|
1092
|
+
* @returns {string} Path to the manifest file
|
|
1093
|
+
*/
|
|
1094
|
+
async writeTaskManifest(cfgDir) {
|
|
1095
|
+
const csvPath = path.join(cfgDir, 'task-manifest.csv');
|
|
1096
|
+
const escapeCsv = (value) => `"${String(value ?? '').replaceAll('"', '""')}"`;
|
|
1097
|
+
|
|
1098
|
+
// Read existing manifest to preserve entries
|
|
1099
|
+
const existingEntries = new Map();
|
|
1100
|
+
if (await fs.pathExists(csvPath)) {
|
|
1101
|
+
const content = await fs.readFile(csvPath, 'utf8');
|
|
1102
|
+
const records = csv.parse(content, {
|
|
1103
|
+
columns: true,
|
|
1104
|
+
skip_empty_lines: true,
|
|
1105
|
+
});
|
|
1106
|
+
for (const record of records) {
|
|
1107
|
+
existingEntries.set(`${record.module}:${record.name}`, record);
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
// Create CSV header with standalone and canonicalId columns
|
|
1112
|
+
let csvContent = 'name,displayName,description,module,path,standalone,canonicalId\n';
|
|
1113
|
+
|
|
1114
|
+
// Combine existing and new tasks
|
|
1115
|
+
const allTasks = new Map();
|
|
1116
|
+
|
|
1117
|
+
// Add existing entries
|
|
1118
|
+
for (const [key, value] of existingEntries) {
|
|
1119
|
+
allTasks.set(key, value);
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
// Add/update new tasks
|
|
1123
|
+
for (const task of this.tasks) {
|
|
1124
|
+
const key = `${task.module}:${task.name}`;
|
|
1125
|
+
allTasks.set(key, {
|
|
1126
|
+
name: task.name,
|
|
1127
|
+
displayName: task.displayName,
|
|
1128
|
+
description: task.description,
|
|
1129
|
+
module: task.module,
|
|
1130
|
+
path: task.path,
|
|
1131
|
+
standalone: task.standalone,
|
|
1132
|
+
canonicalId: task.canonicalId || '',
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
// Write all tasks
|
|
1137
|
+
for (const [, record] of allTasks) {
|
|
1138
|
+
const row = [
|
|
1139
|
+
escapeCsv(record.name),
|
|
1140
|
+
escapeCsv(record.displayName),
|
|
1141
|
+
escapeCsv(record.description),
|
|
1142
|
+
escapeCsv(record.module),
|
|
1143
|
+
escapeCsv(record.path),
|
|
1144
|
+
escapeCsv(record.standalone),
|
|
1145
|
+
escapeCsv(record.canonicalId),
|
|
1146
|
+
].join(',');
|
|
1147
|
+
csvContent += row + '\n';
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
await fs.writeFile(csvPath, csvContent);
|
|
1151
|
+
return csvPath;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
/**
|
|
1155
|
+
* Write tool manifest CSV
|
|
1156
|
+
* @returns {string} Path to the manifest file
|
|
1157
|
+
*/
|
|
1158
|
+
async writeToolManifest(cfgDir) {
|
|
1159
|
+
const csvPath = path.join(cfgDir, 'tool-manifest.csv');
|
|
1160
|
+
const escapeCsv = (value) => `"${String(value ?? '').replaceAll('"', '""')}"`;
|
|
1161
|
+
|
|
1162
|
+
// Read existing manifest to preserve entries
|
|
1163
|
+
const existingEntries = new Map();
|
|
1164
|
+
if (await fs.pathExists(csvPath)) {
|
|
1165
|
+
const content = await fs.readFile(csvPath, 'utf8');
|
|
1166
|
+
const records = csv.parse(content, {
|
|
1167
|
+
columns: true,
|
|
1168
|
+
skip_empty_lines: true,
|
|
1169
|
+
});
|
|
1170
|
+
for (const record of records) {
|
|
1171
|
+
existingEntries.set(`${record.module}:${record.name}`, record);
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
// Create CSV header with standalone and canonicalId columns
|
|
1176
|
+
let csvContent = 'name,displayName,description,module,path,standalone,canonicalId\n';
|
|
1177
|
+
|
|
1178
|
+
// Combine existing and new tools
|
|
1179
|
+
const allTools = new Map();
|
|
1180
|
+
|
|
1181
|
+
// Add existing entries
|
|
1182
|
+
for (const [key, value] of existingEntries) {
|
|
1183
|
+
allTools.set(key, value);
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
// Add/update new tools
|
|
1187
|
+
for (const tool of this.tools) {
|
|
1188
|
+
const key = `${tool.module}:${tool.name}`;
|
|
1189
|
+
allTools.set(key, {
|
|
1190
|
+
name: tool.name,
|
|
1191
|
+
displayName: tool.displayName,
|
|
1192
|
+
description: tool.description,
|
|
1193
|
+
module: tool.module,
|
|
1194
|
+
path: tool.path,
|
|
1195
|
+
standalone: tool.standalone,
|
|
1196
|
+
canonicalId: tool.canonicalId || '',
|
|
1197
|
+
});
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
// Write all tools
|
|
1201
|
+
for (const [, record] of allTools) {
|
|
1202
|
+
const row = [
|
|
1203
|
+
escapeCsv(record.name),
|
|
1204
|
+
escapeCsv(record.displayName),
|
|
1205
|
+
escapeCsv(record.description),
|
|
1206
|
+
escapeCsv(record.module),
|
|
1207
|
+
escapeCsv(record.path),
|
|
1208
|
+
escapeCsv(record.standalone),
|
|
1209
|
+
escapeCsv(record.canonicalId),
|
|
1210
|
+
].join(',');
|
|
1211
|
+
csvContent += row + '\n';
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
await fs.writeFile(csvPath, csvContent);
|
|
1215
|
+
return csvPath;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
/**
|
|
1219
|
+
* Write files manifest CSV
|
|
1220
|
+
*/
|
|
1221
|
+
/**
|
|
1222
|
+
* Calculate SHA256 hash of a file
|
|
1223
|
+
* @param {string} filePath - Path to file
|
|
1224
|
+
* @returns {string} SHA256 hash
|
|
1225
|
+
*/
|
|
1226
|
+
async calculateFileHash(filePath) {
|
|
1227
|
+
try {
|
|
1228
|
+
const content = await fs.readFile(filePath);
|
|
1229
|
+
return crypto.createHash('sha256').update(content).digest('hex');
|
|
1230
|
+
} catch {
|
|
1231
|
+
return '';
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
/**
|
|
1236
|
+
* @returns {string} Path to the manifest file
|
|
1237
|
+
*/
|
|
1238
|
+
async writeFilesManifest(cfgDir) {
|
|
1239
|
+
const csvPath = path.join(cfgDir, 'files-manifest.csv');
|
|
1240
|
+
|
|
1241
|
+
// Create CSV header with hash column
|
|
1242
|
+
let csv = 'type,name,module,path,hash\n';
|
|
1243
|
+
|
|
1244
|
+
// If we have ALL installed files, use those instead of just workflows/agents/tasks
|
|
1245
|
+
const allFiles = [];
|
|
1246
|
+
if (this.allInstalledFiles && this.allInstalledFiles.length > 0) {
|
|
1247
|
+
// Process all installed files
|
|
1248
|
+
for (const filePath of this.allInstalledFiles) {
|
|
1249
|
+
// Store paths relative to xiaomaDir (no folder prefix)
|
|
1250
|
+
const relativePath = filePath.replace(this.xiaomaDir, '').replaceAll('\\', '/').replace(/^\//, '');
|
|
1251
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
1252
|
+
const fileName = path.basename(filePath, ext);
|
|
1253
|
+
|
|
1254
|
+
// Determine module from path (first directory component)
|
|
1255
|
+
const pathParts = relativePath.split('/');
|
|
1256
|
+
const module = pathParts.length > 0 ? pathParts[0] : 'unknown';
|
|
1257
|
+
|
|
1258
|
+
// Calculate hash
|
|
1259
|
+
const hash = await this.calculateFileHash(filePath);
|
|
1260
|
+
|
|
1261
|
+
allFiles.push({
|
|
1262
|
+
type: ext.slice(1) || 'file',
|
|
1263
|
+
name: fileName,
|
|
1264
|
+
module: module,
|
|
1265
|
+
path: relativePath,
|
|
1266
|
+
hash: hash,
|
|
1267
|
+
});
|
|
1268
|
+
}
|
|
1269
|
+
} else {
|
|
1270
|
+
// Fallback: use the collected workflows/agents/tasks
|
|
1271
|
+
for (const file of this.files) {
|
|
1272
|
+
// Strip the folder prefix if present (for consistency)
|
|
1273
|
+
const relPath = file.path.replace(this.xiaomaFolderName + '/', '');
|
|
1274
|
+
const filePath = path.join(this.xiaomaDir, relPath);
|
|
1275
|
+
const hash = await this.calculateFileHash(filePath);
|
|
1276
|
+
allFiles.push({
|
|
1277
|
+
...file,
|
|
1278
|
+
path: relPath,
|
|
1279
|
+
hash: hash,
|
|
1280
|
+
});
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
// Sort files by module, then type, then name
|
|
1285
|
+
allFiles.sort((a, b) => {
|
|
1286
|
+
if (a.module !== b.module) return a.module.localeCompare(b.module);
|
|
1287
|
+
if (a.type !== b.type) return a.type.localeCompare(b.type);
|
|
1288
|
+
return a.name.localeCompare(b.name);
|
|
1289
|
+
});
|
|
1290
|
+
|
|
1291
|
+
// Add all files
|
|
1292
|
+
for (const file of allFiles) {
|
|
1293
|
+
csv += `"${file.type}","${file.name}","${file.module}","${file.path}","${file.hash}"\n`;
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
await fs.writeFile(csvPath, csv);
|
|
1297
|
+
return csvPath;
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
/**
|
|
1301
|
+
* Scan the xiaoma directory to find all installed modules
|
|
1302
|
+
* @param {string} xiaomaDir - Path to xiaoma directory
|
|
1303
|
+
* @returns {Array} List of module names
|
|
1304
|
+
*/
|
|
1305
|
+
async scanInstalledModules(xiaomaDir) {
|
|
1306
|
+
const modules = [];
|
|
1307
|
+
|
|
1308
|
+
try {
|
|
1309
|
+
const entries = await fs.readdir(xiaomaDir, { withFileTypes: true });
|
|
1310
|
+
|
|
1311
|
+
for (const entry of entries) {
|
|
1312
|
+
// Skip if not a directory or is a special directory
|
|
1313
|
+
if (!entry.isDirectory() || entry.name.startsWith('.') || entry.name === '_config') {
|
|
1314
|
+
continue;
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
// Check if this looks like a module (has agents, workflows, or tasks directory)
|
|
1318
|
+
const modulePath = path.join(xiaomaDir, entry.name);
|
|
1319
|
+
const hasAgents = await fs.pathExists(path.join(modulePath, 'agents'));
|
|
1320
|
+
const hasWorkflows = await fs.pathExists(path.join(modulePath, 'workflows'));
|
|
1321
|
+
const hasTasks = await fs.pathExists(path.join(modulePath, 'tasks'));
|
|
1322
|
+
const hasTools = await fs.pathExists(path.join(modulePath, 'tools'));
|
|
1323
|
+
|
|
1324
|
+
// Check for skill-only modules: recursive scan for xiaoma-skill-manifest.yaml with type: skill
|
|
1325
|
+
let hasSkills = false;
|
|
1326
|
+
if (!hasAgents && !hasWorkflows && !hasTasks && !hasTools) {
|
|
1327
|
+
hasSkills = await this._hasSkillManifestRecursive(modulePath);
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
// If it has any of these directories or skill manifests, it's likely a module
|
|
1331
|
+
if (hasAgents || hasWorkflows || hasTasks || hasTools || hasSkills) {
|
|
1332
|
+
modules.push(entry.name);
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
} catch (error) {
|
|
1336
|
+
await prompts.log.warn(`Could not scan for installed modules: ${error.message}`);
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
return modules;
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
/**
|
|
1343
|
+
* Recursively check if a directory tree contains a xiaoma-skill-manifest.yaml with type: skill.
|
|
1344
|
+
* Skips directories starting with . or _.
|
|
1345
|
+
* @param {string} dir - Directory to search
|
|
1346
|
+
* @returns {boolean} True if a skill manifest is found
|
|
1347
|
+
*/
|
|
1348
|
+
async _hasSkillManifestRecursive(dir) {
|
|
1349
|
+
let entries;
|
|
1350
|
+
try {
|
|
1351
|
+
entries = await fs.readdir(dir, { withFileTypes: true });
|
|
1352
|
+
} catch {
|
|
1353
|
+
return false;
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
// Check for manifest in this directory
|
|
1357
|
+
const manifest = await this.loadSkillManifest(dir);
|
|
1358
|
+
if (manifest) {
|
|
1359
|
+
const type = this.getArtifactType(manifest, 'workflow.md');
|
|
1360
|
+
if (type === 'skill') return true;
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
// Recurse into subdirectories
|
|
1364
|
+
for (const entry of entries) {
|
|
1365
|
+
if (!entry.isDirectory()) continue;
|
|
1366
|
+
if (entry.name.startsWith('.') || entry.name.startsWith('_')) continue;
|
|
1367
|
+
if (await this._hasSkillManifestRecursive(path.join(dir, entry.name))) return true;
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
return false;
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
module.exports = { ManifestGenerator };
|