diff --git a/.github/prompts/pull-request.prompt.md b/.github/prompts/pull-request.prompt.md index 42a009703..85c9addfe 100644 --- a/.github/prompts/pull-request.prompt.md +++ b/.github/prompts/pull-request.prompt.md @@ -34,11 +34,24 @@ You WILL ALWAYS preserve template structure and formatting. * **If `pr-reference.xml` is NOT provided**: * Use `git fetch {{remote}} {{branch}}` determined from `${input:branch:origin/main}`, to update the remote branch to build a correct pull request. * **MANDATORY**: You MUST create `pr-reference.xml` using the repository scriptsβ€”select the command that matches your host environment. Do not use any other commands to gather git status or diffs. - * **Unix-like shells**: Use `./scripts/dev-tools/pr-ref-gen.sh`. + * **Script Location**: Scripts may be available locally at `./scripts/dev-tools/` OR bundled in a VS Code extension. Check local path first, then fall back to extension: + * **Local path**: `./scripts/dev-tools/pr-ref-gen.sh` or `./scripts/dev-tools/Generate-PrReference.ps1` + * **Extension path** (if local not found): `~/.vscode/extensions/ise-hve-essentials.hve-core-*/scripts/dev-tools/` + * **Locate from extension** (cross-platform): + + ```bash + # Find PowerShell script + pwsh -c '$SCRIPT = Get-ChildItem -Path "$HOME/.vscode/extensions" -Filter "Generate-PrReference.ps1" -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty FullName; Write-Host "Found: $SCRIPT"' + + # Find shell script + find ~/.vscode/extensions -name "pr-ref-gen.sh" 2>/dev/null | head -1 + ``` + + * **Unix-like shells**: Use `./scripts/dev-tools/pr-ref-gen.sh` (or extension path if local not available). * Default: `./scripts/dev-tools/pr-ref-gen.sh`. * If `${input:excludeMarkdown}` is true: `./scripts/dev-tools/pr-ref-gen.sh --no-md-diff` (excludes markdown). * If a different base branch is specified via `${input:branch}`: `./scripts/dev-tools/pr-ref-gen.sh --no-md-diff --base-branch ${input:branch}` (adjust markdown inclusion as needed). - * **Windows PowerShell hosts**: Use `pwsh -File ./scripts/dev-tools/Generate-PrReference.ps1`. + * **Windows PowerShell hosts**: Use `pwsh -File ./scripts/dev-tools/Generate-PrReference.ps1` (or extension path if local not available). * Default: `pwsh -File ./scripts/dev-tools/Generate-PrReference.ps1`. * If `${input:excludeMarkdown}` is true: `pwsh -File ./scripts/dev-tools/Generate-PrReference.ps1 -ExcludeMarkdownDiff` (excludes markdown). * If a different base branch is specified via `${input:branch}`: `pwsh -File ./scripts/dev-tools/Generate-PrReference.ps1 -ExcludeMarkdownDiff -BaseBranch ${input:branch}` (adjust markdown inclusion as needed). diff --git a/.github/workflows/extension-package.yml b/.github/workflows/extension-package.yml new file mode 100644 index 000000000..3b63bbad5 --- /dev/null +++ b/.github/workflows/extension-package.yml @@ -0,0 +1,103 @@ +name: Package Extension + +on: + workflow_call: + inputs: + version: + description: 'Full version to use (e.g., 1.0.0 or empty to use package.json)' + required: false + type: string + default: '' + dev-patch-number: + description: 'Dev patch number to append (creates version like 1.0.0-dev.123)' + required: false + type: string + default: '' + use-changelog: + description: 'Whether to download and use changelog artifact' + required: false + type: boolean + default: false + outputs: + version: + description: 'Version that was packaged' + value: ${{ jobs.package.outputs.version }} + vsix-file: + description: 'Path to the packaged VSIX file' + value: ${{ jobs.package.outputs.vsix-file }} + +permissions: + contents: read + +jobs: + package: + runs-on: ubuntu-latest + outputs: + version: ${{ steps.package.outputs.version }} + vsix-file: ${{ steps.package.outputs.vsix-file }} + steps: + - name: Harden Runner + uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 + with: + egress-policy: audit + + - name: Checkout code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + + - name: Setup Node.js + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: '20' + + - name: Install dependencies + run: npm install -g @vscode/vsce + + - name: Setup PowerShell + shell: pwsh + run: | + Write-Host "PowerShell version: $($PSVersionTable.PSVersion)" + + - name: Download changelog artifact + if: inputs.use-changelog + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 + with: + name: changelog + path: ./ + continue-on-error: true + + - name: Package extension + id: package + shell: pwsh + run: | + $version = "${{ inputs.version }}".Trim() + $devPatch = "${{ inputs.dev-patch-number }}".Trim() + + Write-Host "πŸ“¦ Packaging extension..." + + $arguments = @() + + if ($version) { + $arguments += '-Version' + $arguments += $version + } + + if ($devPatch) { + $arguments += '-DevPatchNumber' + $arguments += $devPatch + } + + if (Test-Path "./CHANGELOG.md") { + $arguments += '-ChangelogPath' + $arguments += "./CHANGELOG.md" + } + + ./scripts/extension/Package-Extension.ps1 @arguments + + - name: Upload VSIX artifact + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: extension-vsix + path: extension/*.vsix + retention-days: 30 diff --git a/.github/workflows/extension-publish.yml b/.github/workflows/extension-publish.yml new file mode 100644 index 000000000..1e0e33756 --- /dev/null +++ b/.github/workflows/extension-publish.yml @@ -0,0 +1,146 @@ +name: Publish Extension + +on: + release: + types: [published] + workflow_dispatch: + inputs: + version: + description: 'Version to publish (leave empty to use package.json version)' + required: false + type: string + default: '' + dry-run: + description: 'Dry run (package only, do not publish)' + required: false + type: boolean + default: false + +permissions: + contents: read + id-token: write + +jobs: + prepare-changelog: + name: Prepare Changelog + runs-on: ubuntu-latest + outputs: + changelog-path: ${{ steps.create-changelog.outputs.path }} + steps: + - name: Harden Runner + uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 + with: + egress-policy: audit + + - name: Checkout code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + + - name: Create changelog file + id: create-changelog + run: | + if [ "${{ github.event_name }}" == "release" ]; then + cat > CHANGELOG.md << 'EOF' + ${{ github.event.release.body }} + EOF + echo "path=CHANGELOG.md" >> $GITHUB_OUTPUT + elif [ "${{ github.event_name }}" == "workflow_dispatch" ]; then + echo "path=" >> $GITHUB_OUTPUT + else + echo "path=" >> $GITHUB_OUTPUT + fi + + - name: Upload changelog + if: steps.create-changelog.outputs.path != '' + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: changelog + path: CHANGELOG.md + retention-days: 1 + + normalize-version: + name: Normalize Version + runs-on: ubuntu-latest + outputs: + version: ${{ steps.normalize.outputs.version }} + steps: + - name: Harden Runner + uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 + with: + egress-policy: audit + + - name: Normalize version string + id: normalize + run: | + if [ "${{ github.event_name }}" == "release" ]; then + VERSION="${{ github.event.release.tag_name }}" + else + VERSION="${{ inputs.version }}" + fi + # Strip leading 'v' if present + VERSION="${VERSION#v}" + echo "version=$VERSION" >> $GITHUB_OUTPUT + + package: + name: Package Extension + needs: [prepare-changelog, normalize-version] + uses: ./.github/workflows/extension-package.yml + with: + version: ${{ needs.normalize-version.outputs.version }} + use-changelog: ${{ needs.prepare-changelog.outputs.changelog-path != '' }} + permissions: + contents: read + + publish: + name: Publish to Marketplace + needs: [prepare-changelog, package] + if: ${{ !inputs.dry-run }} + runs-on: ubuntu-latest + environment: marketplace + steps: + - name: Harden Runner + uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 + with: + egress-policy: audit + + - name: Checkout code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + persist-credentials: false + + - name: Azure Login (OIDC) + uses: azure/login@a65d910e8af852a8061c627c456678983e180302 # v2.2.0 + with: + client-id: ${{ secrets.AZURE_CLIENT_ID }} + tenant-id: ${{ secrets.AZURE_TENANT_ID }} + subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} + + - name: Setup Node.js + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: '20' + + - name: Install VSCE + run: npm install -g @vscode/vsce + + - name: Download VSIX artifact + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 + with: + name: extension-vsix + path: ./extension + + - name: Publish to VS Code Marketplace + run: | + VSIX_FILE=$(ls -t extension/hve-core-*.vsix | head -1) + echo "πŸ“¦ Publishing: $VSIX_FILE" + vsce publish --packagePath "$VSIX_FILE" --azure-credential + + - name: Summary + run: | + echo "## πŸŽ‰ Extension Published Successfully" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Version:** ${{ needs.package.outputs.version }}" >> $GITHUB_STEP_SUMMARY + echo "**VSIX File:** ${{ needs.package.outputs.vsix-file }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "View on [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=ise-hve-essentials.hve-core)" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 89a1c613d..1b1049fa5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -4,6 +4,7 @@ on: push: branches: - main + workflow_dispatch: # Minimal permissions for security @@ -46,6 +47,19 @@ jobs: upload-sarif: true upload-artifact: true + extension-package: + name: Package VS Code Extension + needs: + - spell-check + - markdown-lint + - table-format + - dependency-pinning-scan + uses: ./.github/workflows/extension-package.yml + with: + dev-patch-number: ${{ github.run_number }} + permissions: + contents: read + release-please: name: Release Please needs: @@ -53,6 +67,7 @@ jobs: - markdown-lint - table-format - dependency-pinning-scan + - extension-package runs-on: ubuntu-latest permissions: contents: write diff --git a/.gitignore b/.gitignore index 0b1a5003f..9b5399957 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,9 @@ ## ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore +# macOS +.DS_Store + # User-specific files *.rsuser *.suo @@ -412,6 +415,10 @@ FodyWeavers.xsd # Built Visual Studio Code Extensions *.vsix +# Extension build artifacts +extension/LICENSE +extension/CHANGELOG.md + # Windows Installer files from build outputs *.cab *.msi diff --git a/extension/.vscodeignore b/extension/.vscodeignore new file mode 100644 index 000000000..5b7e96394 --- /dev/null +++ b/extension/.vscodeignore @@ -0,0 +1,13 @@ +# Exclude everything by default +** + +# Include only the extension essentials +!.github/chatmodes/** +!.github/prompts/** +!.github/instructions/** +!.github/agents/** +!scripts/dev-tools/** +!package.json +!README.md +!LICENSE +!CHANGELOG.md diff --git a/extension/LICENSE b/extension/LICENSE new file mode 100644 index 000000000..7bd95a91b --- /dev/null +++ b/extension/LICENSE @@ -0,0 +1,21 @@ +# MIT License + +Copyright (c) Microsoft Corporation. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/extension/PACKAGING.md b/extension/PACKAGING.md new file mode 100644 index 000000000..04ba74abb --- /dev/null +++ b/extension/PACKAGING.md @@ -0,0 +1,211 @@ +--- +title: Extension Packaging Guide +description: Developer guide for packaging and publishing the HVE Core VS Code extension +author: Microsoft +ms.date: 2025-12-19 +ms.topic: reference +--- + +This folder contains the VS Code extension configuration for HVE Core. + +## Structure + +```plaintext +extension/ +β”œβ”€β”€ .github/ # Temporarily copied during packaging (removed after) +β”œβ”€β”€ scripts/dev-tools/ # Temporarily copied during packaging (removed after) +β”œβ”€β”€ package.json # Extension manifest with VS Code configuration +β”œβ”€β”€ .vscodeignore # Controls what gets packaged into the .vsix +β”œβ”€β”€ README.md # Extension marketplace description +β”œβ”€β”€ LICENSE # Copy of root LICENSE +β”œβ”€β”€ CHANGELOG.md # Copy of root CHANGELOG +└── PACKAGING.md # This file +``` + +## Prerequisites + +Install the VS Code Extension Manager CLI: + +```bash +npm install -g @vscode/vsce +``` + +Install the PowerShell-Yaml module (required for Prepare-Extension.ps1): + +```powershell +Install-Module -Name PowerShell-Yaml -Scope CurrentUser +``` + +## Automated CI/CD Workflows + +The extension is automatically packaged and published through GitHub Actions: + +| Workflow | Trigger | Purpose | +|--------------------------------------------|-------------------|---------------------------------------------| +| `.github/workflows/extension-package.yml` | Reusable workflow | Packages extension with flexible versioning | +| `.github/workflows/extension-publish.yml` | Release/manual | Publishes to VS Code Marketplace | +| `.github/workflows/main.yml` | Push to main | Includes extension packaging in CI | + +## Packaging the Extension + +### Using the Automated Scripts (Recommended) + +#### Step 1: Prepare the Extension + +First, update `package.json` with discovered agents, chatmodes, prompts, and instructions: + +```bash +# Discover components and update package.json +pwsh ./scripts/extension/Prepare-Extension.ps1 + +# Or use npm script +npm run extension:prepare +``` + +The preparation script automatically: + +- Discovers and registers all chat agents from `.github/agents/` +- Discovers and registers all chatmodes from `.github/chatmodes/` +- Discovers and registers all prompts from `.github/prompts/` +- Discovers and registers all instruction files from `.github/instructions/` +- Updates `package.json` with discovered components +- Uses existing version from `package.json` (does not modify it) + +#### Step 2: Package the Extension + +Then package the extension: + +```bash +# Package using version from package.json +pwsh ./scripts/extension/Package-Extension.ps1 + +# Or use npm script +npm run extension:package + +# Package with specific version +pwsh ./scripts/extension/Package-Extension.ps1 -Version "1.0.3" + +# Package with dev patch number (e.g., 1.0.2-dev.123) +pwsh ./scripts/extension/Package-Extension.ps1 -DevPatchNumber "123" + +# Package with version and dev patch number +pwsh ./scripts/extension/Package-Extension.ps1 -Version "1.1.0" -DevPatchNumber "456" +``` + +The packaging script automatically: + +- Uses version from `package.json` (or specified version) +- Optionally appends dev patch number for pre-release builds +- Copies required `.github` directory +- Copies `scripts/dev-tools` directory (developer utilities) +- Packages the extension using `vsce` +- Cleans up temporary files +- Restores original `package.json` version if temporarily modified + +### Manual Packaging (Legacy) + +If you need to package manually: + +```bash +cd extension +rm -rf .github scripts && cp -r ../.github . && mkdir -p scripts && cp -r ../scripts/dev-tools scripts/ && vsce package && rm -rf .github scripts +``` + +Or use npm script: + +```bash +npm run package:extension +``` + +## Publishing the Extension + +**Important:** Update version in `extension/package.json` before publishing. + +**Setup Personal Access Token (one-time):** + +Set your Azure DevOps PAT as an environment variable: + +```bash +export VSCE_PAT=your-token-here +``` + +To get a PAT: + +1. Go to +2. User settings β†’ Personal access tokens β†’ New Token +3. Set scope to **Marketplace (Manage)** +4. Copy the token + +**Publish command:** + +```bash +# Publish the packaged extension (replace X.Y.Z with actual version) +vsce publish --packagePath "extension/hve-core-X.Y.Z.vsix" + +# Or use the latest .vsix file +VSIX_FILE=$(ls -t extension/hve-core-*.vsix | head -1) +vsce publish --packagePath "$VSIX_FILE" +``` + +Or use npm script: + +```bash +npm run publish:extension +``` + +## What Gets Included + +The `extension/.vscodeignore` file controls what gets packaged. Currently included: + +- `.github/agents/**` - All chat agent definitions +- `.github/chatmodes/**` - All chatmode definitions +- `.github/prompts/**` - All prompt templates +- `.github/instructions/**` - All instruction files +- `package.json` - Extension manifest +- `README.md` - Extension description +- `LICENSE` - License file +- `CHANGELOG.md` - Version history + +## Testing Locally + +Install the packaged extension locally: + +```bash +code --install-extension hve-core-*.vsix +``` + +## Version Management + +### Update Version in `package.json` + +1. Manually update version in `extension/package.json` +2. Run `scripts/extension/Prepare-Extension.ps1` to update agents/chatmodes/prompts/instructions +3. Run `scripts/extension/Package-Extension.ps1` to create the `.vsix` file + +### Development Builds + +For pre-release or CI builds, use the dev patch number: + +```bash +# Creates version like 1.0.2-dev.123 +pwsh ./scripts/extension/Package-Extension.ps1 -DevPatchNumber "123" +``` + +This temporarily modifies the version during packaging but restores it afterward. + +### Override Version at Package Time + +You can override the version without modifying `package.json`: + +```bash +# Package as 1.1.0 without updating package.json +pwsh ./scripts/extension/Package-Extension.ps1 -Version "1.1.0" +``` + +## Notes + +- The `.github` and `scripts/dev-tools` folders are temporarily copied during packaging (not permanently stored) +- `LICENSE` and `CHANGELOG.md` are copied from root during packaging and excluded from git +- Only essential extension files are included (chatmodes, prompts, instructions, dev-tools) +- Non-essential files are excluded (workflows, issue templates, agent installer, etc.) +- The root `package.json` contains development scripts for the repository diff --git a/extension/README.md b/extension/README.md new file mode 100644 index 000000000..a53c4f52c --- /dev/null +++ b/extension/README.md @@ -0,0 +1,107 @@ +--- +title: HVE Core - AI-Powered Development Assistant +description: AI-powered chat agents, prompts, and instructions for hybrid virtual environments +author: Microsoft +ms.date: 2025-12-19 +ms.topic: overview +--- + +> AI-powered chat agents, prompts, and instructions for hybrid virtual environments + +HVE Core provides a comprehensive collection of specialized AI chat agents, prompts, and instructions designed to accelerate development workflows in VS Code with GitHub Copilot. + +## Features + +### πŸ€– Chat Agents + +Specialized AI assistants for specific development tasks: + +#### Setup & Installation + +- **hve-core-installer** - Decision-driven installer with 6 installation methods for local, devcontainer, and Codespaces environments + +#### Development Workflow + +- **task-researcher** - Research technical solutions and approaches +- **task-planner** - Plan and break down complex tasks +- **task-implementor** - Implement tasks from detailed plans +- **pr-review** - Comprehensive pull request review assistant +- **github-issue-manager** - Manage GitHub issues efficiently + +#### Architecture & Documentation + +- **adr-creation** - Create Architecture Decision Records +- **arch-diagram-builder** - Build high-quality ASCII-art architecture diagrams +- **brd-builder** - Build Business Requirements Documents with guided Q&A +- **prd-builder** - Build Product Requirements Documents with guided Q&A +- **prompt-builder** - Build and optimize AI prompts +- **security-plan-creator** - Expert security architect for creating comprehensive cloud security plans + +#### Azure DevOps Integration + +- **ado-prd-to-wit** - Convert Product Requirements Documents to Azure DevOps work items + +#### Data Science & Visualization + +- **gen-data-spec** - Generate data specifications and schemas +- **gen-jupyter-notebook** - Generate Jupyter notebooks for data analysis +- **gen-streamlit-dashboard** - Generate Streamlit dashboards +- **test-streamlit-dashboard** - Comprehensive testing of Streamlit dashboards + +### πŸ“ Prompts + +Reusable prompt templates for common workflows: + +- **Git Operations** - Commit messages, merges, setup, and pull requests +- **GitHub Workflows** - Issue creation and management +- **Azure DevOps** - PR creation, build info, and work item management + +### πŸ“š Instructions + +Best practice guidelines for: + +- **Languages** - Bash, Python, C#, Bicep +- **Git & Version Control** - Commit messages, merge operations +- **Documentation** - Markdown formatting +- **Azure DevOps** - Work item management and PR workflows +- **Task Management** - Implementation tracking and planning +- **Project Management** - UV projects and dependencies + +## Getting Started + +After installing this extension, the chat agents will be available in GitHub Copilot Chat. You can: + +1. **Use chat agents** by typing `@agent-name` in Copilot Chat +2. **Apply prompts** through the Copilot Chat interface +3. **Reference instructions** - They're automatically applied based on file patterns + +## Usage Examples + +### Using Chat Agents + +```plaintext +@task-planner help me break down this feature into implementable tasks +@pr-review review this pull request for security issues +@adr-creation create an ADR for our new microservice architecture +``` + +### Applying Prompts + +Prompts are available in the Copilot Chat prompt picker and can be used to generate consistent, high-quality outputs for common tasks. + +## Requirements + +- VS Code version 1.106.1 or higher +- GitHub Copilot extension + +## License + +MIT License - see [LICENSE](LICENSE) for details + +## Support + +For issues, questions, or contributions, please visit the [GitHub repository](https://github.com/microsoft/hve-core). + +--- + +Brought to you by Microsoft ISE HVE Essentials diff --git a/extension/package.json b/extension/package.json new file mode 100644 index 000000000..a63601178 --- /dev/null +++ b/extension/package.json @@ -0,0 +1,242 @@ +{ + "name": "hve-core", + "displayName": "HVE Core", + "version": "1.0.0", + "description": "AI-powered chat agents, prompts, and instructions for hybrid virtual environments", + "publisher": "ise-hve-essentials", + "repository": { + "type": "git", + "url": "https://github.com/microsoft/hve-core.git" + }, + "engines": { + "vscode": "^1.106.1" + }, + "categories": [ + "Chat" + ], + "contributes": { + "chatAgents": [ + { + "name": "hve-core-installer", + "path": "./.github/agents/hve-core-installer.agent.md", + "description": "Decision-driven installer for HVE-Core with 6 installation methods for local, devcontainer, and Codespaces environments - Brought to you by microsoft/hve-core" + }, + { + "name": "ado-prd-to-wit", + "path": "./.github/chatmodes/ado-prd-to-wit.chatmode.md", + "description": "Product Manager expert for analyzing PRDs and planning Azure DevOps work item hierarchies" + }, + { + "name": "adr-creation", + "path": "./.github/chatmodes/adr-creation.chatmode.md", + "description": "Interactive AI coaching for collaborative architectural decision record creation with guided discovery, research integration, and progressive documentation building - Brought to you by microsoft/edge-ai" + }, + { + "name": "arch-diagram-builder", + "path": "./.github/chatmodes/arch-diagram-builder.chatmode.md", + "description": "Architecture diagram builder agent that builds high quality ASCII-art diagrams - Brought to you by microsoft/hve-core" + }, + { + "name": "brd-builder", + "path": "./.github/chatmodes/brd-builder.chatmode.md", + "description": "Business Requirements Document builder with guided Q&A and reference integration" + }, + { + "name": "gen-data-spec", + "path": "./.github/chatmodes/gen-data-spec.chatmode.md", + "description": "Generate comprehensive data dictionaries, machine-readable data profiles, and objective summaries for downstream analysis (EDA notebooks, dashboards) through guided discovery" + }, + { + "name": "gen-jupyter-notebook", + "path": "./.github/chatmodes/gen-jupyter-notebook.chatmode.md", + "description": "Create a structured exploratory data analysis Jupyter notebook leveraging available data sources & generated data dictionaries WITHOUT directly embedding raw data dumps." + }, + { + "name": "gen-streamlit-dashboard", + "path": "./.github/chatmodes/gen-streamlit-dashboard.chatmode.md", + "description": "Develop a multi-page streamlit dashboard" + }, + { + "name": "github-issue-manager", + "path": "./.github/chatmodes/github-issue-manager.chatmode.md", + "description": "Interactive GitHub issue management with conversational workflows for filing, navigating, and searching issues" + }, + { + "name": "pr-review", + "path": "./.github/chatmodes/pr-review.chatmode.md", + "description": "Comprehensive Pull Request review assistant ensuring code quality, security, and convention compliance - Brought to you by microsoft/hve-core" + }, + { + "name": "prd-builder", + "path": "./.github/chatmodes/prd-builder.chatmode.md", + "description": "Product Requirements Document builder with guided Q&A and reference integration" + }, + { + "name": "prompt-builder", + "path": "./.github/chatmodes/prompt-builder.chatmode.md", + "description": "Expert prompt engineering and validation system for creating high-quality prompts - Brought to you by microsoft/hve-core" + }, + { + "name": "security-plan-creator", + "path": "./.github/chatmodes/security-plan-creator.chatmode.md", + "description": "Expert security architect for creating comprehensive cloud security plans - Brought to you by microsoft/edge-ai" + }, + { + "name": "task-implementor", + "path": "./.github/chatmodes/task-implementor.chatmode.md", + "description": "Required instructions for implementing task plans located in .copilot-tracking/plans and .copilot-tracking/details folders, with progressive tracking and change records - Brought to you by microsoft/edge-ai" + }, + { + "name": "task-planner", + "path": "./.github/chatmodes/task-planner.chatmode.md", + "description": "Task planner for creating actionable implementation plans - Brought to you by microsoft/hve-core" + }, + { + "name": "task-researcher", + "path": "./.github/chatmodes/task-researcher.chatmode.md", + "description": "Task research specialist for comprehensive project analysis - Brought to you by microsoft/hve-core" + }, + { + "name": "test-streamlit-dashboard", + "path": "./.github/chatmodes/test-streamlit-dashboard.chatmode.md", + "description": "Comprehensive testing of the Streamlit dashboard using Playwright automation and issue tracking" + } + ], + "chatPromptFiles": [ + { + "name": "ado-create-pull-request", + "path": "./.github/prompts/ado-create-pull-request.prompt.md", + "description": "Generate pull request description, discover related work items, identify reviewers, and create Azure DevOps pull request with all linkages." + }, + { + "name": "ado-get-build-info", + "path": "./.github/prompts/ado-get-build-info.prompt.md", + "description": "Retrieve Azure DevOps build information for a Pull Request or specific Build Number." + }, + { + "name": "ado-get-my-work-items", + "path": "./.github/prompts/ado-get-my-work-items.prompt.md", + "description": "Retrieve user's current Azure DevOps work items and organize them into planning file definitions" + }, + { + "name": "ado-process-my-work-items-for-task-planning", + "path": "./.github/prompts/ado-process-my-work-items-for-task-planning.prompt.md", + "description": "Process retrieved work items for task planning and generate task-planning-logs.md handoff file" + }, + { + "name": "git-commit-message", + "path": "./.github/prompts/git-commit-message.prompt.md", + "description": "Generates a commit message following the commit-message.instructions.md rules based on all changes in the branch" + }, + { + "name": "git-commit", + "path": "./.github/prompts/git-commit.prompt.md", + "description": "Stages all changes, generates a conventional commit message, shows it to the user, and commits using only git add/commit" + }, + { + "name": "git-merge", + "path": "./.github/prompts/git-merge.prompt.md", + "description": "Coordinate Git merge, rebase, and rebase --onto workflows with consistent conflict handling." + }, + { + "name": "git-setup", + "path": "./.github/prompts/git-setup.prompt.md", + "description": "Interactive, verification-first Git configuration assistant (non-destructive)" + }, + { + "name": "github-add-issue", + "path": "./.github/prompts/github-add-issue.prompt.md", + "description": "Add a GitHub issue to the backlog using discovered issue templates from .github/ISSUE_TEMPLATE/" + }, + { + "name": "pull-request", + "path": "./.github/prompts/pull-request.prompt.md", + "description": "Provides prompt instructions for pull request (PR) generation - Brought to you by microsoft/edge-ai" + } + ], + "chatInstructions": [ + { + "name": "ado-create-pull-request-instructions", + "path": "./.github/instructions/ado-create-pull-request.instructions.md", + "description": "Required protocol for creating Azure DevOps pull requests with work item discovery, reviewer identification, and automated linking." + }, + { + "name": "ado-get-build-info-instructions", + "path": "./.github/instructions/ado-get-build-info.instructions.md", + "description": "Required instructions for anything related to Azure Devops or ado build information including status, logs, or details from provided pullrequest (PR), build Id, or branch name." + }, + { + "name": "ado-update-wit-items-instructions", + "path": "./.github/instructions/ado-update-wit-items.instructions.md", + "description": "Required instructions for work item updating and creation leveraging mcp ado tool calls." + }, + { + "name": "ado-wit-discovery-instructions", + "path": "./.github/instructions/ado-wit-discovery.instructions.md", + "description": "Required protocol for discovering, planning, and handing off Azure DevOps User Stories and Bugs." + }, + { + "name": "ado-wit-planning-instructions", + "path": "./.github/instructions/ado-wit-planning.instructions.md", + "description": "Required instructions for work item planning and creation or updating leveraging mcp ado tool calls." + }, + { + "name": "bash-instructions", + "path": "./.github/instructions/bash/bash.instructions.md", + "description": "Instructions for bash script implementation - Brought to you by microsoft/edge-ai" + }, + { + "name": "bicep-instructions", + "path": "./.github/instructions/bicep/bicep.instructions.md", + "description": "Instructions for Bicep infrastructure as code implementation - Brought to you by microsoft/edge-ai" + }, + { + "name": "commit-message-instructions", + "path": "./.github/instructions/commit-message.instructions.md", + "description": "Required instructions for creating all commit messages - Brought to you by microsoft/edge-ai" + }, + { + "name": "csharp-tests-instructions", + "path": "./.github/instructions/csharp/csharp-tests.instructions.md", + "description": "Required instructions for C# (CSharp) test code research, planning, implementation, editing, or creating" + }, + { + "name": "csharp-instructions", + "path": "./.github/instructions/csharp/csharp.instructions.md", + "description": "Instructions for C# (CSharp) implementation - Brought to you by microsoft/edge-ai" + }, + { + "name": "git-merge-instructions", + "path": "./.github/instructions/git-merge.instructions.md", + "description": "Required protocol for Git merge, rebase, and rebase --onto workflows with conflict handling and stop controls." + }, + { + "name": "markdown-instructions", + "path": "./.github/instructions/markdown.instructions.md", + "description": "Required instructions for creating or editing any Markdown (.md) files" + }, + { + "name": "python-script-instructions", + "path": "./.github/instructions/python-script.instructions.md", + "description": "Instructions for python scripting implementation - Brought to you by microsoft/edge-ai" + }, + { + "name": "shell-instructions", + "path": "./.github/instructions/shell.instructions.md", + "description": "Instructions for shell script implementation using Bash conventions - Brought to you by microsoft/edge-ai" + }, + { + "name": "task-implementation-instructions", + "path": "./.github/instructions/task-implementation.instructions.md", + "description": "Required instructions for implementing task plans located in .copilot-tracking/plans and .copilot-tracking/details folders, with progressive tracking and change records - Brought to you by microsoft/edge-ai" + }, + { + "name": "uv-projects-instructions", + "path": "./.github/instructions/uv-projects.instructions.md", + "description": "Instructions for Uv Projects" + } + ] + }, + "author": "Microsoft", + "license": "MIT" +} diff --git a/package.json b/package.json index a980c84f9..863ee7ca6 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,11 @@ "lint:md-links": "pwsh -File scripts/linting/Markdown-Link-Check.ps1", "lint:frontmatter": "pwsh -NoProfile -File scripts/linting/Validate-MarkdownFrontmatter.ps1 -WarningsAsErrors -EnableSchemaValidation", "lint:all": "npm run lint:md && npm run lint:ps && npm run lint:links && npm run lint:frontmatter", - "format:tables": "markdown-table-formatter \"**/*.md\"" + "format:tables": "markdown-table-formatter \"**/*.md\"", + "extension:prepare": "pwsh ./scripts/extension/Prepare-Extension.ps1", + "extension:package": "pwsh ./scripts/extension/Package-Extension.ps1", + "package:extension": "npm run extension:prepare && npm run extension:package", + "publish:extension": "npm run extension:prepare && pwsh -Command \"Set-Location extension; try { vsce publish } catch { npx @vscode/vsce publish }\"" }, "devDependencies": { "cspell": "9.4.0", diff --git a/scripts/extension/Package-Extension.ps1 b/scripts/extension/Package-Extension.ps1 new file mode 100644 index 000000000..e282b7d5f --- /dev/null +++ b/scripts/extension/Package-Extension.ps1 @@ -0,0 +1,263 @@ +#!/usr/bin/env pwsh + +<# +.SYNOPSIS + Packages the HVE Core VS Code extension. + +.DESCRIPTION + This script packages the VS Code extension into a .vsix file. + It uses the version from package.json or a specified version. + Optionally adds a dev patch number for pre-release builds. + +.PARAMETER Version + Optional. The version to use for the package. + If not specified, uses the version from package.json. + +.PARAMETER DevPatchNumber + Optional. Dev patch number to append (e.g., "123" creates "1.0.0-dev.123"). + +.PARAMETER ChangelogPath + Optional. Path to a changelog file to include in the package. + +.EXAMPLE + ./Package-Extension.ps1 + # Packages using version from package.json + +.EXAMPLE + ./Package-Extension.ps1 -Version "2.0.0" + # Packages with specific version + +.EXAMPLE + ./Package-Extension.ps1 -DevPatchNumber "123" + # Packages with dev version (e.g., 1.0.0-dev.123) + +.EXAMPLE + ./Package-Extension.ps1 -Version "1.1.0" -DevPatchNumber "456" + # Packages with specific dev version (1.1.0-dev.456) +#> + +[CmdletBinding()] +param( + [Parameter(Mandatory = $false)] + [string]$Version = "", + + [Parameter(Mandatory = $false)] + [string]$DevPatchNumber = "", + + [Parameter(Mandatory = $false)] + [string]$ChangelogPath = "" +) + +$ErrorActionPreference = "Stop" + +# Determine script and repo paths +$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path +$RepoRoot = (Get-Item "$ScriptDir/../..").FullName +$ExtensionDir = Join-Path $RepoRoot "extension" +$GitHubDir = Join-Path $RepoRoot ".github" +$PackageJsonPath = Join-Path $ExtensionDir "package.json" + +Write-Host "πŸ“¦ HVE Core Extension Packager" -ForegroundColor Cyan +Write-Host "==============================" -ForegroundColor Cyan +Write-Host "" + +# Verify paths exist +if (-not (Test-Path $ExtensionDir)) { + Write-Error "Extension directory not found: $ExtensionDir" + exit 1 +} + +if (-not (Test-Path $PackageJsonPath)) { + Write-Error "package.json not found: $PackageJsonPath" + exit 1 +} + +if (-not (Test-Path $GitHubDir)) { + Write-Error ".github directory not found: $GitHubDir" + exit 1 +} + +# Read current package.json +Write-Host "πŸ“– Reading package.json..." -ForegroundColor Yellow +try { + $packageJson = Get-Content -Path $PackageJsonPath -Raw | ConvertFrom-Json +} catch { + Write-Error "Failed to parse package.json: $_`nPlease check $PackageJsonPath for JSON syntax errors." + exit 1 +} + +# Validate package.json has required version field +if (-not $packageJson.PSObject.Properties['version']) { + Write-Error "package.json is missing required 'version' field" + exit 1 +} + +# Determine version +$baseVersion = if ($Version -and $Version -ne "") { + # Validate specified version format + if ($Version -notmatch '^\d+\.\d+\.\d+$') { + Write-Error "Invalid version format specified: '$Version'. Expected semantic version format (e.g., 1.0.0).`nPre-release suffixes like '-dev.123' should be added via -DevPatchNumber parameter, not in the version itself." + exit 1 + } + $Version +} else { + # Use version from package.json + $currentVersion = $packageJson.version + if ($currentVersion -notmatch '^\d+\.\d+\.\d+') { + $errorMessage = @( + "Invalid version format in package.json: '$currentVersion'.", + "Expected semantic version format (e.g., 1.0.0).", + "Pre-release suffixes should not be committed to package.json.", + "Use -DevPatchNumber parameter to add '-dev.N' suffix during packaging." + ) -join "`n" + Write-Error $errorMessage + exit 1 + } + # Extract base version (validation above ensures this will match) + $currentVersion -match '^(\d+\.\d+\.\d+)' | Out-Null + $Matches[1] +} + +# Apply dev patch number if provided +$packageVersion = if ($DevPatchNumber -and $DevPatchNumber -ne "") { + "$baseVersion-dev.$DevPatchNumber" +} else { + $baseVersion +} + +Write-Host " Using version: $packageVersion" -ForegroundColor Green + +# Handle temporary version update for dev builds +$originalVersion = $packageJson.version + +if ($packageVersion -ne $originalVersion) { + Write-Host "" + Write-Host "πŸ“ Temporarily updating package.json version..." -ForegroundColor Yellow + $packageJson.version = $packageVersion + $packageJson | ConvertTo-Json -Depth 10 | Set-Content -Path $PackageJsonPath -Encoding UTF8NoBOM + Write-Host " Version: $originalVersion -> $packageVersion" -ForegroundColor Green +} + +# Handle changelog if provided +if ($ChangelogPath -and $ChangelogPath -ne "") { + Write-Host "" + Write-Host "πŸ“‹ Processing changelog..." -ForegroundColor Yellow + + if (Test-Path $ChangelogPath) { + $changelogDest = Join-Path $ExtensionDir "CHANGELOG.md" + Copy-Item -Path $ChangelogPath -Destination $changelogDest -Force + Write-Host " Copied changelog to extension directory" -ForegroundColor Green + } else { + Write-Warning "Changelog file not found: $ChangelogPath" + } +} + +# Prepare extension directory +Write-Host "" +Write-Host "πŸ—‚οΈ Preparing extension directory..." -ForegroundColor Yellow + +# Clean any existing copied directories +$dirsToClean = @(".github", "scripts") +foreach ($dir in $dirsToClean) { + $dirPath = Join-Path $ExtensionDir $dir + if (Test-Path $dirPath) { + Remove-Item -Path $dirPath -Recurse -Force + Write-Host " Cleaned existing $dir directory" -ForegroundColor Gray + } +} + +# Copy required directories +Write-Host " Copying .github..." -ForegroundColor Gray +Copy-Item -Path "$RepoRoot/.github" -Destination "$ExtensionDir/.github" -Recurse + +Write-Host " Copying scripts/dev-tools..." -ForegroundColor Gray +New-Item -Path "$ExtensionDir/scripts" -ItemType Directory -Force | Out-Null +Copy-Item -Path "$RepoRoot/scripts/dev-tools" -Destination "$ExtensionDir/scripts/dev-tools" -Recurse + +Write-Host " βœ… Extension directory prepared" -ForegroundColor Green + +# Package extension +Write-Host "" +Write-Host "πŸ“¦ Packaging extension..." -ForegroundColor Yellow + +# Initialize vsixFile variable to avoid scope issues +$vsixFile = $null + +Push-Location $ExtensionDir + +try { + # Check if vsce is available + $vsceCmd = Get-Command vsce -ErrorAction SilentlyContinue + if (-not $vsceCmd) { + $vsceCmd = Get-Command npx -ErrorAction SilentlyContinue + if ($vsceCmd) { + Write-Host " Using npx @vscode/vsce..." -ForegroundColor Gray + & npx @vscode/vsce package --no-dependencies + } else { + Write-Error "Neither vsce nor npx found. Please install @vscode/vsce globally or ensure npm is available." + exit 1 + } + } else { + Write-Host " Using vsce..." -ForegroundColor Gray + & vsce package --no-dependencies + } + + if ($LASTEXITCODE -ne 0) { + Write-Error "Failed to package extension" + exit 1 + } + + # Find the generated vsix file + $vsixFile = Get-ChildItem -Path $ExtensionDir -Filter "*.vsix" | Sort-Object LastWriteTime -Descending | Select-Object -First 1 + + if ($vsixFile) { + Write-Host "" + Write-Host "βœ… Extension packaged successfully!" -ForegroundColor Green + Write-Host " File: $($vsixFile.Name)" -ForegroundColor Cyan + Write-Host " Size: $([math]::Round($vsixFile.Length / 1KB, 2)) KB" -ForegroundColor Cyan + Write-Host " Version: $packageVersion" -ForegroundColor Cyan + } else { + Write-Error "No .vsix file found after packaging" + exit 1 + } + +} finally { + Pop-Location + + # Cleanup copied directories + Write-Host "" + Write-Host "🧹 Cleaning up..." -ForegroundColor Yellow + + foreach ($dir in $dirsToClean) { + $dirPath = Join-Path $ExtensionDir $dir + if (Test-Path $dirPath) { + Remove-Item -Path $dirPath -Recurse -Force + Write-Host " Removed $dir" -ForegroundColor Gray + } + } + + # Restore original version if it was changed + if ($packageVersion -ne $originalVersion) { + Write-Host "" + Write-Host "πŸ”„ Restoring original package.json version..." -ForegroundColor Yellow + $packageJson.version = $originalVersion + $packageJson | ConvertTo-Json -Depth 10 | Set-Content -Path $PackageJsonPath -Encoding UTF8NoBOM + Write-Host " Version restored to: $originalVersion" -ForegroundColor Green + } +} + +Write-Host "" +Write-Host "πŸŽ‰ Done!" -ForegroundColor Green +Write-Host "" + +# Output for CI/CD consumption +if ($env:GITHUB_OUTPUT) { + if ($vsixFile) { + "version=$packageVersion" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8 + "vsix-file=$($vsixFile.Name)" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8 + } else { + Write-Warning "Cannot write GITHUB_OUTPUT: vsix file not available" + } +} + +exit 0 diff --git a/scripts/extension/Prepare-Extension.ps1 b/scripts/extension/Prepare-Extension.ps1 new file mode 100644 index 000000000..d3ad8d5b7 --- /dev/null +++ b/scripts/extension/Prepare-Extension.ps1 @@ -0,0 +1,322 @@ +#!/usr/bin/env pwsh +#Requires -Modules PowerShell-Yaml + +<# +.SYNOPSIS + Prepares the HVE Core VS Code extension for packaging. + +.DESCRIPTION + This script prepares the VS Code extension by: + - Auto-discovering chat agents, chatmodes, prompts, and instruction files + - Updating package.json with discovered components + - Updating changelog if provided + + The package.json version is not modified. + +.PARAMETER ChangelogPath + Optional. Path to a changelog file to include in the package. + +.PARAMETER DryRun + Optional. If specified, shows what would be done without making changes. + +.EXAMPLE + ./Prepare-Extension.ps1 + # Prepares using existing version from package.json + +.EXAMPLE + ./Prepare-Extension.ps1 -ChangelogPath "./CHANGELOG.md" + # Prepares with changelog + +.NOTES + Dependencies: PowerShell-Yaml module +#> + +[CmdletBinding()] +param( + [Parameter(Mandatory = $false)] + [string]$ChangelogPath = "", + + [Parameter(Mandatory = $false)] + [switch]$DryRun +) + +$ErrorActionPreference = "Stop" + +# Helper function to extract description from YAML frontmatter +function Get-DescriptionFromYaml { + param( + [Parameter(Mandatory = $true)] + [string]$FilePath, + + [Parameter(Mandatory = $false)] + [string]$FallbackDescription = "" + ) + + $content = Get-Content -Path $FilePath -Raw + $description = "" + + # Extract YAML frontmatter and parse with PowerShell-Yaml + if ($content -match '(?s)^---\s*\r?\n(.*?)\r?\n---') { + # Normalize line endings to LF for consistent parsing across platforms + $yamlContent = $Matches[1] -replace '\r\n', "`n" -replace '\r', "`n" + try { + $data = ConvertFrom-Yaml -Yaml $yamlContent + if ($data.ContainsKey('description')) { + $description = $data.description + } + } catch { + Write-Warning "Failed to parse YAML frontmatter in $(Split-Path -Leaf $FilePath): $_" + } + } + + # Return description or fallback + if ($description) { + return $description + } else { + return $FallbackDescription + } +} + +# Determine script and repo paths +$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path +$RepoRoot = (Get-Item "$ScriptDir/../..").FullName +$ExtensionDir = Join-Path $RepoRoot "extension" +$GitHubDir = Join-Path $RepoRoot ".github" +$PackageJsonPath = Join-Path $ExtensionDir "package.json" + +Write-Host "πŸ“¦ HVE Core Extension Preparer" -ForegroundColor Cyan +Write-Host "==============================" -ForegroundColor Cyan +Write-Host "" + +# Verify paths exist +if (-not (Test-Path $ExtensionDir)) { + Write-Error "Extension directory not found: $ExtensionDir" + exit 1 +} + +if (-not (Test-Path $PackageJsonPath)) { + Write-Error "package.json not found: $PackageJsonPath" + exit 1 +} + +if (-not (Test-Path $GitHubDir)) { + Write-Error ".github directory not found: $GitHubDir" + exit 1 +} + +# Read current package.json +Write-Host "πŸ“– Reading package.json..." -ForegroundColor Yellow +try { + $packageJson = Get-Content -Path $PackageJsonPath -Raw | ConvertFrom-Json +} catch { + Write-Error "Failed to parse package.json: $_`nPlease check $PackageJsonPath for JSON syntax errors." + exit 1 +} + +# Validate package.json has required version field +if (-not $packageJson.PSObject.Properties['version']) { + Write-Error "package.json is missing required 'version' field" + exit 1 +} + +# Use existing version from package.json +$version = $packageJson.version + +# Validate version format +if ($version -notmatch '^\d+\.\d+\.\d+$') { + Write-Error "Invalid version format in package.json: '$version'. Expected semantic version format (e.g., 1.0.0)" + exit 1 +} + +Write-Host " Using version: $version" -ForegroundColor Green + +# Discover chat agents +Write-Host "" +Write-Host "πŸ” Discovering chat agents..." -ForegroundColor Yellow +$agentsDir = Join-Path $GitHubDir "agents" +$chatAgents = @() + +if (Test-Path $agentsDir) { + $agentFiles = Get-ChildItem -Path $agentsDir -Filter "*.agent.md" | Sort-Object Name + + foreach ($agentFile in $agentFiles) { + # Extract agent name from filename (e.g., hve-core-installer.agent.md -> hve-core-installer) + $agentName = $agentFile.BaseName -replace '\.agent$', '' + + # Extract description from YAML frontmatter + $description = Get-DescriptionFromYaml -FilePath $agentFile.FullName -FallbackDescription "AI agent for $agentName" + + $agent = [PSCustomObject]@{ + name = $agentName + path = "./.github/agents/$($agentFile.Name)" + description = $description + } + + $chatAgents += $agent + Write-Host " βœ… $agentName" -ForegroundColor Green + } +} else { + Write-Warning "Agents directory not found: $agentsDir" +} + +# Discover chatmodes +Write-Host "" +Write-Host "πŸ” Discovering chatmodes..." -ForegroundColor Yellow +$chatmodesDir = Join-Path $GitHubDir "chatmodes" +$chatmodes = @() + +if (Test-Path $chatmodesDir) { + $chatmodeFiles = Get-ChildItem -Path $chatmodesDir -Filter "*.chatmode.md" | Sort-Object Name + + foreach ($chatmodeFile in $chatmodeFiles) { + # Extract chatmode name from filename (e.g., task-planner.chatmode.md -> task-planner) + $chatmodeName = $chatmodeFile.BaseName -replace '\.chatmode$', '' + + # Extract description from YAML frontmatter + $displayName = $chatmodeName -replace '-', ' ' + $description = Get-DescriptionFromYaml -FilePath $chatmodeFile.FullName -FallbackDescription "Chatmode for $displayName" + + $chatmode = [PSCustomObject]@{ + name = $chatmodeName + path = "./.github/chatmodes/$($chatmodeFile.Name)" + description = $description + } + + $chatmodes += $chatmode + Write-Host " βœ… $chatmodeName" -ForegroundColor Green + } +} else { + Write-Warning "Chatmodes directory not found: $chatmodesDir" +} + +# Discover prompts +Write-Host "" +Write-Host "πŸ” Discovering prompts..." -ForegroundColor Yellow +$promptsDir = Join-Path $GitHubDir "prompts" +$chatPromptFiles = @() + +if (Test-Path $promptsDir) { + $promptFiles = Get-ChildItem -Path $promptsDir -Filter "*.prompt.md" -Recurse | Sort-Object Name + + foreach ($promptFile in $promptFiles) { + # Extract prompt name from filename (e.g., git-commit.prompt.md -> git-commit) + $promptName = $promptFile.BaseName -replace '\.prompt$', '' + + # Extract description from YAML frontmatter + $displayName = ($promptName -replace '-', ' ') -replace '(\b\w)', { $_.Groups[1].Value.ToUpper() } + $description = Get-DescriptionFromYaml -FilePath $promptFile.FullName -FallbackDescription "Prompt for $displayName" + + # Calculate relative path from .github + $relativePath = $promptFile.FullName.Substring($GitHubDir.Length + 1) -replace '\\', '/' + + $prompt = [PSCustomObject]@{ + name = $promptName + path = "./.github/$relativePath" + description = $description + } + + $chatPromptFiles += $prompt + Write-Host " βœ… $promptName" -ForegroundColor Green + } +} else { + Write-Warning "Prompts directory not found: $promptsDir" +} + +# Discover instruction files +Write-Host "" +Write-Host "πŸ” Discovering instruction files..." -ForegroundColor Yellow +$instructionsDir = Join-Path $GitHubDir "instructions" +$chatInstructions = @() + +if (Test-Path $instructionsDir) { + $instructionFiles = Get-ChildItem -Path $instructionsDir -Filter "*.instructions.md" -Recurse | Sort-Object Name + + foreach ($instrFile in $instructionFiles) { + # Extract instruction name from filename (e.g., commit-message.instructions.md -> commit-message-instructions) + $baseName = $instrFile.BaseName -replace '\.instructions$', '' + $instrName = "$baseName-instructions" + + # Extract description from YAML frontmatter + $displayName = ($baseName -replace '-', ' ') -replace '(\b\w)', { $_.Groups[1].Value.ToUpper() } + $description = Get-DescriptionFromYaml -FilePath $instrFile.FullName -FallbackDescription "Instructions for $displayName" + + # Calculate relative path from .github using cross-platform APIs + $relativePathFromGitHub = [System.IO.Path]::GetRelativePath($GitHubDir, $instrFile.FullName) + $normalizedRelativePath = (Join-Path ".github" $relativePathFromGitHub) -replace '\\', '/' + + $instruction = [PSCustomObject]@{ + name = $instrName + path = "./$normalizedRelativePath" + description = $description + } + + $chatInstructions += $instruction + Write-Host " βœ… $instrName" -ForegroundColor Green + } +} else { + Write-Warning "Instructions directory not found: $instructionsDir" +} + +# Update package.json +Write-Host "" +Write-Host "πŸ“ Updating package.json..." -ForegroundColor Yellow + +# Ensure contributes section exists +if (-not $packageJson.contributes) { + $packageJson | Add-Member -NotePropertyName "contributes" -NotePropertyValue ([PSCustomObject]@{}) +} + +# Combine agents and chatmodes into chatAgents (VS Code treats chatmodes as chatAgents) +$allChatAgents = $chatAgents + $chatmodes + +# Update chatAgents +$packageJson.contributes.chatAgents = $allChatAgents +Write-Host " Updated chatAgents: $($allChatAgents.Count) items ($($chatAgents.Count) agents + $($chatmodes.Count) chatmodes)" -ForegroundColor Green + +# Update chatPromptFiles +$packageJson.contributes.chatPromptFiles = $chatPromptFiles +Write-Host " Updated chatPromptFiles: $($chatPromptFiles.Count) prompts" -ForegroundColor Green + +# Update chatInstructions +$packageJson.contributes.chatInstructions = $chatInstructions +Write-Host " Updated chatInstructions: $($chatInstructions.Count) files" -ForegroundColor Green + +if ($DryRun) { + Write-Host "" + Write-Host "πŸ” DRY RUN - Would write the following package.json:" -ForegroundColor Magenta + Write-Host ($packageJson | ConvertTo-Json -Depth 10) + Write-Host "" + Write-Host "πŸ” DRY RUN - No changes made" -ForegroundColor Magenta + exit 0 +} + +# Write updated package.json +$packageJson | ConvertTo-Json -Depth 10 | Set-Content -Path $PackageJsonPath -Encoding UTF8NoBOM +Write-Host " Saved package.json" -ForegroundColor Green + +# Handle changelog if provided +if ($ChangelogPath) { + Write-Host "" + Write-Host "πŸ“‹ Processing changelog..." -ForegroundColor Yellow + + if (Test-Path $ChangelogPath) { + $changelogDest = Join-Path $ExtensionDir "CHANGELOG.md" + Copy-Item -Path $ChangelogPath -Destination $changelogDest -Force + Write-Host " Copied changelog to extension directory" -ForegroundColor Green + } else { + Write-Warning "Changelog file not found: $ChangelogPath" + } +} + +Write-Host "" +Write-Host "πŸŽ‰ Done!" -ForegroundColor Green +Write-Host "" +Write-Host "πŸ“Š Summary:" -ForegroundColor Cyan +Write-Host " Version: $version" -ForegroundColor White +Write-Host " Chat Agents: $($chatAgents.Count)" -ForegroundColor White +Write-Host " Chatmodes: $($chatmodes.Count)" -ForegroundColor White +Write-Host " Prompts: $($chatPromptFiles.Count)" -ForegroundColor White +Write-Host " Instructions: $($chatInstructions.Count)" -ForegroundColor White +Write-Host "" + +exit 0