drt-method 1.0.0
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/AGENTS.md +45 -0
- package/GETTING-STARTED.md +269 -0
- package/README.md +233 -0
- package/drt-method-1.0.0.tgz +0 -0
- package/drt-modules.yaml +1 -0
- package/package.json +51 -0
- package/scripts/install-from-github.ps1 +22 -0
- package/scripts/install-from-github.sh +17 -0
- package/src/core-skills/drt-advanced-elicitation/SKILL.md +142 -0
- package/src/core-skills/drt-advanced-elicitation/methods.csv +72 -0
- package/src/core-skills/drt-brainstorming/SKILL.md +80 -0
- package/src/core-skills/drt-brainstorming/assets/brain-icons.json +166 -0
- package/src/core-skills/drt-brainstorming/assets/brain-methods.csv +109 -0
- package/src/core-skills/drt-brainstorming/assets/brain-selector.html +326 -0
- package/src/core-skills/drt-brainstorming/customize.toml +84 -0
- package/src/core-skills/drt-brainstorming/references/converge.md +24 -0
- package/src/core-skills/drt-brainstorming/references/finalize.md +26 -0
- package/src/core-skills/drt-brainstorming/references/headless.md +54 -0
- package/src/core-skills/drt-brainstorming/references/in-chat-techniques.md +18 -0
- package/src/core-skills/drt-brainstorming/references/mode-autonomous.md +10 -0
- package/src/core-skills/drt-brainstorming/references/mode-facilitator.md +11 -0
- package/src/core-skills/drt-brainstorming/references/mode-partner.md +16 -0
- package/src/core-skills/drt-brainstorming/references/resume.md +5 -0
- package/src/core-skills/drt-brainstorming/scripts/brain.py +740 -0
- package/src/core-skills/drt-customize/SKILL.md +111 -0
- package/src/core-skills/drt-customize/scripts/list_customizable_skills.py +231 -0
- package/src/core-skills/drt-editorial-review-prose/SKILL.md +86 -0
- package/src/core-skills/drt-editorial-review-structure/SKILL.md +179 -0
- package/src/core-skills/drt-forge-idea/SKILL.md +107 -0
- package/src/core-skills/drt-forge-idea/customize.toml +42 -0
- package/src/core-skills/drt-forge-idea/scripts/resolve_personas.py +270 -0
- package/src/core-skills/drt-help/SKILL.md +75 -0
- package/src/core-skills/drt-index-docs/SKILL.md +66 -0
- package/src/core-skills/drt-party-mode/SKILL.md +60 -0
- package/src/core-skills/drt-party-mode/customize.toml +211 -0
- package/src/core-skills/drt-party-mode/references/create-party.md +70 -0
- package/src/core-skills/drt-party-mode/references/mode-agent-team.md +13 -0
- package/src/core-skills/drt-party-mode/references/mode-auto.md +13 -0
- package/src/core-skills/drt-party-mode/references/mode-subagent.md +31 -0
- package/src/core-skills/drt-party-mode/references/party-memory.md +51 -0
- package/src/core-skills/drt-party-mode/scripts/resolve_party.py +272 -0
- package/src/core-skills/drt-review-adversarial-general/SKILL.md +37 -0
- package/src/core-skills/drt-review-edge-case-hunter/SKILL.md +73 -0
- package/src/core-skills/drt-review-edge-case-hunter/references/deletion-check.md +14 -0
- package/src/core-skills/drt-review-verification-gap/SKILL.md +106 -0
- package/src/core-skills/drt-shard-doc/SKILL.md +105 -0
- package/src/core-skills/drt-spec/SKILL.md +160 -0
- package/src/core-skills/drt-spec/assets/headless-schemas.md +33 -0
- package/src/core-skills/drt-spec/assets/spec-template.md +49 -0
- package/src/core-skills/drt-spec/assets/stories-schema.md +44 -0
- package/src/core-skills/drt-spec/customize.toml +53 -0
- package/src/core-skills/module-help.csv +14 -0
- package/src/core-skills/module.yaml +33 -0
- package/src/drt-skills/1-analysis/drt-agent-analyst/SKILL.md +76 -0
- package/src/drt-skills/1-analysis/drt-agent-analyst/customize.toml +90 -0
- package/src/drt-skills/1-analysis/drt-agent-tech-writer/SKILL.md +76 -0
- package/src/drt-skills/1-analysis/drt-agent-tech-writer/customize.toml +81 -0
- package/src/drt-skills/1-analysis/drt-agent-tech-writer/explain-concept.md +20 -0
- package/src/drt-skills/1-analysis/drt-agent-tech-writer/mermaid-gen.md +20 -0
- package/src/drt-skills/1-analysis/drt-agent-tech-writer/validate-doc.md +19 -0
- package/src/drt-skills/1-analysis/drt-agent-tech-writer/write-document.md +20 -0
- package/src/drt-skills/1-analysis/drt-document-project/SKILL.md +62 -0
- package/src/drt-skills/1-analysis/drt-document-project/checklist.md +245 -0
- package/src/drt-skills/1-analysis/drt-document-project/customize.toml +41 -0
- package/src/drt-skills/1-analysis/drt-document-project/documentation-requirements.csv +12 -0
- package/src/drt-skills/1-analysis/drt-document-project/instructions.md +128 -0
- package/src/drt-skills/1-analysis/drt-document-project/templates/deep-dive-template.md +345 -0
- package/src/drt-skills/1-analysis/drt-document-project/templates/index-template.md +169 -0
- package/src/drt-skills/1-analysis/drt-document-project/templates/project-overview-template.md +103 -0
- package/src/drt-skills/1-analysis/drt-document-project/templates/project-scan-report-schema.json +160 -0
- package/src/drt-skills/1-analysis/drt-document-project/templates/source-tree-template.md +135 -0
- package/src/drt-skills/1-analysis/drt-document-project/workflows/deep-dive-instructions.md +300 -0
- package/src/drt-skills/1-analysis/drt-document-project/workflows/deep-dive-workflow.md +34 -0
- package/src/drt-skills/1-analysis/drt-document-project/workflows/full-scan-instructions.md +1111 -0
- package/src/drt-skills/1-analysis/drt-document-project/workflows/full-scan-workflow.md +34 -0
- package/src/drt-skills/1-analysis/drt-prfaq/SKILL.md +135 -0
- package/src/drt-skills/1-analysis/drt-prfaq/agents/artifact-analyzer.md +60 -0
- package/src/drt-skills/1-analysis/drt-prfaq/agents/web-researcher.md +49 -0
- package/src/drt-skills/1-analysis/drt-prfaq/assets/prfaq-template.md +62 -0
- package/src/drt-skills/1-analysis/drt-prfaq/bmad-manifest.json +16 -0
- package/src/drt-skills/1-analysis/drt-prfaq/customize.toml +41 -0
- package/src/drt-skills/1-analysis/drt-prfaq/references/customer-faq.md +55 -0
- package/src/drt-skills/1-analysis/drt-prfaq/references/internal-faq.md +51 -0
- package/src/drt-skills/1-analysis/drt-prfaq/references/press-release.md +60 -0
- package/src/drt-skills/1-analysis/drt-prfaq/references/verdict.md +83 -0
- package/src/drt-skills/1-analysis/drt-product-brief/SKILL.md +91 -0
- package/src/drt-skills/1-analysis/drt-product-brief/assets/brief-template.md +41 -0
- package/src/drt-skills/1-analysis/drt-product-brief/customize.toml +99 -0
- package/src/drt-skills/1-analysis/research/drt-domain-research/SKILL.md +96 -0
- package/src/drt-skills/1-analysis/research/drt-domain-research/customize.toml +41 -0
- package/src/drt-skills/1-analysis/research/drt-domain-research/domain-steps/step-01-init.md +137 -0
- package/src/drt-skills/1-analysis/research/drt-domain-research/domain-steps/step-02-domain-analysis.md +229 -0
- package/src/drt-skills/1-analysis/research/drt-domain-research/domain-steps/step-03-competitive-landscape.md +238 -0
- package/src/drt-skills/1-analysis/research/drt-domain-research/domain-steps/step-04-regulatory-focus.md +206 -0
- package/src/drt-skills/1-analysis/research/drt-domain-research/domain-steps/step-05-technical-trends.md +234 -0
- package/src/drt-skills/1-analysis/research/drt-domain-research/domain-steps/step-06-research-synthesis.md +450 -0
- package/src/drt-skills/1-analysis/research/drt-domain-research/research.template.md +29 -0
- package/src/drt-skills/1-analysis/research/drt-market-research/SKILL.md +96 -0
- package/src/drt-skills/1-analysis/research/drt-market-research/customize.toml +41 -0
- package/src/drt-skills/1-analysis/research/drt-market-research/research.template.md +29 -0
- package/src/drt-skills/1-analysis/research/drt-market-research/steps/step-01-init.md +184 -0
- package/src/drt-skills/1-analysis/research/drt-market-research/steps/step-02-customer-behavior.md +239 -0
- package/src/drt-skills/1-analysis/research/drt-market-research/steps/step-03-customer-pain-points.md +251 -0
- package/src/drt-skills/1-analysis/research/drt-market-research/steps/step-04-customer-decisions.md +261 -0
- package/src/drt-skills/1-analysis/research/drt-market-research/steps/step-05-competitive-analysis.md +173 -0
- package/src/drt-skills/1-analysis/research/drt-market-research/steps/step-06-research-completion.md +484 -0
- package/src/drt-skills/1-analysis/research/drt-technical-research/SKILL.md +96 -0
- package/src/drt-skills/1-analysis/research/drt-technical-research/customize.toml +41 -0
- package/src/drt-skills/1-analysis/research/drt-technical-research/research.template.md +29 -0
- package/src/drt-skills/1-analysis/research/drt-technical-research/technical-steps/step-01-init.md +137 -0
- package/src/drt-skills/1-analysis/research/drt-technical-research/technical-steps/step-02-technical-overview.md +239 -0
- package/src/drt-skills/1-analysis/research/drt-technical-research/technical-steps/step-03-integration-patterns.md +248 -0
- package/src/drt-skills/1-analysis/research/drt-technical-research/technical-steps/step-04-architectural-patterns.md +202 -0
- package/src/drt-skills/1-analysis/research/drt-technical-research/technical-steps/step-05-implementation-research.md +233 -0
- package/src/drt-skills/1-analysis/research/drt-technical-research/technical-steps/step-06-research-synthesis.md +493 -0
- package/src/drt-skills/2-plan-workflows/drt-agent-pm/SKILL.md +76 -0
- package/src/drt-skills/2-plan-workflows/drt-agent-pm/customize.toml +75 -0
- package/src/drt-skills/2-plan-workflows/drt-agent-ux-designer/SKILL.md +76 -0
- package/src/drt-skills/2-plan-workflows/drt-agent-ux-designer/customize.toml +60 -0
- package/src/drt-skills/2-plan-workflows/drt-create-prd/SKILL.md +30 -0
- package/src/drt-skills/2-plan-workflows/drt-create-prd/customize.toml +41 -0
- package/src/drt-skills/2-plan-workflows/drt-edit-prd/SKILL.md +30 -0
- package/src/drt-skills/2-plan-workflows/drt-edit-prd/customize.toml +42 -0
- package/src/drt-skills/2-plan-workflows/drt-prd/SKILL.md +92 -0
- package/src/drt-skills/2-plan-workflows/drt-prd/assets/headless-schemas.md +76 -0
- package/src/drt-skills/2-plan-workflows/drt-prd/assets/prd-template.md +165 -0
- package/src/drt-skills/2-plan-workflows/drt-prd/assets/prd-validation-checklist.md +135 -0
- package/src/drt-skills/2-plan-workflows/drt-prd/assets/validation-report-template.html +325 -0
- package/src/drt-skills/2-plan-workflows/drt-prd/customize.toml +147 -0
- package/src/drt-skills/2-plan-workflows/drt-prd/references/headless.md +39 -0
- package/src/drt-skills/2-plan-workflows/drt-prd/references/validate.md +97 -0
- package/src/drt-skills/2-plan-workflows/drt-ux/SKILL.md +90 -0
- package/src/drt-skills/2-plan-workflows/drt-ux/assets/color-themes.md +9 -0
- package/src/drt-skills/2-plan-workflows/drt-ux/assets/design-directions.md +9 -0
- package/src/drt-skills/2-plan-workflows/drt-ux/assets/design-example-editorial.md +158 -0
- package/src/drt-skills/2-plan-workflows/drt-ux/assets/design-example-mobile.md +93 -0
- package/src/drt-skills/2-plan-workflows/drt-ux/assets/design-example-shadcn.md +109 -0
- package/src/drt-skills/2-plan-workflows/drt-ux/assets/excalidraw-wireframe.md +19 -0
- package/src/drt-skills/2-plan-workflows/drt-ux/assets/experience-example-mobile.md +112 -0
- package/src/drt-skills/2-plan-workflows/drt-ux/assets/experience-example-shadcn.md +133 -0
- package/src/drt-skills/2-plan-workflows/drt-ux/assets/headless-schemas.md +84 -0
- package/src/drt-skills/2-plan-workflows/drt-ux/assets/key-screens.md +29 -0
- package/src/drt-skills/2-plan-workflows/drt-ux/assets/validation-report-template.html +319 -0
- package/src/drt-skills/2-plan-workflows/drt-ux/customize.toml +100 -0
- package/src/drt-skills/2-plan-workflows/drt-ux/references/creative-tools.md +19 -0
- package/src/drt-skills/2-plan-workflows/drt-ux/references/design-md-spec.md +50 -0
- package/src/drt-skills/2-plan-workflows/drt-ux/references/headless.md +37 -0
- package/src/drt-skills/2-plan-workflows/drt-ux/references/validate.md +115 -0
- package/src/drt-skills/2-plan-workflows/drt-validate-prd/SKILL.md +30 -0
- package/src/drt-skills/2-plan-workflows/drt-validate-prd/customize.toml +42 -0
- package/src/drt-skills/3-solutioning/drt-agent-architect/SKILL.md +76 -0
- package/src/drt-skills/3-solutioning/drt-agent-architect/customize.toml +65 -0
- package/src/drt-skills/3-solutioning/drt-architecture/SKILL.md +85 -0
- package/src/drt-skills/3-solutioning/drt-architecture/assets/spine-template.md +79 -0
- package/src/drt-skills/3-solutioning/drt-architecture/customize.toml +100 -0
- package/src/drt-skills/3-solutioning/drt-architecture/references/headless.md +26 -0
- package/src/drt-skills/3-solutioning/drt-architecture/references/reviewer-gate.md +13 -0
- package/src/drt-skills/3-solutioning/drt-architecture/scripts/lint_spine.py +257 -0
- package/src/drt-skills/3-solutioning/drt-check-implementation-readiness/SKILL.md +91 -0
- package/src/drt-skills/3-solutioning/drt-check-implementation-readiness/customize.toml +41 -0
- package/src/drt-skills/3-solutioning/drt-check-implementation-readiness/steps/step-01-document-discovery.md +179 -0
- package/src/drt-skills/3-solutioning/drt-check-implementation-readiness/steps/step-02-prd-analysis.md +168 -0
- package/src/drt-skills/3-solutioning/drt-check-implementation-readiness/steps/step-03-epic-coverage-validation.md +169 -0
- package/src/drt-skills/3-solutioning/drt-check-implementation-readiness/steps/step-04-ux-alignment.md +129 -0
- package/src/drt-skills/3-solutioning/drt-check-implementation-readiness/steps/step-05-epic-quality-review.md +241 -0
- package/src/drt-skills/3-solutioning/drt-check-implementation-readiness/steps/step-06-final-assessment.md +132 -0
- package/src/drt-skills/3-solutioning/drt-check-implementation-readiness/templates/readiness-report-template.md +4 -0
- package/src/drt-skills/3-solutioning/drt-create-architecture/SKILL.md +30 -0
- package/src/drt-skills/3-solutioning/drt-create-architecture/customize.toml +41 -0
- package/src/drt-skills/3-solutioning/drt-create-epics-and-stories/SKILL.md +93 -0
- package/src/drt-skills/3-solutioning/drt-create-epics-and-stories/customize.toml +41 -0
- package/src/drt-skills/3-solutioning/drt-create-epics-and-stories/steps/step-01-validate-prerequisites.md +263 -0
- package/src/drt-skills/3-solutioning/drt-create-epics-and-stories/steps/step-02-design-epics.md +242 -0
- package/src/drt-skills/3-solutioning/drt-create-epics-and-stories/steps/step-03-create-stories.md +255 -0
- package/src/drt-skills/3-solutioning/drt-create-epics-and-stories/steps/step-04-final-validation.md +143 -0
- package/src/drt-skills/3-solutioning/drt-create-epics-and-stories/templates/epics-template.md +61 -0
- package/src/drt-skills/3-solutioning/drt-generate-project-context/SKILL.md +81 -0
- package/src/drt-skills/3-solutioning/drt-generate-project-context/customize.toml +41 -0
- package/src/drt-skills/3-solutioning/drt-generate-project-context/project-context-template.md +21 -0
- package/src/drt-skills/3-solutioning/drt-generate-project-context/steps/step-01-discover.md +186 -0
- package/src/drt-skills/3-solutioning/drt-generate-project-context/steps/step-02-generate.md +321 -0
- package/src/drt-skills/3-solutioning/drt-generate-project-context/steps/step-03-complete.md +284 -0
- package/src/drt-skills/4-implementation/drt-agent-dev/SKILL.md +76 -0
- package/src/drt-skills/4-implementation/drt-agent-dev/customize.toml +95 -0
- package/src/drt-skills/4-implementation/drt-checkpoint-preview/SKILL.md +68 -0
- package/src/drt-skills/4-implementation/drt-checkpoint-preview/customize.toml +41 -0
- package/src/drt-skills/4-implementation/drt-checkpoint-preview/generate-trail.md +38 -0
- package/src/drt-skills/4-implementation/drt-checkpoint-preview/step-01-orientation.md +105 -0
- package/src/drt-skills/4-implementation/drt-checkpoint-preview/step-02-walkthrough.md +89 -0
- package/src/drt-skills/4-implementation/drt-checkpoint-preview/step-03-detail-pass.md +106 -0
- package/src/drt-skills/4-implementation/drt-checkpoint-preview/step-04-testing.md +74 -0
- package/src/drt-skills/4-implementation/drt-checkpoint-preview/step-05-wrapup.md +30 -0
- package/src/drt-skills/4-implementation/drt-code-review/SKILL.md +90 -0
- package/src/drt-skills/4-implementation/drt-code-review/customize.toml +93 -0
- package/src/drt-skills/4-implementation/drt-code-review/steps/step-01-gather-context.md +84 -0
- package/src/drt-skills/4-implementation/drt-code-review/steps/step-02-review.md +32 -0
- package/src/drt-skills/4-implementation/drt-code-review/steps/step-03-triage.md +50 -0
- package/src/drt-skills/4-implementation/drt-code-review/steps/step-04-present.md +132 -0
- package/src/drt-skills/4-implementation/drt-correct-course/SKILL.md +301 -0
- package/src/drt-skills/4-implementation/drt-correct-course/checklist.md +288 -0
- package/src/drt-skills/4-implementation/drt-correct-course/customize.toml +41 -0
- package/src/drt-skills/4-implementation/drt-create-story/SKILL.md +432 -0
- package/src/drt-skills/4-implementation/drt-create-story/checklist.md +357 -0
- package/src/drt-skills/4-implementation/drt-create-story/customize.toml +41 -0
- package/src/drt-skills/4-implementation/drt-create-story/discover-inputs.md +88 -0
- package/src/drt-skills/4-implementation/drt-create-story/template.md +49 -0
- package/src/drt-skills/4-implementation/drt-dev-auto/SKILL.md +123 -0
- package/src/drt-skills/4-implementation/drt-dev-auto/compile-epic-context.md +62 -0
- package/src/drt-skills/4-implementation/drt-dev-auto/customize.toml +108 -0
- package/src/drt-skills/4-implementation/drt-dev-auto/spec-template.md +98 -0
- package/src/drt-skills/4-implementation/drt-dev-auto/step-01-clarify-and-route.md +84 -0
- package/src/drt-skills/4-implementation/drt-dev-auto/step-02-plan.md +31 -0
- package/src/drt-skills/4-implementation/drt-dev-auto/step-03-implement.md +42 -0
- package/src/drt-skills/4-implementation/drt-dev-auto/step-04-review.md +95 -0
- package/src/drt-skills/4-implementation/drt-dev-story/SKILL.md +500 -0
- package/src/drt-skills/4-implementation/drt-dev-story/checklist.md +80 -0
- package/src/drt-skills/4-implementation/drt-dev-story/customize.toml +41 -0
- package/src/drt-skills/4-implementation/drt-implement-task/SKILL.md +101 -0
- package/src/drt-skills/4-implementation/drt-implement-task/assets/task-spec-template.md +60 -0
- package/src/drt-skills/4-implementation/drt-implement-task/customize.toml +17 -0
- package/src/drt-skills/4-implementation/drt-implement-task/steps/step-01-gather-intent.md +42 -0
- package/src/drt-skills/4-implementation/drt-implement-task/steps/step-02-plan-and-approve.md +43 -0
- package/src/drt-skills/4-implementation/drt-implement-task/steps/step-03-confirm-dependencies.md +38 -0
- package/src/drt-skills/4-implementation/drt-implement-task/steps/step-04-implement.md +42 -0
- package/src/drt-skills/4-implementation/drt-implement-task/steps/step-05-qc-test.md +31 -0
- package/src/drt-skills/4-implementation/drt-implement-task/steps/step-06-quality-review.md +30 -0
- package/src/drt-skills/4-implementation/drt-implement-task/steps/step-07-fix-findings.md +33 -0
- package/src/drt-skills/4-implementation/drt-implement-task/steps/step-08-complete.md +35 -0
- package/src/drt-skills/4-implementation/drt-qa-generate-e2e-tests/SKILL.md +176 -0
- package/src/drt-skills/4-implementation/drt-qa-generate-e2e-tests/checklist.md +33 -0
- package/src/drt-skills/4-implementation/drt-qa-generate-e2e-tests/customize.toml +41 -0
- package/src/drt-skills/4-implementation/drt-quick-dev/SKILL.md +13 -0
- package/src/drt-skills/4-implementation/drt-quick-dev/compile-epic-context.md +62 -0
- package/src/drt-skills/4-implementation/drt-quick-dev/customize.toml +83 -0
- package/src/drt-skills/4-implementation/drt-quick-dev/render.js +206 -0
- package/src/drt-skills/4-implementation/drt-quick-dev/spec-template.md +89 -0
- package/src/drt-skills/4-implementation/drt-quick-dev/step-01-clarify-and-route.md +103 -0
- package/src/drt-skills/4-implementation/drt-quick-dev/step-02-plan.md +47 -0
- package/src/drt-skills/4-implementation/drt-quick-dev/step-03-implement.md +45 -0
- package/src/drt-skills/4-implementation/drt-quick-dev/step-04-review.md +55 -0
- package/src/drt-skills/4-implementation/drt-quick-dev/step-05-present.md +78 -0
- package/src/drt-skills/4-implementation/drt-quick-dev/step-oneshot.md +78 -0
- package/src/drt-skills/4-implementation/drt-quick-dev/sync-sprint-status.md +19 -0
- package/src/drt-skills/4-implementation/drt-quick-dev/workflow.md +85 -0
- package/src/drt-skills/4-implementation/drt-retrospective/SKILL.md +1527 -0
- package/src/drt-skills/4-implementation/drt-retrospective/customize.toml +41 -0
- package/src/drt-skills/4-implementation/drt-sprint-planning/SKILL.md +319 -0
- package/src/drt-skills/4-implementation/drt-sprint-planning/checklist.md +34 -0
- package/src/drt-skills/4-implementation/drt-sprint-planning/customize.toml +41 -0
- package/src/drt-skills/4-implementation/drt-sprint-planning/sprint-status-template.yaml +69 -0
- package/src/drt-skills/4-implementation/drt-sprint-status/SKILL.md +311 -0
- package/src/drt-skills/4-implementation/drt-sprint-status/customize.toml +41 -0
- package/src/drt-skills/module-help.csv +32 -0
- package/src/drt-skills/module.yaml +95 -0
- package/src/scripts/lib/load-toml.js +43 -0
- package/src/scripts/lib/merge-utils.js +89 -0
- package/src/scripts/memlog.js +184 -0
- package/src/scripts/package.json +7 -0
- package/src/scripts/resolve-config.js +56 -0
- package/src/scripts/resolve-customization.js +77 -0
- package/tools/installer/cli-utils.js +53 -0
- package/tools/installer/commands/install.js +149 -0
- package/tools/installer/commands/status.js +65 -0
- package/tools/installer/commands/uninstall.js +167 -0
- package/tools/installer/core/config.js +73 -0
- package/tools/installer/core/existing-install.js +121 -0
- package/tools/installer/core/install-paths.js +132 -0
- package/tools/installer/core/installer.js +1762 -0
- package/tools/installer/core/legacy-warnings.js +151 -0
- package/tools/installer/core/manifest-generator.js +859 -0
- package/tools/installer/core/manifest.js +433 -0
- package/tools/installer/core/uv-check.js +97 -0
- package/tools/installer/core/wsl-node-check.js +109 -0
- package/tools/installer/drt-cli.js +104 -0
- package/tools/installer/file-ops.js +204 -0
- package/tools/installer/fs-native.js +116 -0
- package/tools/installer/ide/_config-driven.js +972 -0
- package/tools/installer/ide/manager.js +324 -0
- package/tools/installer/ide/platform-codes.js +80 -0
- package/tools/installer/ide/platform-codes.yaml +343 -0
- package/tools/installer/ide/shared/installed-skills.js +50 -0
- package/tools/installer/ide/shared/path-utils.js +217 -0
- package/tools/installer/ide/shared/skill-manifest.js +57 -0
- package/tools/installer/install-messages.yaml +29 -0
- package/tools/installer/list-options.js +210 -0
- package/tools/installer/message-loader.js +83 -0
- package/tools/installer/modules/channel-plan.js +203 -0
- package/tools/installer/modules/channel-resolver.js +241 -0
- package/tools/installer/modules/custom-module-manager.js +918 -0
- package/tools/installer/modules/external-manager.js +667 -0
- package/tools/installer/modules/module-help-schema.js +13 -0
- package/tools/installer/modules/official-modules.js +2257 -0
- package/tools/installer/modules/plugin-resolver.js +398 -0
- package/tools/installer/modules/version-resolver.js +336 -0
- package/tools/installer/project-root.js +224 -0
- package/tools/installer/prompts.js +852 -0
- package/tools/installer/set-overrides.js +330 -0
- package/tools/installer/ui.js +2090 -0
- package/tools/installer/yaml-format.js +245 -0
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
const path = require('node:path');
|
|
2
|
+
const https = require('node:https');
|
|
3
|
+
const { execFile } = require('node:child_process');
|
|
4
|
+
const { promisify } = require('node:util');
|
|
5
|
+
const fs = require('../fs-native');
|
|
6
|
+
const crypto = require('node:crypto');
|
|
7
|
+
const { resolveModuleVersion } = require('../modules/version-resolver');
|
|
8
|
+
const prompts = require('../prompts');
|
|
9
|
+
|
|
10
|
+
const execFileAsync = promisify(execFile);
|
|
11
|
+
const NPM_LOOKUP_TIMEOUT_MS = 10_000;
|
|
12
|
+
const NPM_PACKAGE_NAME_PATTERN = /^(?:@[a-z0-9][a-z0-9._~-]*\/)?[a-z0-9][a-z0-9._~-]*$/;
|
|
13
|
+
|
|
14
|
+
function isValidNpmPackageName(packageName) {
|
|
15
|
+
return typeof packageName === 'string' && NPM_PACKAGE_NAME_PATTERN.test(packageName);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
class Manifest {
|
|
19
|
+
/**
|
|
20
|
+
* Create a new manifest
|
|
21
|
+
* @param {string} drtDir - Path to drt directory
|
|
22
|
+
* @param {Object} data - Manifest data
|
|
23
|
+
* @param {Array} installedFiles - List of installed files (no longer used, files tracked in files-manifest.csv)
|
|
24
|
+
*/
|
|
25
|
+
async create(drtDir, data, installedFiles = []) {
|
|
26
|
+
const manifestPath = path.join(drtDir, '_config', 'manifest.yaml');
|
|
27
|
+
const yaml = require('yaml');
|
|
28
|
+
|
|
29
|
+
// Ensure _config directory exists
|
|
30
|
+
await fs.ensureDir(path.dirname(manifestPath));
|
|
31
|
+
|
|
32
|
+
// Get the DRT version from package.json
|
|
33
|
+
const drtVersion = data.version || require(path.join(process.cwd(), 'package.json')).version;
|
|
34
|
+
|
|
35
|
+
// Convert module list to new detailed format
|
|
36
|
+
const moduleDetails = [];
|
|
37
|
+
if (data.modules && Array.isArray(data.modules)) {
|
|
38
|
+
for (const moduleName of data.modules) {
|
|
39
|
+
// Core and BMM modules use the DRT version
|
|
40
|
+
const moduleVersion = moduleName === 'core' || moduleName === 'drt' ? drtVersion : null;
|
|
41
|
+
const now = data.installDate || new Date().toISOString();
|
|
42
|
+
|
|
43
|
+
moduleDetails.push({
|
|
44
|
+
name: moduleName,
|
|
45
|
+
version: moduleVersion,
|
|
46
|
+
installDate: now,
|
|
47
|
+
lastUpdated: now,
|
|
48
|
+
source: moduleName === 'core' || moduleName === 'drt' ? 'built-in' : 'unknown',
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Structure the manifest data
|
|
54
|
+
const manifestData = {
|
|
55
|
+
installation: {
|
|
56
|
+
version: drtVersion,
|
|
57
|
+
installDate: data.installDate || new Date().toISOString(),
|
|
58
|
+
lastUpdated: data.lastUpdated || new Date().toISOString(),
|
|
59
|
+
},
|
|
60
|
+
modules: moduleDetails,
|
|
61
|
+
ides: data.ides || [],
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// Write YAML manifest
|
|
65
|
+
// Clean the manifest data to remove any non-serializable values
|
|
66
|
+
const cleanManifestData = structuredClone(manifestData);
|
|
67
|
+
|
|
68
|
+
const yamlContent = yaml.stringify(cleanManifestData, {
|
|
69
|
+
indent: 2,
|
|
70
|
+
lineWidth: 0,
|
|
71
|
+
sortKeys: false,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Ensure POSIX-compliant final newline
|
|
75
|
+
const content = yamlContent.endsWith('\n') ? yamlContent : yamlContent + '\n';
|
|
76
|
+
await fs.writeFile(manifestPath, content, 'utf8');
|
|
77
|
+
return { success: true, path: manifestPath, filesTracked: 0 };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Read existing manifest
|
|
82
|
+
* @param {string} drtDir - Path to drt directory
|
|
83
|
+
* @returns {Object|null} Manifest data or null if not found
|
|
84
|
+
*/
|
|
85
|
+
async read(drtDir) {
|
|
86
|
+
const yamlPath = path.join(drtDir, '_config', 'manifest.yaml');
|
|
87
|
+
const yaml = require('yaml');
|
|
88
|
+
|
|
89
|
+
if (await fs.pathExists(yamlPath)) {
|
|
90
|
+
try {
|
|
91
|
+
const content = await fs.readFile(yamlPath, 'utf8');
|
|
92
|
+
const manifestData = yaml.parse(content);
|
|
93
|
+
|
|
94
|
+
// Handle new detailed module format
|
|
95
|
+
const modules = manifestData.modules || [];
|
|
96
|
+
|
|
97
|
+
// For backward compatibility: if modules is an array of strings (old format),
|
|
98
|
+
// the calling code may need the array of names
|
|
99
|
+
const moduleNames = modules.map((m) => (typeof m === 'string' ? m : m.name));
|
|
100
|
+
|
|
101
|
+
// Check if we have the new detailed format
|
|
102
|
+
const hasDetailedModules = modules.length > 0 && typeof modules[0] === 'object';
|
|
103
|
+
|
|
104
|
+
// Flatten the structure for compatibility with existing code
|
|
105
|
+
return {
|
|
106
|
+
version: manifestData.installation?.version,
|
|
107
|
+
installDate: manifestData.installation?.installDate,
|
|
108
|
+
lastUpdated: manifestData.installation?.lastUpdated,
|
|
109
|
+
modules: moduleNames, // Simple array of module names for backward compatibility
|
|
110
|
+
modulesDetailed: hasDetailedModules ? modules : null, // New detailed format
|
|
111
|
+
ides: manifestData.ides || [],
|
|
112
|
+
};
|
|
113
|
+
} catch (error) {
|
|
114
|
+
await prompts.log.error(`Failed to read YAML manifest: ${error.message}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Read raw manifest data without flattening
|
|
123
|
+
* @param {string} drtDir - Path to drt directory
|
|
124
|
+
* @returns {Object|null} Raw manifest data or null if not found
|
|
125
|
+
*/
|
|
126
|
+
async _readRaw(drtDir) {
|
|
127
|
+
const yamlPath = path.join(drtDir, '_config', 'manifest.yaml');
|
|
128
|
+
const yaml = require('yaml');
|
|
129
|
+
|
|
130
|
+
if (await fs.pathExists(yamlPath)) {
|
|
131
|
+
try {
|
|
132
|
+
const content = await fs.readFile(yamlPath, 'utf8');
|
|
133
|
+
return yaml.parse(content);
|
|
134
|
+
} catch (error) {
|
|
135
|
+
await prompts.log.error(`Failed to read YAML manifest: ${error.message}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Flatten manifest for backward compatibility
|
|
144
|
+
* @param {Object} manifest - Raw manifest data
|
|
145
|
+
* @returns {Object} Flattened manifest
|
|
146
|
+
*/
|
|
147
|
+
_flattenManifest(manifest) {
|
|
148
|
+
const modules = manifest.modules || [];
|
|
149
|
+
const moduleNames = modules.map((m) => (typeof m === 'string' ? m : m.name));
|
|
150
|
+
const hasDetailedModules = modules.length > 0 && typeof modules[0] === 'object';
|
|
151
|
+
|
|
152
|
+
return {
|
|
153
|
+
version: manifest.installation?.version,
|
|
154
|
+
installDate: manifest.installation?.installDate,
|
|
155
|
+
lastUpdated: manifest.installation?.lastUpdated,
|
|
156
|
+
modules: moduleNames,
|
|
157
|
+
modulesDetailed: hasDetailedModules ? modules : null,
|
|
158
|
+
ides: manifest.ides || [],
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Add a module to the manifest with optional version info
|
|
164
|
+
* If module already exists, update its version info
|
|
165
|
+
* @param {string} drtDir - Path to drt directory
|
|
166
|
+
* @param {string} moduleName - Module name to add
|
|
167
|
+
* @param {Object} options - Optional version info
|
|
168
|
+
*/
|
|
169
|
+
async addModule(drtDir, moduleName, options = {}) {
|
|
170
|
+
let manifest = await this._readRaw(drtDir);
|
|
171
|
+
if (!manifest) {
|
|
172
|
+
// Bootstrap a minimal manifest if it doesn't exist yet
|
|
173
|
+
// (e.g., skill-only modules with no agents to compile)
|
|
174
|
+
manifest = { modules: [] };
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (!manifest.modules) {
|
|
178
|
+
manifest.modules = [];
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const existingIndex = manifest.modules.findIndex((m) => m.name === moduleName);
|
|
182
|
+
|
|
183
|
+
if (existingIndex === -1) {
|
|
184
|
+
// Module doesn't exist, add it
|
|
185
|
+
const entry = {
|
|
186
|
+
name: moduleName,
|
|
187
|
+
version: options.version || null,
|
|
188
|
+
installDate: new Date().toISOString(),
|
|
189
|
+
lastUpdated: new Date().toISOString(),
|
|
190
|
+
source: options.source || 'unknown',
|
|
191
|
+
npmPackage: options.npmPackage || null,
|
|
192
|
+
repoUrl: options.repoUrl || null,
|
|
193
|
+
};
|
|
194
|
+
if (options.channel) entry.channel = options.channel;
|
|
195
|
+
if (options.sha) entry.sha = options.sha;
|
|
196
|
+
if (options.localPath) entry.localPath = options.localPath;
|
|
197
|
+
if (options.rawSource) entry.rawSource = options.rawSource;
|
|
198
|
+
if (options.registryApprovedTag) entry.registryApprovedTag = options.registryApprovedTag;
|
|
199
|
+
if (options.registryApprovedSha) entry.registryApprovedSha = options.registryApprovedSha;
|
|
200
|
+
manifest.modules.push(entry);
|
|
201
|
+
} else {
|
|
202
|
+
// Module exists, update its version info
|
|
203
|
+
const existing = manifest.modules[existingIndex];
|
|
204
|
+
manifest.modules[existingIndex] = {
|
|
205
|
+
...existing,
|
|
206
|
+
version: options.version === undefined ? existing.version : options.version,
|
|
207
|
+
source: options.source || existing.source,
|
|
208
|
+
npmPackage: options.npmPackage === undefined ? existing.npmPackage : options.npmPackage,
|
|
209
|
+
repoUrl: options.repoUrl === undefined ? existing.repoUrl : options.repoUrl,
|
|
210
|
+
localPath: options.localPath === undefined ? existing.localPath : options.localPath,
|
|
211
|
+
channel: options.channel === undefined ? existing.channel : options.channel,
|
|
212
|
+
sha: options.sha === undefined ? existing.sha : options.sha,
|
|
213
|
+
rawSource: options.rawSource === undefined ? existing.rawSource : options.rawSource,
|
|
214
|
+
registryApprovedTag: options.registryApprovedTag === undefined ? existing.registryApprovedTag : options.registryApprovedTag,
|
|
215
|
+
registryApprovedSha: options.registryApprovedSha === undefined ? existing.registryApprovedSha : options.registryApprovedSha,
|
|
216
|
+
lastUpdated: new Date().toISOString(),
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
await this._writeRaw(drtDir, manifest);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Get all modules with their version info
|
|
225
|
+
* @param {string} drtDir - Path to drt directory
|
|
226
|
+
* @returns {Array} Array of module info objects
|
|
227
|
+
*/
|
|
228
|
+
async getAllModuleVersions(drtDir) {
|
|
229
|
+
const manifest = await this._readRaw(drtDir);
|
|
230
|
+
if (!manifest || !manifest.modules) {
|
|
231
|
+
return [];
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return manifest.modules;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Write raw manifest data to file
|
|
239
|
+
* @param {string} drtDir - Path to drt directory
|
|
240
|
+
* @param {Object} manifestData - Raw manifest data to write
|
|
241
|
+
*/
|
|
242
|
+
async _writeRaw(drtDir, manifestData) {
|
|
243
|
+
const yaml = require('yaml');
|
|
244
|
+
const manifestPath = path.join(drtDir, '_config', 'manifest.yaml');
|
|
245
|
+
|
|
246
|
+
await fs.ensureDir(path.dirname(manifestPath));
|
|
247
|
+
|
|
248
|
+
const cleanManifestData = structuredClone(manifestData);
|
|
249
|
+
|
|
250
|
+
const yamlContent = yaml.stringify(cleanManifestData, {
|
|
251
|
+
indent: 2,
|
|
252
|
+
lineWidth: 0,
|
|
253
|
+
sortKeys: false,
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
const content = yamlContent.endsWith('\n') ? yamlContent : yamlContent + '\n';
|
|
257
|
+
await fs.writeFile(manifestPath, content, 'utf8');
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Calculate SHA256 hash of a file
|
|
262
|
+
* @param {string} filePath - Path to file
|
|
263
|
+
* @returns {string} SHA256 hash
|
|
264
|
+
*/
|
|
265
|
+
async calculateFileHash(filePath) {
|
|
266
|
+
try {
|
|
267
|
+
const content = await fs.readFile(filePath);
|
|
268
|
+
return crypto.createHash('sha256').update(content).digest('hex');
|
|
269
|
+
} catch {
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Get module version info from source
|
|
276
|
+
* @param {string} moduleName - Module name/code
|
|
277
|
+
* @param {string} drtDir - Path to drt directory
|
|
278
|
+
* @param {string} moduleSourcePath - Optional source path for custom modules
|
|
279
|
+
* @returns {Object} Version info object with version, source, npmPackage, repoUrl
|
|
280
|
+
*/
|
|
281
|
+
async getModuleVersionInfo(moduleName, drtDir, moduleSourcePath = null) {
|
|
282
|
+
// Resolve source type first, then read version with the correct path context
|
|
283
|
+
if (['core', 'drt'].includes(moduleName)) {
|
|
284
|
+
const versionInfo = await resolveModuleVersion(moduleName, { moduleSourcePath });
|
|
285
|
+
return {
|
|
286
|
+
version: versionInfo.version,
|
|
287
|
+
source: 'built-in',
|
|
288
|
+
npmPackage: null,
|
|
289
|
+
repoUrl: null,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Check if this is an external official module
|
|
294
|
+
const { ExternalModuleManager } = require('../modules/external-manager');
|
|
295
|
+
const extMgr = new ExternalModuleManager();
|
|
296
|
+
const moduleInfo = await extMgr.getModuleByCode(moduleName);
|
|
297
|
+
|
|
298
|
+
if (moduleInfo) {
|
|
299
|
+
const externalResolution = extMgr.getResolution(moduleName);
|
|
300
|
+
const versionInfo = await resolveModuleVersion(moduleName, { moduleSourcePath });
|
|
301
|
+
return {
|
|
302
|
+
// Git tag recorded during install trumps the on-disk package.json
|
|
303
|
+
// version, so the manifest carries "v1.7.0" instead of "1.7.0".
|
|
304
|
+
version: externalResolution?.version || versionInfo.version,
|
|
305
|
+
source: 'external',
|
|
306
|
+
npmPackage: moduleInfo.npmPackage || null,
|
|
307
|
+
repoUrl: moduleInfo.url || null,
|
|
308
|
+
channel: externalResolution?.channel || null,
|
|
309
|
+
sha: externalResolution?.sha || null,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Check if this is a custom module (from user-provided URL or local path)
|
|
314
|
+
const { CustomModuleManager } = require('../modules/custom-module-manager');
|
|
315
|
+
const customMgr = new CustomModuleManager();
|
|
316
|
+
const resolved = customMgr.getResolution(moduleName);
|
|
317
|
+
const customSource = await customMgr.findModuleSourceByCode(moduleName, { drtDir });
|
|
318
|
+
if (customSource || resolved) {
|
|
319
|
+
const versionInfo = await resolveModuleVersion(moduleName, {
|
|
320
|
+
moduleSourcePath: moduleSourcePath || customSource,
|
|
321
|
+
fallbackVersion: resolved?.version,
|
|
322
|
+
marketplacePluginNames: resolved?.pluginName ? [resolved.pluginName] : [],
|
|
323
|
+
});
|
|
324
|
+
const hasGitClone = !!resolved?.repoUrl;
|
|
325
|
+
return {
|
|
326
|
+
// Prefer the git ref we actually cloned over the package.json version.
|
|
327
|
+
version: resolved?.cloneRef || (hasGitClone ? 'main' : versionInfo.version),
|
|
328
|
+
source: 'custom',
|
|
329
|
+
npmPackage: null,
|
|
330
|
+
repoUrl: resolved?.repoUrl || null,
|
|
331
|
+
localPath: resolved?.localPath || null,
|
|
332
|
+
channel: hasGitClone ? (resolved?.cloneRef ? 'pinned' : 'next') : null,
|
|
333
|
+
sha: resolved?.cloneSha || null,
|
|
334
|
+
rawSource: resolved?.rawInput || null,
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Unknown module
|
|
339
|
+
const versionInfo = await resolveModuleVersion(moduleName, { moduleSourcePath });
|
|
340
|
+
return {
|
|
341
|
+
version: versionInfo.version,
|
|
342
|
+
source: 'unknown',
|
|
343
|
+
npmPackage: null,
|
|
344
|
+
repoUrl: null,
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Fetch latest version from npm for a package
|
|
350
|
+
* @param {string} packageName - npm package name
|
|
351
|
+
* @returns {string|null} Latest version or null
|
|
352
|
+
*/
|
|
353
|
+
async fetchNpmVersion(packageName) {
|
|
354
|
+
if (!isValidNpmPackageName(packageName)) {
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
try {
|
|
359
|
+
// Try using npm view first (more reliable)
|
|
360
|
+
try {
|
|
361
|
+
const { stdout } = await execFileAsync('npm', ['view', packageName, 'version'], {
|
|
362
|
+
encoding: 'utf8',
|
|
363
|
+
timeout: NPM_LOOKUP_TIMEOUT_MS,
|
|
364
|
+
});
|
|
365
|
+
return stdout.trim();
|
|
366
|
+
} catch {
|
|
367
|
+
// Fallback to npm registry API
|
|
368
|
+
return new Promise((resolve) => {
|
|
369
|
+
const request = https.get(`https://registry.npmjs.org/${encodeURIComponent(packageName)}`, (res) => {
|
|
370
|
+
let data = '';
|
|
371
|
+
res.on('data', (chunk) => (data += chunk));
|
|
372
|
+
res.on('end', () => {
|
|
373
|
+
try {
|
|
374
|
+
const pkg = JSON.parse(data);
|
|
375
|
+
resolve(pkg['dist-tags']?.latest || pkg.version || null);
|
|
376
|
+
} catch {
|
|
377
|
+
resolve(null);
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
request.setTimeout(NPM_LOOKUP_TIMEOUT_MS, () => {
|
|
383
|
+
request.destroy();
|
|
384
|
+
resolve(null);
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
request.on('error', () => resolve(null));
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
} catch {
|
|
391
|
+
return null;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Check for available updates for installed modules
|
|
397
|
+
* @param {string} drtDir - Path to drt directory
|
|
398
|
+
* @returns {Array} Array of update info objects
|
|
399
|
+
*/
|
|
400
|
+
async checkForUpdates(drtDir) {
|
|
401
|
+
const semver = require('semver');
|
|
402
|
+
const modules = await this.getAllModuleVersions(drtDir);
|
|
403
|
+
const updates = [];
|
|
404
|
+
|
|
405
|
+
for (const module of modules) {
|
|
406
|
+
if (!module.npmPackage) {
|
|
407
|
+
continue; // Skip modules without npm package (built-in)
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const latestVersion = await this.fetchNpmVersion(module.npmPackage);
|
|
411
|
+
if (!latestVersion) {
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
const installedVersion = semver.valid(module.version) || semver.valid(semver.coerce(module.version || ''));
|
|
416
|
+
const availableVersion = semver.valid(latestVersion) || semver.valid(semver.coerce(latestVersion));
|
|
417
|
+
|
|
418
|
+
if (installedVersion && availableVersion && semver.gt(availableVersion, installedVersion)) {
|
|
419
|
+
updates.push({
|
|
420
|
+
name: module.name,
|
|
421
|
+
installedVersion: module.version,
|
|
422
|
+
latestVersion: latestVersion,
|
|
423
|
+
npmPackage: module.npmPackage,
|
|
424
|
+
updateAvailable: true,
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
return updates;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
module.exports = { Manifest };
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
const { spawnSync } = require('node:child_process');
|
|
2
|
+
const prompts = require('../prompts');
|
|
3
|
+
|
|
4
|
+
// `uv` (https://docs.astral.sh/uv/) is becoming the de facto standard for
|
|
5
|
+
// running the Python scripts DRT workflows shell out to: `uv run <script>`
|
|
6
|
+
// resolves the interpreter and any dependencies on demand, so skills don't
|
|
7
|
+
// have to assume a particular `python3` is on PATH. The ecosystem is mid-
|
|
8
|
+
// migration — some skills still call `python3` directly — so a missing `uv`
|
|
9
|
+
// is a warning, not a blocker: DRT installs and runs either way.
|
|
10
|
+
const RUNTIME_COMMAND = 'uv';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Parse `uv --version` output into version parts.
|
|
14
|
+
* Example outputs: "uv 0.5.31", "uv 0.5.31 (Homebrew 2025-02-12)".
|
|
15
|
+
* @param {string} output - stdout/stderr from `uv --version`
|
|
16
|
+
* @returns {{major: number, minor: number, patch: number, raw: string}|null}
|
|
17
|
+
*/
|
|
18
|
+
function parseUvVersion(output) {
|
|
19
|
+
if (!output) return null;
|
|
20
|
+
const match = output.match(/uv\s+(\d+)\.(\d+)(?:\.(\d+))?/i);
|
|
21
|
+
if (!match) return null;
|
|
22
|
+
return {
|
|
23
|
+
major: Number(match[1]),
|
|
24
|
+
minor: Number(match[2]),
|
|
25
|
+
patch: Number(match[3] || 0),
|
|
26
|
+
raw: `${match[1]}.${match[2]}.${match[3] || 0}`,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Probe the local environment for `uv`.
|
|
32
|
+
* @returns {{version: {major: number, minor: number, patch: number, raw: string}}|null}
|
|
33
|
+
*/
|
|
34
|
+
function detectUv() {
|
|
35
|
+
let result;
|
|
36
|
+
try {
|
|
37
|
+
result = spawnSync(RUNTIME_COMMAND, ['--version'], {
|
|
38
|
+
encoding: 'utf8',
|
|
39
|
+
timeout: 5000,
|
|
40
|
+
windowsHide: true,
|
|
41
|
+
});
|
|
42
|
+
} catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
if (!result || result.error) return null;
|
|
46
|
+
const version = parseUvVersion(`${result.stdout || ''}\n${result.stderr || ''}`);
|
|
47
|
+
return version ? { version } : null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function setupHints() {
|
|
51
|
+
return [
|
|
52
|
+
'DRT workflows increasingly run Python scripts via `uv run`, which manages',
|
|
53
|
+
'the interpreter and dependencies for you — no manual venv or pip needed.',
|
|
54
|
+
'',
|
|
55
|
+
'Easiest path: ask your AI agent to "install and set up uv for me".',
|
|
56
|
+
'',
|
|
57
|
+
'Or install it yourself:',
|
|
58
|
+
' macOS/Linux: curl -LsSf https://astral.sh/uv/install.sh | sh',
|
|
59
|
+
' Windows: powershell -c "irm https://astral.sh/uv/install.ps1 | iex"',
|
|
60
|
+
' Homebrew: brew install uv',
|
|
61
|
+
' Docs: https://docs.astral.sh/uv/getting-started/installation/',
|
|
62
|
+
].join('\n');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Check whether `uv` is available and inform the user.
|
|
67
|
+
*
|
|
68
|
+
* Warn-don't-block, and no acknowledgement prompt: `uv` is on its way to being
|
|
69
|
+
* the standard runner for DRT's Python scripts, but the migration is still in
|
|
70
|
+
* progress, so the install never stops on its account. The note tells the user
|
|
71
|
+
* how to set it up (preferably by asking their agent).
|
|
72
|
+
*
|
|
73
|
+
* @returns {Promise<{status: 'found'|'missing', detected: Object|null}>}
|
|
74
|
+
*/
|
|
75
|
+
async function checkUvEnvironment() {
|
|
76
|
+
// Called via module.exports so tests can stub detection.
|
|
77
|
+
const detected = module.exports.detectUv();
|
|
78
|
+
|
|
79
|
+
if (detected) {
|
|
80
|
+
await prompts.log.success(`✅ Python UV check pass (uv ${detected.version.raw} detected).`);
|
|
81
|
+
return { status: 'found', detected };
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
await prompts.log.warn(
|
|
85
|
+
"uv not found on PATH. uv is becoming the de facto standard for running DRT's Python\n" +
|
|
86
|
+
'scripts (`uv run <script>`), and it provisions the interpreter for you. DRT installs\n' +
|
|
87
|
+
'fine without it, but setting up uv now keeps you ahead as workflows adopt it.',
|
|
88
|
+
);
|
|
89
|
+
await prompts.note(setupHints(), 'uv recommended');
|
|
90
|
+
return { status: 'missing', detected: null };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
module.exports = {
|
|
94
|
+
checkUvEnvironment,
|
|
95
|
+
detectUv,
|
|
96
|
+
parseUvVersion,
|
|
97
|
+
};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
const prompts = require('../prompts');
|
|
2
|
+
|
|
3
|
+
const WSL_UNC_PATTERN = /^\\\\wsl(?:\.localhost|\$)?\\/i;
|
|
4
|
+
|
|
5
|
+
function normalizePath(value) {
|
|
6
|
+
return typeof value === 'string' ? value.replaceAll('/', '\\').toLowerCase() : '';
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function isLinuxStylePath(value) {
|
|
10
|
+
return (
|
|
11
|
+
typeof value === 'string' &&
|
|
12
|
+
value.startsWith('/') &&
|
|
13
|
+
!value.startsWith('//') &&
|
|
14
|
+
!/^\/[a-z](?:\/|$)/i.test(value) &&
|
|
15
|
+
!/^\/cygdrive\/[a-z](?:\/|$)/i.test(value)
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function isWslUncPath(value) {
|
|
20
|
+
return WSL_UNC_PATTERN.test(value || '');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Detect the broken interop case where WSL resolved node/npx to Windows.
|
|
25
|
+
* @param {Object} [runtime]
|
|
26
|
+
* @param {string} [runtime.platform]
|
|
27
|
+
* @param {Object} [runtime.env]
|
|
28
|
+
* @param {string} [runtime.cwd]
|
|
29
|
+
* @param {string} [runtime.execPath]
|
|
30
|
+
* @returns {{isMismatch: boolean, reason: string|null, execPath: string}}
|
|
31
|
+
*/
|
|
32
|
+
function detectWindowsNodeFromWsl(runtime = {}) {
|
|
33
|
+
const platform = runtime.platform || process.platform;
|
|
34
|
+
const env = runtime.env || process.env;
|
|
35
|
+
const cwd = runtime.cwd || safeCwd();
|
|
36
|
+
const execPath = runtime.execPath || process.execPath || '';
|
|
37
|
+
|
|
38
|
+
if (platform !== 'win32') {
|
|
39
|
+
return { isMismatch: false, reason: null, execPath };
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (env.WSL_DISTRO_NAME) {
|
|
43
|
+
return { isMismatch: true, reason: 'WSL_DISTRO_NAME is set', execPath };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (env.WSL_INTEROP) {
|
|
47
|
+
return { isMismatch: true, reason: 'WSL_INTEROP is set', execPath };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (isLinuxStylePath(env.PWD)) {
|
|
51
|
+
return { isMismatch: true, reason: 'PWD is a Linux path', execPath };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (isWslUncPath(cwd)) {
|
|
55
|
+
return { isMismatch: true, reason: 'current directory is a WSL UNC path', execPath };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const normalizedExecPath = normalizePath(execPath);
|
|
59
|
+
if (normalizedExecPath.includes('\\wsl$\\') || normalizedExecPath.includes('\\wsl.localhost\\')) {
|
|
60
|
+
return { isMismatch: true, reason: 'Node executable path is under a WSL UNC path', execPath };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return { isMismatch: false, reason: null, execPath };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function safeCwd() {
|
|
67
|
+
try {
|
|
68
|
+
return process.cwd();
|
|
69
|
+
} catch {
|
|
70
|
+
return '';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function formatWindowsNodeFromWslMessage(detection) {
|
|
75
|
+
const lines = [
|
|
76
|
+
'Windows Node.js was launched from a WSL shell.',
|
|
77
|
+
'',
|
|
78
|
+
'This usually means Node.js is not installed inside the WSL distro, so WSL resolved `node`/`npx` to Windows.',
|
|
79
|
+
'The installer cannot safely continue because Linux paths may be interpreted as Windows paths.',
|
|
80
|
+
'',
|
|
81
|
+
'Install Node.js inside WSL, then rerun the same command from the WSL terminal.',
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
if (detection.execPath) {
|
|
85
|
+
lines.push('', `Detected Node executable: ${detection.execPath}`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (detection.reason) {
|
|
89
|
+
lines.push(`Detection signal: ${detection.reason}`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return lines.join('\n');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function checkWindowsNodeFromWsl() {
|
|
96
|
+
const detection = module.exports.detectWindowsNodeFromWsl();
|
|
97
|
+
if (!detection.isMismatch) {
|
|
98
|
+
return detection;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
await prompts.log.error(formatWindowsNodeFromWslMessage(detection));
|
|
102
|
+
process.exit(1);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
module.exports = {
|
|
106
|
+
checkWindowsNodeFromWsl,
|
|
107
|
+
detectWindowsNodeFromWsl,
|
|
108
|
+
formatWindowsNodeFromWslMessage,
|
|
109
|
+
};
|