diff --git a/.github/BRANCH_PROTECTION_CHECKLIST.md b/.github/BRANCH_PROTECTION_CHECKLIST.md new file mode 100644 index 0000000..4e52b41 --- /dev/null +++ b/.github/BRANCH_PROTECTION_CHECKLIST.md @@ -0,0 +1,67 @@ +# Branch Protection Quick Setup Checklist + +Use this checklist when configuring branch protection for the first time. + +## βœ… Pre-Setup (Already Complete) + +- [x] CODEOWNERS file created (`.github/CODEOWNERS`) +- [x] CI/CD workflows configured (`ci.yml`, `security.yml`) +- [x] Documentation available (`doc/BRANCH_PROTECTION.md`) + +## πŸ”§ GitHub Settings Configuration + +Navigate to: **Repository Settings β†’ Branches β†’ Add rule** + +### Branch Pattern +- [ ] Branch name pattern: `main` + +### Pull Request Requirements +- [ ] βœ… Require a pull request before merging + - [ ] Required approvals: **1** (minimum) + - [ ] βœ… Dismiss stale pull request approvals when new commits are pushed + - [ ] βœ… Require review from Code Owners (recommended) + +### Status Check Requirements +- [ ] βœ… Require status checks to pass before merging + - [ ] Search and add: `build-and-test` + - [ ] Search and add: `nodejs-tools` + - [ ] Search and add: `security-scan` + - [ ] Search and add: `codeql-analysis` + - [ ] βœ… Require branches to be up to date before merging + +### Additional Protections +- [ ] βœ… Require conversation resolution before merging +- [ ] ⬜ Do not allow bypassing the above settings (optional - prevents admin bypass) + +### Save +- [ ] Click **Create** to save the branch protection rule + +## πŸ§ͺ Testing + +After setup, test that it works: + +1. [ ] Create a test branch +2. [ ] Make a small change +3. [ ] Push and create a PR +4. [ ] Verify you're automatically assigned as reviewer +5. [ ] Try to merge without approval (should be blocked) +6. [ ] Approve the PR +7. [ ] Merge successfully + +## πŸ“š Reference + +For detailed instructions, see: [doc/BRANCH_PROTECTION.md](../doc/BRANCH_PROTECTION.md) + +## πŸ†˜ Need Help? + +- **Can't find the settings?** Make sure you have admin access to the repository +- **Status checks not appearing?** Run the workflows at least once first +- **Need to bypass temporarily?** Uncheck "Do not allow bypassing" in the rule settings + +## What Happens After Setup? + +βœ… All changes to `main` require a pull request +βœ… Pull requests require your approval before merging +βœ… CI/CD checks must pass before merging +βœ… You're automatically assigned as reviewer on all PRs +βœ… Direct pushes to `main` are blocked diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..48742a4 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,17 @@ +# CODEOWNERS file for dragon-copilot-extension-samples-test +# This file defines who should be automatically requested for review on pull requests. +# +# Each line is a file pattern followed by one or more owners. +# These owners will be automatically requested for review when someone opens a pull request +# that modifies files matching the pattern. +# +# Documentation: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners + +# Default owner for all files in the repository +# This ensures that @mfrongillo35 is automatically requested to review all pull requests +* @mfrongillo35 + +# You can add more specific rules below as needed, for example: +# /docs/ @mfrongillo35 @documentation-team +# *.js @mfrongillo35 @frontend-team +# /samples/ @mfrongillo35 @sample-reviewers diff --git a/.github/dependabot.yml b/.github/dependabot.yml index c6bb20d..38c1d42 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -34,7 +34,7 @@ updates: # Enable version updates for npm dependencies - package-ecosystem: "npm" - directory: "/tools/dragon-extension-cli" + directory: "/tools/dragon-copilot-cli" schedule: interval: "weekly" day: "monday" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bd3cdcc..88dbb79 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,16 +55,16 @@ jobs: with: node-version: '20' cache: 'npm' - cache-dependency-path: tools/dragon-extension-cli/package.json + cache-dependency-path: tools/dragon-copilot-cli/package-lock.json - name: Install dependencies - working-directory: tools/dragon-extension-cli + working-directory: tools/dragon-copilot-cli run: npm ci - name: Run tests - working-directory: tools/dragon-extension-cli + working-directory: tools/dragon-copilot-cli run: npm test - name: Build - working-directory: tools/dragon-extension-cli + working-directory: tools/dragon-copilot-cli run: npm run build --if-present diff --git a/QUICKSTART.md b/QUICKSTART.md index 592db40..5fb89a2 100644 --- a/QUICKSTART.md +++ b/QUICKSTART.md @@ -1,3 +1,4 @@ +# # Quick Start Guide for Dragon Extension Developer ## πŸš€ Getting Started (Choose One) @@ -7,6 +8,28 @@ * Node 22.20.0 * npm 10.9.3 +### Generate Manifests with the CLI +Use the unified `dragon-copilot` CLI to create and validate manifest version 3 definitions that now support automation scripts, event triggers, and dependency metadata. + +```powershell +cd tools/dragon-copilot-cli +npm install +npm run build +npm link + +# Interactive extension wizard (prompts for scripts/triggers/dependencies) +dragon-copilot extension init + +# Validate both extension and publisher configuration together +dragon-copilot extension validate ./extension.yaml + +# Partner manifest workflow +dragon-copilot partner init +dragon-copilot partner validate ./integration.yaml +``` + +> Tip: The wizard ensures `manifestVersion: 3` is set and collects automation metadata so the generated YAML aligns with the new schema shipped in this repository. + ### Local Development Environment 1. Clone the repository 1. Open a terminal and navigate to `samples/DragonCopilot/Workflow/SampleExtension.Web` diff --git a/README.md b/README.md index 7c6ccb2..32879cb 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Welcome! This repository contains sample code illustrating the Dragon Copilot ex - [Samples](#-samples) - [Tools](#️-tools) - [Contributing](#-contributing) +- [Repository Security](#-repository-security) - [License](#-license) ## πŸ“ Overview @@ -17,7 +18,7 @@ Welcome! This repository contains sample code illustrating the Dragon Copilot ex This repo includes: - Sample extension with best practices -- CLI tools to initialize & package extension +- Unified `dragon-copilot-cli` tooling (extension + partner flows) - [Additional Documentation](doc/) ## πŸš€ Quick Start @@ -37,21 +38,22 @@ cd dragon-copilot-extension-samples ## πŸ› οΈ Tools -### Dragon Extension CLI +### Dragon Copilot CLI -CLI to easily generate manifest & package the extension, getting ready to publish or upload the extension. +The `dragon-copilot-cli` consolidates both the legacy extension and partner CLIs. It now generates **manifest version 3** files with support for automation scripts, event triggers, and dependency metadata. Quick usage: ```bash -cd tools/dragon-extension-cli +cd tools/dragon-copilot-cli +npm install npm run build npm link -dragon-extension init -dragon-extension package +dragon-copilot extension init +dragon-copilot partner validate ./path/to/integration.yaml ``` -See [CLI README](tools/dragon-extension-cli/README.md) for details. +See [tools/dragon-copilot-cli/README.md](tools/dragon-copilot-cli/README.md) for more details, including an automation script scaffolding HOWTO. ## 🀝 Contributing @@ -62,6 +64,18 @@ See [CLI README](tools/dragon-extension-cli/README.md) for details. 5. Ensure all tests pass 6. Submit a pull request +All pull requests require review before merging to main. See the [Branch Protection Guide](doc/BRANCH_PROTECTION.md) for details on repository security settings. + +## πŸ”’ Repository Security + +This repository uses branch protection rules and code owners to maintain code quality: + +- **Pull Request Reviews Required**: All changes to `main` must go through a reviewed pull request +- **Code Owners**: The `.github/CODEOWNERS` file automatically assigns reviewers +- **CI/CD Checks**: All tests and security scans must pass before merging + +For setup instructions, see [Branch Protection Setup Guide](doc/BRANCH_PROTECTION.md). + ## πŸ“„ License MIT License. See [LICENSE](LICENSE) for details. diff --git a/STANDALONE_SETUP.md b/STANDALONE_SETUP.md new file mode 100644 index 0000000..67eb4a1 --- /dev/null +++ b/STANDALONE_SETUP.md @@ -0,0 +1,358 @@ +# Standalone Setup Guide for Dragon Copilot Extensions + +This guide explains how to extract and run the Dragon Copilot partner initialization tools **without VS Code**. + +## Windows Quick Start (Recommended) + +If you are on Windows and want an automated setup, run the helper script from the repository root: + +```powershell +pwsh ./tools/dragon-copilot-cli/scripts/setup-partner-cli.ps1 +``` + +The script will: +- Check for Node.js 22.20.0+ and install it via `winget` or Chocolatey when available +- Run `npm install` and `npm run build` inside `tools/dragon-copilot-cli` +- Launch the partner manifest wizard (`dragon-copilot partner init`) when the CLI is ready + +Optional flags: +- `-SkipNodeInstall` keeps your existing Node.js installation +- `-SkipBuild` assumes you already ran `npm install` and `npm run build` + +Use the manual steps below if you are on macOS/Linux or prefer to perform each step yourself. + +## Install Required Dependencies + +### Step 1: Install Node.js and npm + +The Dragon Copilot CLI requires Node.js (which includes npm). Choose the appropriate installation method for your platform: + +#### Windows + +**Option A: Download from Official Website** +1. Visit [https://nodejs.org](https://nodejs.org) +2. Download the **LTS version** (22.20.0 or later) +3. Run the installer (.msi file) +4. Follow the installation wizard (accept defaults) +5. Restart your command prompt/PowerShell + +**Option B: Using Package Manager (Chocolatey)** +```powershell +# Install Chocolatey if not already installed +Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) + +# Install Node.js +choco install nodejs --version=22.20.0 +``` + +**Option C: Using Package Manager (Winget)** +```powershell +# Install Node.js via Windows Package Manager +winget install OpenJS.NodeJS +``` + +#### macOS + +**Option A: Download from Official Website** +1. Visit [https://nodejs.org](https://nodejs.org) +2. Download the **LTS version** for macOS +3. Run the installer (.pkg file) +4. Follow the installation wizard + +**Option B: Using Homebrew** +```bash +# Install Homebrew if not already installed +/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" + +# Install Node.js +brew install node@22 +``` + +**Option C: Using Node Version Manager (nvm)** +```bash +# Install nvm +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash + +# Restart terminal or run: +source ~/.bashrc + +# Install Node.js +nvm install 22.20.0 +nvm use 22.20.0 +nvm alias default 22.20.0 +``` + +#### Linux (Ubuntu/Debian) + +**Option A: Using Node Package Manager (nvm) - Recommended** +```bash +# Install nvm +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash + +# Restart terminal or run: +source ~/.bashrc + +# Install Node.js +nvm install 22.20.0 +nvm use 22.20.0 +nvm alias default 22.20.0 +``` + +**Option B: Using apt package manager** +```bash +# Update package index +sudo apt update + +# Install Node.js and npm +curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - +sudo apt-get install -y nodejs +``` + +#### Linux (CentOS/RHEL/Fedora) + +```bash +# Using dnf/yum +sudo dnf install npm nodejs + +# Or using nvm (recommended for latest versions) +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash +source ~/.bashrc +nvm install 22.20.0 +nvm use 22.20.0 +``` + +### Step 2: Install .NET (Optional) + +If you plan to work with C# extensions, install .NET 9: + +#### Windows +```powershell +# Using winget +winget install Microsoft.DotNet.SDK.9 + +# Or download from: https://dotnet.microsoft.com/download +``` + +#### macOS +```bash +# Using Homebrew +brew install --cask dotnet-sdk + +# Or download from: https://dotnet.microsoft.com/download +``` + +#### Linux +```bash +# Ubuntu/Debian +wget https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb +sudo dpkg -i packages-microsoft-prod.deb +sudo apt-get update && sudo apt-get install -y dotnet-sdk-9.0 + +# Or follow instructions at: https://dotnet.microsoft.com/download +``` + +## Verify Prerequisites + +Before you begin, ensure you have the following installed: + +- **Node.js 22.20.0** or later +- **npm 10.9.3** or later +- **.NET 9** (if working with C# extensions) +- **PowerShell** (for Windows) or **Bash** (for Linux/Mac) + +You can verify your installations: + +```bash +node --version +npm --version +dotnet --version +``` + +## Step 3: Extract the Archive + +1. **Download/Receive** the Dragon Copilot extension samples zip file +2. **Extract** the archive to your desired location: + +### Windows +```powershell +# Extract using PowerShell +Expand-Archive -Path "dragon-copilot-extension-samples.zip" -DestinationPath "C:\your-project-folder" +cd "C:\your-project-folder\dragon-copilot-extension-samples" +``` + +### Linux/Mac +```bash +# Extract using unzip +unzip dragon-copilot-extension-samples.zip -d /your-project-folder +cd /your-project-folder/dragon-copilot-extension-samples +``` + +## Step 4: Install and Build the CLI Tools + +Navigate to the CLI tools directory and set up the Dragon Copilot CLI: + +### Windows (PowerShell) +```powershell +cd tools\dragon-copilot-cli +npm install +npm run build +npm link +``` + +### Linux/Mac (Bash) +```bash +cd tools/dragon-copilot-cli +npm install +npm run build +npm link +``` + +This will: +- Install all required dependencies +- Build the TypeScript CLI from source +- Create a global `dragon-copilot` command available from anywhere + +## Step 5: Verify CLI Installation + +Test that the CLI is properly installed: + +```bash +dragon-copilot --help +``` + +You should see the CLI help menu with available commands. + +## Step 6: Initialize Partner Integration + +Now you can run the partner initialization wizard: + +```bash +dragon-copilot partner init +``` + +This interactive wizard will: +- Guide you through creating a `integration.yaml` manifest +- Configure partner authentication settings +- Set up clinical application integration details +- Create publisher configuration + +The wizard will prompt you for: +- **Partner name** and description +- **Clinical application name** (the EHR or workflow system) +- **Authentication method** (JWT, API key, etc.) +- **API endpoints** and configuration +- **Data access requirements** + +## Step 7: Validate Your Configuration + +After completing the wizard, validate your configuration: + +```bash +dragon-copilot partner validate ./integration.yaml +``` + +This ensures your manifest follows the correct schema and business rules. + +## Step 8: Working with Extensions (Optional) + +If you want to create Dragon Copilot extensions (not just partner integrations): + +```bash +# Create a new extension +dragon-copilot extension init + +# Validate extension manifest +dragon-copilot extension validate ./extension.yaml + +# Package extension for distribution +dragon-copilot extension package --manifest ./extension.yaml +``` + +## Directory Structure After Setup + +After extraction and setup, your directory structure should look like: + +``` +your-project-folder/ +β”œβ”€β”€ dragon-copilot-extension-samples/ +β”‚ β”œβ”€β”€ doc/ # Documentation +β”‚ β”œβ”€β”€ samples/ # Sample implementations +β”‚ β”‚ └── DragonCopilot/ +β”‚ β”‚ └── Workflow/ +β”‚ β”‚ └── SampleExtension.Web/ # C# sample extension +β”‚ β”œβ”€β”€ src/ +β”‚ β”‚ └── Dragon.Copilot.Models/ # Data models and contracts +β”‚ β”œβ”€β”€ tools/ +β”‚ β”‚ └── dragon-copilot-cli/ # CLI tools (now built) +β”‚ └── [your-integration-files]/ # Generated by wizard +β”‚ β”œβ”€β”€ integration.yaml # Partner manifest +β”‚ β”œβ”€β”€ publisher.json # Publisher configuration +β”‚ └── assets/ # Logos and resources +``` + +## Troubleshooting + +### CLI Not Found +If `dragon-copilot` command is not recognized: + +1. **Verify npm global directory** is in your PATH: + ```bash + npm config get prefix + ``` + +2. **Manually add to PATH** if needed: + - Windows: Add `%APPDATA%\npm` to your PATH + - Linux/Mac: Add `~/.npm-global/bin` to your PATH + +3. **Alternative: Use npx** instead of global install: + ```bash + cd tools/dragon-copilot-cli + npx dragon-copilot partner init + ``` + +### Permission Issues (Linux/Mac) +If you encounter permission errors with `npm link`: + +```bash +# Use a global directory you own +mkdir ~/.npm-global +npm config set prefix '~/.npm-global' +echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.bashrc +source ~/.bashrc + +# Then retry the build and link +npm run build +npm link +``` + +### Node.js Version Issues +Ensure you're using Node.js 22.20.0 or compatible version. If you need to install or update Node.js, refer to the detailed installation instructions in **Step 1: Install Node.js and npm** section above. + +Quick verification: +```bash +node --version # Should show v22.20.0 or later +npm --version # Should show v10.9.3 or later +``` + +If you need to switch versions using nvm: +```bash +# Linux/Mac/Windows (with nvm-windows) +nvm install 22.20.0 +nvm use 22.20.0 +``` + +## Next Steps + +1. **Review Documentation**: Check the `doc/` folder for authentication patterns and API integration guides +2. **Examine Sample Code**: Look at `samples/DragonCopilot/Workflow/SampleExtension.Web/` for implementation examples +3. **Test Integration**: Use the generated configuration files to test your Dragon Copilot integration +4. **Deploy**: Follow deployment guides in the documentation for production setup + +## Getting Help + +- **CLI Help**: Run `dragon-copilot --help` or `dragon-copilot --help` +- **Documentation**: Review files in the `doc/` directory +- **Sample Code**: Examine the sample extension in `samples/` for patterns +- **Validation**: Use `dragon-copilot partner validate` to check your configuration + +This setup allows you to use all Dragon Copilot development tools without requiring VS Code, using only command-line tools and your preferred text editor. \ No newline at end of file diff --git a/doc/Authentication.md b/doc/Authentication.md index 2ff7647..fa3ba46 100644 --- a/doc/Authentication.md +++ b/doc/Authentication.md @@ -49,6 +49,8 @@ The production configuration in file [appsettings.json](../samples/DragonCopilot - `HeaderName`: Custom header name for license keys (e.g., `"X-License-Key"`) - `ValidKeys`: Array of valid license key values +> **Manifest v3 Note**: When you generate manifests with the new `dragon-copilot` CLI, the `auth.tenantId` field captured in `extension.yaml` must match the `TenantId` configured here. The CLI wizard will prompt for the same tenant information to keep runtime and manifest settings aligned. + ## Microsoft Entra ID (JWT) Authentication ### Implementation Features diff --git a/doc/AuthenticationDesign.md b/doc/AuthenticationDesign.md index 758622a..9888ccb 100644 --- a/doc/AuthenticationDesign.md +++ b/doc/AuthenticationDesign.md @@ -10,6 +10,8 @@ Additionally, you will find the threat model applied to the service-to-service r See [Authentication.md](Authentication.md) for implementation details in the Sample Extension. +> **Related tooling**: The `dragon-copilot` CLI generates manifest version 3 files that capture the same tenant identifiers discussed here. Ensure the values provided to the CLI match the configuration steps below so request validation succeeds. + ## Service-to-Service Authentication Overview The Dragon Copilot Extension Runtime receives extension configuration including the extension's endpoint and authentication information. diff --git a/doc/BRANCH_PROTECTION.md b/doc/BRANCH_PROTECTION.md new file mode 100644 index 0000000..6e8721b --- /dev/null +++ b/doc/BRANCH_PROTECTION.md @@ -0,0 +1,171 @@ +# Branch Protection Setup Guide + +This guide explains how to configure GitHub branch protection rules to require pull request reviews before merging to the `main` branch. + +## Overview + +Branch protection rules help you enforce certain workflows and requirements before code can be merged into protected branches. This is essential for maintaining code quality and security in your repository. + +## Prerequisites + +- You must have **admin** access to the repository +- The repository must have at least one branch (typically `main`) + +## Step-by-Step Setup + +### 1. Navigate to Branch Protection Settings + +1. Go to your repository on GitHub +2. Click on **Settings** (top navigation bar) +3. In the left sidebar, click **Branches** (under "Code and automation") + +### 2. Add Branch Protection Rule + +1. Click the **Add rule** button (or **Add branch protection rule**) +2. In the **Branch name pattern** field, enter: `main` + - This applies the rule to the main branch + - You can also use wildcards like `release/*` to protect multiple branches + +### 3. Configure Required Settings + +Configure the following options to require pull request reviews: + +#### Required Options: + +βœ… **Require a pull request before merging** + - Check this box to ensure all changes go through a pull request + - This prevents direct pushes to the main branch + + Under this option, configure: + - βœ… **Require approvals**: Set the number to **1** (or more if you want multiple reviewers) + - βœ… **Dismiss stale pull request approvals when new commits are pushed**: Recommended for security + - ⬜ **Require review from Code Owners**: Optional, but recommended since you have a CODEOWNERS file + - When enabled, at least one code owner (you, as defined in `.github/CODEOWNERS`) must approve + +βœ… **Require status checks to pass before merging** (Recommended) + - This ensures CI/CD checks pass before merging + - Search for and add the following checks: + - `build-and-test` (from CI workflow) + - `nodejs-tools` (from CI workflow) + - `security-scan` (from Security workflow) + - `codeql-analysis` (from Security workflow) + - βœ… **Require branches to be up to date before merging**: Ensures the branch is current with main + +#### Additional Recommended Options: + +βœ… **Require conversation resolution before merging** + - Ensures all review comments are addressed before merging + +βœ… **Do not allow bypassing the above settings** + - Prevents even admins from bypassing these rules + - ⚠️ Note: Unchecking this allows admins (you) to bypass if needed in emergencies + +βœ… **Restrict who can push to matching branches** (Optional) + - Can restrict push access to specific people, teams, or apps + - If you're the sole maintainer, this might not be necessary + +### 4. Save Changes + +1. Scroll to the bottom of the page +2. Click **Create** (or **Save changes** if editing an existing rule) + +## What This Accomplishes + +Once configured, the following will happen: + +1. βœ… **No direct pushes to main**: All changes must go through a pull request +2. βœ… **Review required**: You (or designated reviewers) must approve PRs before merging +3. βœ… **CI checks required**: All workflow checks must pass (build, test, security scans) +4. βœ… **Automatic reviewer assignment**: The CODEOWNERS file automatically assigns you as a reviewer +5. βœ… **Conversations resolved**: All review comments must be addressed + +## Testing the Setup + +To verify the branch protection is working: + +1. Create a new branch: `git checkout -b test-branch-protection` +2. Make a small change (e.g., update README.md) +3. Commit and push: `git add . && git commit -m "Test" && git push -u origin test-branch-protection` +4. Go to GitHub and create a pull request +5. Try to merge without approval β†’ Should be blocked +6. Approve the PR β†’ Should now be able to merge + +## CODEOWNERS File + +The `.github/CODEOWNERS` file in this repository automatically assigns you (`@mfrongillo35`) as a reviewer for all pull requests. This works in conjunction with branch protection rules. + +To modify who gets automatically assigned: +1. Edit `.github/CODEOWNERS` +2. Add or modify patterns and owners +3. Commit and push changes + +Example patterns: +``` +# All files +* @mfrongillo35 + +# Specific directories +/docs/ @mfrongillo35 @docs-team +/samples/ @mfrongillo35 @samples-team + +# Specific file types +*.md @mfrongillo35 @documentation-team +*.yml @mfrongillo35 @devops-team +``` + +## Alternative: Repository Rulesets (Beta) + +GitHub also offers Repository Rulesets, a newer feature that provides more flexibility: + +1. Go to **Settings** β†’ **Rules** β†’ **Rulesets** +2. Click **New ruleset** β†’ **New branch ruleset** +3. Name it (e.g., "Protect main branch") +4. Set **Target branches**: Add `main` +5. Configure rules similar to branch protection above +6. Set **Bypass list** if needed (to allow certain users/teams to bypass) +7. Click **Create** + +Rulesets offer advantages like: +- Better insights and rule evaluation +- More granular control +- Ability to target multiple branches with one ruleset + +## Troubleshooting + +### "I can't push to main" +βœ… **Expected behavior** - Create a pull request instead + +### "I can't merge my own PRs" +- As a repository admin, you can approve your own PRs by default +- If you want to require review from another user, you can: + - Add more collaborators to the repository + - Enable "Require review from Code Owners" and ensure CODEOWNERS includes other users + - Or create a second GitHub account for testing purposes +- Note: Branch protection can be configured to prevent self-approval with additional organization-level settings + +### "Status checks won't complete" +- Verify the workflow names match exactly +- Ensure workflows are enabled in Actions settings +- Check workflow runs for errors + +### "I need to make an emergency fix" +- If you enabled "Do not allow bypassing", you'll need to temporarily modify the rule +- Make the fix via PR, then re-enable strict rules + +## Additional Resources + +- [GitHub: About protected branches](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches) +- [GitHub: Managing a branch protection rule](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/managing-a-branch-protection-rule) +- [GitHub: About code owners](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners) +- [GitHub: About rulesets](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/about-rulesets) + +## Summary + +By following this guide, you'll have: +1. βœ… Created a CODEOWNERS file (already in this repo) +2. βœ… Configured branch protection rules via GitHub Settings +3. βœ… Ensured all PRs require your review before merging +4. βœ… Protected your main branch from direct pushes +5. βœ… Required CI/CD checks to pass before merging + +Your repository is now secure, and you maintain control over all changes to the main branch! πŸ”’ diff --git a/samples/DragonCopilot/Workflow/SampleExtension.Web/README.md b/samples/DragonCopilot/Workflow/SampleExtension.Web/README.md index dfcb1be..f08c6e6 100644 --- a/samples/DragonCopilot/Workflow/SampleExtension.Web/README.md +++ b/samples/DragonCopilot/Workflow/SampleExtension.Web/README.md @@ -28,6 +28,7 @@ A sample C# Web API project that demonstrates how to create an extension that ca - **Structured Logging**: Comprehensive logging for debugging and monitoring - **Error Handling**: Robust error handling with appropriate HTTP status codes - **Dockerfile**: Build your application as a container. +- **Manifest v3 Example**: The accompanying `extension.yaml` demonstrates automation scripts, event triggers, and dependency declarations required by the latest schema. ## API Endpoints @@ -39,7 +40,7 @@ A sample C# Web API project that demonstrates how to create an extension that ca ## Request/Response Examples -Example request and response models are available in the [requests](../../../requests) directory. +Example request and response models are available in the [requests](../../../requests) directory. Those samples align with the manifest v3 automation script and trigger metadata shipped with this project. ## Getting Started diff --git a/samples/DragonCopilot/Workflow/SampleExtension.Web/extension-package.zip b/samples/DragonCopilot/Workflow/SampleExtension.Web/extension-package.zip new file mode 100644 index 0000000..be88c2a Binary files /dev/null and b/samples/DragonCopilot/Workflow/SampleExtension.Web/extension-package.zip differ diff --git a/samples/DragonCopilot/Workflow/SampleExtension.Web/extension.yaml b/samples/DragonCopilot/Workflow/SampleExtension.Web/extension.yaml index 801eba2..a61303f 100644 --- a/samples/DragonCopilot/Workflow/SampleExtension.Web/extension.yaml +++ b/samples/DragonCopilot/Workflow/SampleExtension.Web/extension.yaml @@ -1,13 +1,16 @@ +manifestVersion: 3 name: sample-clinical-extraction description: Extracts certain clinical entities version: 0.0.1 +auth: + tenantId: 00000000-0000-0000-0000-000000000000 tools: - name: clinical-entity-extractor description: Extracts certain clinical entities endpoint: http://localhost:5181/v1/process inputs: - name: note - description: Note + description: Clinical note captured by Dragon Copilot data: DSP/Note outputs: - name: sample-entities @@ -16,3 +19,18 @@ tools: - name: adaptive-card description: Coded clinical entities in Adaptive Card format data: DSP +automationScripts: + - name: note-automation + description: Generates insights whenever a note is processed + entryPoint: scripts/analyze-note/index.js + runtime: nodejs18 + timeoutSeconds: 120 +eventTriggers: + - name: note-created + description: Runs the automation script when a new note arrives + eventType: note.created + scriptName: note-automation +dependencies: + - name: terminology-service + version: 1.0.0 + type: service diff --git a/samples/DragonCopilot/Workflow/partner.yaml b/samples/DragonCopilot/Workflow/partner.yaml new file mode 100644 index 0000000..1bcc598 --- /dev/null +++ b/samples/DragonCopilot/Workflow/partner.yaml @@ -0,0 +1,100 @@ +name: sample-partner +description: Dragon Copilot deep integration for sample-partner +version: 0.0.1 +partner-id: 5d0d3b72-2d47-4bf7-9091-8c7c3b03af84 +clinical-application-name: Sample Partner Clinical Application +server-authentication: + - issuer: https://auth.sample-partner.com/v2.0 + identity_claim: azp + identity_value: + - 8c2c91b9-1e4f-4b9d-9c27-a24f35e3f4dc + - 6aefb6a8-0f1a-45bd-bcf5-0cb1dd0cf9a4 + - issuer: https://auth-backup.sample-partner.com/v2.0 + identity_claim: azp + identity_value: + - 3c4fa8f2-6ca7-45c7-bd62-913df97ec9cd + - 7732f3dc-f7f4-4b04-8e5d-3b5639a34c84 +note-sections: + hpi: + - hpi + - chief-complaint + chief-complaint: + past-medical-history: + assessment: + - assessment + - plan + medications: + allergies: + review-of-systems: + physical-exam: physical-exam + procedures: procedures + results: results +instance: + client-authentication: + allow-multiple-issuers: yes + issuer: + access-token-issuer: + type: url + description: The value of the issuer claim for partner issued, user scoped access tokens. + default-value: https://auth.sample-partner.com/oauth2/v2.0 + required: yes + user-identity-claim: + type: string + description: Optional name of claim containing the EHR identity of an end user. Defaults to 'sub' if not collected. + default-value: sub + required: no + customer-identity-claim: + type: string + description: Optional name of claim containing the Microsoft environment ID. + default-value: http://customerid.dragon.com + required: no + web-launch-sof: + name: access-token-issuer + type: url + description: The value of the issuer claim when invoking the Dragon Copilot SMART on FHIR endpoint. + default-value: https://smart.sample-partner.com/oauth2 + required: yes + web-launch-token: + use-client-authentication: no + allow-multiple-issuers: yes + issuer: + - name: access-token-issuer + type: url + description: The value of the issuer claim for partner issued, user scoped access tokens. + default-value: https://auth.sample-partner.com/oauth2/v2.0 + required: yes + - name: user-identity-claim + type: string + description: Optional name of claim containing the EHR identity of an end user. Defaults to 'sub' if not collected. + default-value: sub + required: no + context-retrieval: + instance: + - name: base_url + type: url + description: Base URL needed for API calls. These are typically FHIR calls. + required: yes + - name: ehr-user_id + type: string + description: Optional EHR user id for FHIR API calls. + required: no + - name: in-bound-client-id + type: string + description: Credential for inbound calls to interop. + required: yes + - name: in-bound-issuer + type: url + description: Issuer claim of access tokens used by the partner to call Dragon Copilot Interop. + required: yes + - name: out-bound-issuer + type: url + description: Endpoint used to issue access tokens for Dragon Copilot Interop to call the partner. + required: yes + - name: out-bound-client-id + type: string + description: Partner provided client id to issue access tokens for Dragon Copilot Interop to call the partner. + required: yes + - name: out-bound-secret + type: string + description: Partner provided secret to issue access tokens for Dragon Copilot Interop to call the partner. + required: yes diff --git a/samples/requests/sample-requests-responses.md b/samples/requests/sample-requests-responses.md index 371beeb..8b30be1 100644 --- a/samples/requests/sample-requests-responses.md +++ b/samples/requests/sample-requests-responses.md @@ -1,6 +1,6 @@ # Sample Requests and Responses -This directory contains sample requests and responses for the Dragon Copilot extension. +This directory contains sample requests and responses for the Dragon Copilot extension. The examples align with the **manifest version 3** structure produced by the unified CLI. ## Sample Request: Note Payload @@ -10,10 +10,19 @@ This file contains a sample request payload for an extension that is configured Sample Manifest Configuration: ```yaml + manifestVersion: 3 inputs: - name: note description: Note data: DSP/Note + automationScripts: + - name: note-automation + entryPoint: scripts/analyze-note/index.js + runtime: nodejs18 + eventTriggers: + - name: note-created + eventType: note.created + scriptName: note-automation ``` ## Sample Response: Plugin Result @@ -28,4 +37,9 @@ Sample Manifest Configuration: - name: adaptive-card description: Response from the plugin data: DSP + + automationScripts: + - name: note-automation + entryPoint: scripts/analyze-note/index.js + runtime: nodejs18 ``` diff --git a/tools/dragon-copilot-cli/README.md b/tools/dragon-copilot-cli/README.md new file mode 100644 index 0000000..1343472 --- /dev/null +++ b/tools/dragon-copilot-cli/README.md @@ -0,0 +1,104 @@ +# Dragon Copilot CLI + +The `dragon-copilot` CLI unifies the legacy extension and partner tooling into a single package. It now targets **manifest version 3** so you can author manifests that describe automation scripts, event triggers, and extension dependencies alongside the traditional tool definitions. + +## Installation + +### Windows quick start + +To automate installation, build, and launch of the partner wizard on Windows, run the helper from the repo root: + +```powershell +pwsh ./tools/dragon-copilot-cli/scripts/setup-partner-cli.ps1 +``` + +Use `-SkipNodeInstall` to keep your existing Node.js installation or `-SkipBuild` when dependencies are already installed. + +### Manual install + +From the CLI folder: + +```powershell +npm install +npm run build +npm link +``` + +This exposes the `dragon-copilot` command globally for local development. + +### Refresh an existing global install + +If you already linked a previous version, relink to pick up the latest changes: + +```powershell +npm unlink -g dragon-copilot +npm link +``` + +Run `npm unlink -g dragon-copilot` only once per workstation; subsequent rebuilds just need `npm run build && npm link`. + +## Commands + +| Domain | Command Example | Description | +|------------|--------------------------------------------------------|-------------| +| Extension | `dragon-copilot extension init` | Interactive wizard that captures manifestVersion 3 data (automation scripts, event triggers, dependencies) and publisher configuration | +| Extension | `dragon-copilot extension validate ./extension.yaml` | Validates the manifest and optional `publisher.json` against JSON schema + business rules | +| Extension | `dragon-copilot extension package --manifest ./extension.yaml` | Produces a zip payload ready for distribution | +| Partner | `dragon-copilot partner init` | Restores the partner manifest wizard (note sections, context retrieval, authentication) | +| Partner | `dragon-copilot partner validate ./extension.yaml` | Validates partner manifests and publisher settings | + +Use `dragon-copilot --help` or `dragon-copilot --help` for additional options. + +During the partner wizard you will now confirm a **clinical application name**β€”typically the embedded EHR or workflow integration that issues user identities to Dragon Copilotβ€”so the manifest captures that metadata consistently. + +## HOWTO: Automation Script Scaffolding + +When you run `dragon-copilot extension init`, the wizard now includes an **automation script** section. + +1. **Enable Scripts** – choose "yes" when prompted to add automation scripts. The CLI will keep asking until you decline. +2. **Script Details** – provide: + - Script name (lowercase with hyphens) + - Optional description + - Entry point (relative path, e.g. `scripts/note/index.js`) + - Runtime (Node.js 18, Python 3.11, .NET 8) + - Optional timeout in seconds +3. **Event Triggers** – if scripts exist, the wizard asks whether to wire triggers: + - Trigger name, description, event type (e.g. `note.created`) + - Optional conditions (string expressions) + - Script selection (from scripts defined in step 2) +4. **Dependencies** – declare external services, extensions, or packages: + - Name and semantic version (minimum compatible version) + - Optional type (`service`, `extension`, `package`) + +The generated `extension.yaml` will include: + +```yaml +manifestVersion: 3 +automationScripts: + - name: example-script + entryPoint: scripts/example/index.js + runtime: nodejs18 + timeoutSeconds: 120 +eventTriggers: + - name: note-created + eventType: note.created + scriptName: example-script +dependencies: + - name: terminology-service + version: 1.0.0 + type: service +``` + +You can update scripts later via `dragon-copilot extension generate --interactive`, which reuses the same prompts while preserving existing values. + +## Development Notes + +- Shared helpers now live under `src/common`, keeping the CLI self-contained without external workspaces. +- `npm run build` emits compiled JS plus copies schemas/resources into `dist/`. +- `npm test` covers extension + partner flows (command registration, schema validation, CLI integration). + +## Troubleshooting + +- **CLI Not Found**: Ensure `npm link` completes without error and your Node install adds the npm global bin directory to PATH. +- **Process Exit during Tests**: Tests set `process.exitCode` and mock logging. If you add new commands, ensure they don’t call `process.exit()` directly in unit scenarios. +- **Schema Errors**: Check the `src/schemas/*.json` files for the latest manifest requirements. diff --git a/tools/dragon-copilot-cli/dist/cli.d.ts b/tools/dragon-copilot-cli/dist/cli.d.ts new file mode 100644 index 0000000..faaadd5 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/cli.d.ts @@ -0,0 +1,3 @@ +#!/usr/bin/env node +export {}; +//# sourceMappingURL=cli.d.ts.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/cli.d.ts.map b/tools/dragon-copilot-cli/dist/cli.d.ts.map new file mode 100644 index 0000000..f022439 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/cli.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/cli.js b/tools/dragon-copilot-cli/dist/cli.js new file mode 100644 index 0000000..032ac7f --- /dev/null +++ b/tools/dragon-copilot-cli/dist/cli.js @@ -0,0 +1,27 @@ +#!/usr/bin/env node +import { Command } from 'commander'; +import chalk from 'chalk'; +import { registerCommands } from './commands/index.js'; +const VERSION = '1.0.0'; +async function main() { + const program = new Command(); + program + .name('dragon-copilot') + .description('Unified CLI for Dragon Copilot extensions and integrations') + .version(VERSION); + registerCommands(program); + await program.parseAsync(); +} +main().catch(error => { + console.error(chalk.red('Unhandled CLI error:'), error); + process.exitCode = 1; +}); +process.on('unhandledRejection', (reason, promise) => { + console.error(chalk.red('Unhandled Rejection at:'), promise, chalk.red('reason:'), reason); + process.exit(1); +}); +process.on('uncaughtException', error => { + console.error(chalk.red('Uncaught Exception:'), error); + process.exit(1); +}); +//# sourceMappingURL=cli.js.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/cli.js.map b/tools/dragon-copilot-cli/dist/cli.js.map new file mode 100644 index 0000000..9c13b93 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/cli.js.map @@ -0,0 +1 @@ +{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD,MAAM,OAAO,GAAG,OAAO,CAAC;AAExB,KAAK,UAAU,IAAI;IAClB,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACL,IAAI,CAAC,gBAAgB,CAAC;SACtB,WAAW,CAAC,4DAA4D,CAAC;SACzE,OAAO,CAAC,OAAO,CAAC,CAAC;IAEnB,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAE1B,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC;AAC5B,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;IACpB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,sBAAsB,CAAC,EAAE,KAAK,CAAC,CAAC;IACxD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACtB,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;IACpD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,yBAAyB,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC;IAC3F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACjB,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAE,KAAK,CAAC,EAAE;IACvC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,qBAAqB,CAAC,EAAE,KAAK,CAAC,CAAC;IACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACjB,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/commands/index.d.ts b/tools/dragon-copilot-cli/dist/commands/index.d.ts new file mode 100644 index 0000000..d554956 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/commands/index.d.ts @@ -0,0 +1,3 @@ +import type { Command } from 'commander'; +export declare function registerCommands(program: Command): void; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/commands/index.d.ts.map b/tools/dragon-copilot-cli/dist/commands/index.d.ts.map new file mode 100644 index 0000000..3cb4815 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/commands/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAGvD"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/commands/index.js b/tools/dragon-copilot-cli/dist/commands/index.js new file mode 100644 index 0000000..60d3e8d --- /dev/null +++ b/tools/dragon-copilot-cli/dist/commands/index.js @@ -0,0 +1,7 @@ +import { registerExtensionCommands } from '../domains/extension/index.js'; +import { registerPartnerCommands } from '../domains/partner/index.js'; +export function registerCommands(program) { + registerExtensionCommands(program); + registerPartnerCommands(program); +} +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/commands/index.js.map b/tools/dragon-copilot-cli/dist/commands/index.js.map new file mode 100644 index 0000000..1eac2df --- /dev/null +++ b/tools/dragon-copilot-cli/dist/commands/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAEtE,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAChD,yBAAyB,CAAC,OAAO,CAAC,CAAC;IACnC,uBAAuB,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/common/assets.d.ts b/tools/dragon-copilot-cli/dist/common/assets.d.ts new file mode 100644 index 0000000..97f5fb3 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/common/assets.d.ts @@ -0,0 +1,12 @@ +export interface AssetBootstrapOptions { + assetsDirName?: string; + silent?: boolean; + overwrite?: boolean; +} +export interface AssetBootstrapResult { + assetsDir: string; + logoPath: string; + copied: boolean; +} +export declare function bootstrapAssetsDirectory(baseDir: string, options?: AssetBootstrapOptions): Promise; +//# sourceMappingURL=assets.d.ts.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/common/assets.d.ts.map b/tools/dragon-copilot-cli/dist/common/assets.d.ts.map new file mode 100644 index 0000000..c5c5c80 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/common/assets.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../src/common/assets.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,qBAAqB;IACpC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,oBAAoB,CAAC,CAoB/B"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/common/assets.js b/tools/dragon-copilot-cli/dist/common/assets.js new file mode 100644 index 0000000..8e7aa70 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/common/assets.js @@ -0,0 +1,32 @@ +import fs from 'fs-extra'; +import path from 'path'; +import { logMessage } from './logging.js'; +const SAMPLE_LOGO_BYTES = [ + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, + 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, 0x15, 0xc4, + 0x89, 0x00, 0x00, 0x00, 0x0a, 0x49, 0x44, 0x41, + 0x54, 0x78, 0x9c, 0x63, 0x00, 0x01, 0x00, 0x00, + 0x05, 0x00, 0x01, 0x0d, 0x0a, 0x2d, 0xb4, 0x00, + 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, + 0x42, 0x60, 0x82 +]; +export async function bootstrapAssetsDirectory(baseDir, options) { + const assetsDirName = options?.assetsDirName ?? 'assets'; + const silent = options?.silent ?? false; + const overwrite = options?.overwrite ?? true; + const assetsDir = path.join(baseDir, assetsDirName); + await fs.ensureDir(assetsDir); + const targetLogoPath = path.join(assetsDir, 'logo_large.png'); + const shouldWrite = overwrite || !(await fs.pathExists(targetLogoPath)); + if (shouldWrite) { + await fs.writeFile(targetLogoPath, Buffer.from(SAMPLE_LOGO_BYTES)); + logMessage(`βœ… Sample logo copied to ${assetsDirName}/logo_large.png`, silent); + logMessage('⚠️ Remember to replace this with your own logo before packaging!', silent); + return { assetsDir, logoPath: targetLogoPath, copied: true }; + } + logMessage(`ℹ️ Existing logo preserved at ${assetsDirName}/logo_large.png`, silent); + return { assetsDir, logoPath: targetLogoPath, copied: false }; +} +//# sourceMappingURL=assets.js.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/common/assets.js.map b/tools/dragon-copilot-cli/dist/common/assets.js.map new file mode 100644 index 0000000..603daa2 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/common/assets.js.map @@ -0,0 +1 @@ +{"version":3,"file":"assets.js","sourceRoot":"","sources":["../../src/common/assets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,iBAAiB,GAAG;IACxB,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;IAC9C,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;IAC9C,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;IAC9C,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;IAC9C,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;IAC9C,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;IAC9C,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;IAC9C,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;IAC9C,IAAI,EAAE,IAAI,EAAE,IAAI;CACjB,CAAC;AAcF,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,OAAe,EACf,OAA+B;IAE/B,MAAM,aAAa,GAAG,OAAO,EAAE,aAAa,IAAI,QAAQ,CAAC;IACzD,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,KAAK,CAAC;IACxC,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,IAAI,CAAC;IAE7C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IACpD,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAE9B,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAC9D,MAAM,WAAW,GAAG,SAAS,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,CAAC;IAExE,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,EAAE,CAAC,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACnE,UAAU,CAAC,2BAA2B,aAAa,iBAAiB,EAAE,MAAM,CAAC,CAAC;QAC9E,UAAU,CAAC,mEAAmE,EAAE,MAAM,CAAC,CAAC;QACxF,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAC/D,CAAC;IAED,UAAU,CAAC,kCAAkC,aAAa,iBAAiB,EAAE,MAAM,CAAC,CAAC;IACrF,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;AAChE,CAAC"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/common/index.d.ts b/tools/dragon-copilot-cli/dist/common/index.d.ts new file mode 100644 index 0000000..8912772 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/common/index.d.ts @@ -0,0 +1,5 @@ +export { logMessage } from './logging.js'; +export { validatePngLogo } from './logo.js'; +export { bootstrapAssetsDirectory } from './assets.js'; +export { promptPublisherDetails, type PublisherConfig, type PublisherPromptOptions, type PublisherPromptValidators, type PromptValidator } from './publisher.js'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/common/index.d.ts.map b/tools/dragon-copilot-cli/dist/common/index.d.ts.map new file mode 100644 index 0000000..0cc1e07 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/common/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/common/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EACL,sBAAsB,EACtB,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC9B,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/common/index.js b/tools/dragon-copilot-cli/dist/common/index.js new file mode 100644 index 0000000..814a407 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/common/index.js @@ -0,0 +1,5 @@ +export { logMessage } from './logging.js'; +export { validatePngLogo } from './logo.js'; +export { bootstrapAssetsDirectory } from './assets.js'; +export { promptPublisherDetails } from './publisher.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/common/index.js.map b/tools/dragon-copilot-cli/dist/common/index.js.map new file mode 100644 index 0000000..fe76b71 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/common/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/common/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EACL,sBAAsB,EAKvB,MAAM,gBAAgB,CAAC"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/common/logging.d.ts b/tools/dragon-copilot-cli/dist/common/logging.d.ts new file mode 100644 index 0000000..ea00ada --- /dev/null +++ b/tools/dragon-copilot-cli/dist/common/logging.d.ts @@ -0,0 +1,8 @@ +export type LogOptions = { + silent?: boolean; +}; +/** + * Writes a message to stdout unless running silently or in tests. + */ +export declare function logMessage(message: string, options?: LogOptions | boolean): void; +//# sourceMappingURL=logging.d.ts.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/common/logging.d.ts.map b/tools/dragon-copilot-cli/dist/common/logging.d.ts.map new file mode 100644 index 0000000..35e8a5b --- /dev/null +++ b/tools/dragon-copilot-cli/dist/common/logging.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../../src/common/logging.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,OAAO,GAAG,IAAI,CAkBhF"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/common/logging.js b/tools/dragon-copilot-cli/dist/common/logging.js new file mode 100644 index 0000000..bddcfc8 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/common/logging.js @@ -0,0 +1,15 @@ +/** + * Writes a message to stdout unless running silently or in tests. + */ +export function logMessage(message, options) { + const silent = typeof options === 'boolean' ? options : options?.silent ?? false; + if (silent) { + return; + } + const nodeEnv = globalThis.process?.env?.NODE_ENV; + if (nodeEnv === 'test') { + return; + } + console.log(message); +} +//# sourceMappingURL=logging.js.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/common/logging.js.map b/tools/dragon-copilot-cli/dist/common/logging.js.map new file mode 100644 index 0000000..1c33f47 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/common/logging.js.map @@ -0,0 +1 @@ +{"version":3,"file":"logging.js","sourceRoot":"","sources":["../../src/common/logging.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,OAAe,EAAE,OAA8B;IACzE,MAAM,MAAM,GAAG,OAAO,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,MAAM,IAAI,KAAK,CAAC;IAEjF,IAAI,MAAM,EAAE,CAAC;QACZ,OAAO;IACR,CAAC;IAED,MAAM,OAAO,GAAI,UAIf,CAAC,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC;IAE1B,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACxB,OAAO;IACR,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACtB,CAAC"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/common/logo.d.ts b/tools/dragon-copilot-cli/dist/common/logo.d.ts new file mode 100644 index 0000000..952b7f6 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/common/logo.d.ts @@ -0,0 +1,5 @@ +export interface LogoValidationOptions { + silent?: boolean; +} +export declare function validatePngLogo(logoPath: string, options?: LogoValidationOptions): Promise; +//# sourceMappingURL=logo.d.ts.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/common/logo.d.ts.map b/tools/dragon-copilot-cli/dist/common/logo.d.ts.map new file mode 100644 index 0000000..3038598 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/common/logo.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"logo.d.ts","sourceRoot":"","sources":["../../src/common/logo.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,OAAO,CAAC,CAsCzG"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/common/logo.js b/tools/dragon-copilot-cli/dist/common/logo.js new file mode 100644 index 0000000..24d7aa2 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/common/logo.js @@ -0,0 +1,38 @@ +import fs from 'fs-extra'; +import chalk from 'chalk'; +import { logMessage } from './logging.js'; +export async function validatePngLogo(logoPath, options) { + const silent = options?.silent ?? false; + if (!(await fs.pathExists(logoPath))) { + return false; + } + try { + const stats = await fs.stat(logoPath); + if (stats.size === 0) { + logMessage(chalk.red(`❌ Logo file is empty: ${logoPath}`), silent); + return false; + } + const buffer = await fs.readFile(logoPath); + const isPNG = buffer.length >= 8 && + buffer[0] === 0x89 && + buffer[1] === 0x50 && + buffer[2] === 0x4e && + buffer[3] === 0x47 && + buffer[4] === 0x0d && + buffer[5] === 0x0a && + buffer[6] === 0x1a && + buffer[7] === 0x0a; + if (!isPNG) { + logMessage(chalk.red(`❌ Logo file is not a valid PNG: ${logoPath}`), silent); + return false; + } + logMessage(chalk.gray(`βœ“ Logo validation passed: ${logoPath}`), silent); + return true; + } + catch (error) { + const message = error instanceof Error ? error.message : 'Unknown error'; + logMessage(chalk.red(`❌ Error validating logo: ${message}`), silent); + return false; + } +} +//# sourceMappingURL=logo.js.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/common/logo.js.map b/tools/dragon-copilot-cli/dist/common/logo.js.map new file mode 100644 index 0000000..686bfbc --- /dev/null +++ b/tools/dragon-copilot-cli/dist/common/logo.js.map @@ -0,0 +1 @@ +{"version":3,"file":"logo.js","sourceRoot":"","sources":["../../src/common/logo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAM1C,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,QAAgB,EAAE,OAA+B;IACrF,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,KAAK,CAAC;IAExC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;QACrC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtC,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACrB,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,yBAAyB,QAAQ,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;YACnE,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC3C,MAAM,KAAK,GACT,MAAM,CAAC,MAAM,IAAI,CAAC;YAClB,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI;YAClB,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI;YAClB,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI;YAClB,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI;YAClB,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI;YAClB,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI;YAClB,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI;YAClB,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;QAErB,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,mCAAmC,QAAQ,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;YAC7E,OAAO,KAAK,CAAC;QACf,CAAC;QAED,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,6BAA6B,QAAQ,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;QACxE,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;QACzE,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,4BAA4B,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;QACrE,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/common/publisher.d.ts b/tools/dragon-copilot-cli/dist/common/publisher.d.ts new file mode 100644 index 0000000..1be46b1 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/common/publisher.d.ts @@ -0,0 +1,36 @@ +export interface PublisherConfig { + publisherId: string; + publisherName: string; + websiteUrl: string; + privacyPolicyUrl: string; + supportUrl: string; + version: string; + contactEmail: string; + offerId: string; + defaultLocale: string; + supportedLocales: string[]; + scope: string; + regions: string[]; +} +export type PromptValidator = (value: string) => string | boolean; +export interface PublisherPromptValidators { + publisherId?: PromptValidator; + publisherName?: PromptValidator; + websiteUrl?: PromptValidator; + privacyPolicyUrl?: PromptValidator; + supportUrl?: PromptValidator; + version?: PromptValidator; + contactEmail?: PromptValidator; + offerId?: PromptValidator; +} +export interface PublisherPromptOptions { + defaults?: Partial; + validators?: PublisherPromptValidators; + scope?: string; + defaultLocale?: string; + supportedLocales?: string[]; + regions?: string[]; + offerIdGenerator?: (publisherId: string) => string | undefined; +} +export declare function promptPublisherDetails(options?: PublisherPromptOptions): Promise; +//# sourceMappingURL=publisher.d.ts.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/common/publisher.d.ts.map b/tools/dragon-copilot-cli/dist/common/publisher.d.ts.map new file mode 100644 index 0000000..a23e162 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/common/publisher.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"publisher.d.ts","sourceRoot":"","sources":["../../src/common/publisher.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,OAAO,CAAC;AAElE,MAAM,WAAW,yBAAyB;IACxC,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,aAAa,CAAC,EAAE,eAAe,CAAC;IAChC,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,gBAAgB,CAAC,EAAE,eAAe,CAAC;IACnC,UAAU,CAAC,EAAE,eAAe,CAAC;IAC7B,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,YAAY,CAAC,EAAE,eAAe,CAAC;IAC/B,OAAO,CAAC,EAAE,eAAe,CAAC;CAC3B;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IACpC,UAAU,CAAC,EAAE,yBAAyB,CAAC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,gBAAgB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAChE;AAqCD,wBAAsB,sBAAsB,CAAC,OAAO,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,eAAe,CAAC,CA8EvG"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/common/publisher.js b/tools/dragon-copilot-cli/dist/common/publisher.js new file mode 100644 index 0000000..a6a3d85 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/common/publisher.js @@ -0,0 +1,97 @@ +import { input } from '@inquirer/prompts'; +const withDefault = (value) => value !== undefined ? { default: value } : {}; +const requiredField = value => (value.trim() ? true : 'This field is required'); +const emailValidator = value => { + if (!value.trim()) { + return 'This field is required'; + } + const pattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return pattern.test(value) ? true : 'Please enter a valid email address'; +}; +const urlValidator = value => { + if (!value.trim()) { + return 'This field is required'; + } + try { + new URL(value); + return true; + } + catch { + return 'Please enter a valid URL (e.g., https://example.com)'; + } +}; +const versionValidator = value => { + if (!value.trim()) { + return 'Version is required'; + } + return /^\d+\.\d+\.\d+$/.test(value) ? true : 'Version must be in format x.y.z (e.g., 1.0.0)'; +}; +export async function promptPublisherDetails(options) { + const defaults = options?.defaults ?? {}; + const validators = { + publisherId: options?.validators?.publisherId ?? requiredField, + publisherName: options?.validators?.publisherName ?? requiredField, + websiteUrl: options?.validators?.websiteUrl ?? urlValidator, + privacyPolicyUrl: options?.validators?.privacyPolicyUrl ?? urlValidator, + supportUrl: options?.validators?.supportUrl ?? urlValidator, + version: options?.validators?.version ?? versionValidator, + contactEmail: options?.validators?.contactEmail ?? emailValidator, + offerId: options?.validators?.offerId ?? requiredField + }; + const publisherId = await input({ + message: 'Publisher ID (e.g., contoso.healthcare):', + ...withDefault(defaults.publisherId), + validate: validators.publisherId + }); + const publisherName = await input({ + message: 'Publisher Name:', + ...withDefault(defaults.publisherName), + validate: validators.publisherName + }); + const websiteUrl = await input({ + message: 'Website URL:', + ...withDefault(defaults.websiteUrl), + validate: validators.websiteUrl + }); + const privacyPolicyUrl = await input({ + message: 'Privacy Policy URL:', + ...withDefault(defaults.privacyPolicyUrl), + validate: validators.privacyPolicyUrl + }); + const supportUrl = await input({ + message: 'Support URL:', + ...withDefault(defaults.supportUrl), + validate: validators.supportUrl + }); + const version = await input({ + message: 'Publisher Config Version:', + default: defaults.version ?? '0.0.1', + validate: validators.version + }); + const contactEmail = await input({ + message: 'Contact Email:', + ...withDefault(defaults.contactEmail), + validate: validators.contactEmail + }); + const offerIdDefault = defaults.offerId ?? options?.offerIdGenerator?.(publisherId) ?? `${publisherId.split('.')[0]}-suite`; + const offerId = await input({ + message: 'Offer ID:', + default: offerIdDefault, + validate: validators.offerId + }); + return { + publisherId, + publisherName, + websiteUrl, + privacyPolicyUrl, + supportUrl, + version, + contactEmail, + offerId, + defaultLocale: options?.defaultLocale ?? defaults.defaultLocale ?? 'en-US', + supportedLocales: options?.supportedLocales ?? defaults.supportedLocales ?? ['en-US'], + scope: options?.scope ?? defaults.scope ?? 'Workflow', + regions: options?.regions ?? defaults.regions ?? ['US'] + }; +} +//# sourceMappingURL=publisher.js.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/common/publisher.js.map b/tools/dragon-copilot-cli/dist/common/publisher.js.map new file mode 100644 index 0000000..370a07b --- /dev/null +++ b/tools/dragon-copilot-cli/dist/common/publisher.js.map @@ -0,0 +1 @@ +{"version":3,"file":"publisher.js","sourceRoot":"","sources":["../../src/common/publisher.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/domains/extension/commands/generate.d.ts b/tools/dragon-copilot-cli/dist/domains/extension/commands/generate.d.ts new file mode 100644 index 0000000..850a290 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/domains/extension/commands/generate.d.ts @@ -0,0 +1,3 @@ +import type { GenerateOptions } from '../types.js'; +export declare function generateManifest(options: GenerateOptions): Promise; +//# sourceMappingURL=generate.d.ts.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/domains/extension/commands/generate.d.ts.map b/tools/dragon-copilot-cli/dist/domains/extension/commands/generate.d.ts.map new file mode 100644 index 0000000..94af3df --- /dev/null +++ b/tools/dragon-copilot-cli/dist/domains/extension/commands/generate.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../../src/domains/extension/commands/generate.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAuC,MAAM,aAAa,CAAC;AAIxF,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAW9E"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/domains/extension/commands/generate.js b/tools/dragon-copilot-cli/dist/domains/extension/commands/generate.js new file mode 100644 index 0000000..c297a5c --- /dev/null +++ b/tools/dragon-copilot-cli/dist/domains/extension/commands/generate.js @@ -0,0 +1,151 @@ +import fs from 'fs-extra'; +const { readFileSync, writeFileSync, existsSync } = fs; +import yaml from 'js-yaml'; +const { load, dump } = yaml; +import chalk from 'chalk'; +import { confirm } from '@inquirer/prompts'; +import { getTemplate } from '../templates/index.js'; +import { promptToolDetails, promptPublisherDetails, promptAuthDetails, getInputDescription } from '../shared/prompts.js'; +export async function generateManifest(options) { + console.log(chalk.blue('πŸ‰ Generating Dragon Copilot Manifest')); + if (options.interactive) { + await generateInteractive(options); + } + else if (options.template) { + await generateFromTemplate(options); + } + else { + console.log(chalk.red('❌ Please specify either --template or --interactive')); + process.exit(1); + } +} +async function generateInteractive(options) { + console.log(chalk.gray('Interactive manifest generation...\n')); + // Check if manifest already exists + let existingManifest = null; + try { + const existing = readFileSync(options.output || 'extension.yaml', 'utf8'); + existingManifest = load(existing); + console.log(chalk.yellow('πŸ“„ Found existing manifest, will add to it')); + } + catch { + // File doesn't exist, create new + } + // Check for publisher.json and offer to create/update it + const publisherPath = 'publisher.json'; + const publisherExists = existsSync(publisherPath); + if (!publisherExists) { + const createPublisher = await confirm({ + message: 'No publisher.json found. Create publisher configuration?', + default: true + }); + if (createPublisher) { + console.log(chalk.blue('\nπŸ“‹ Publisher Configuration')); + const publisherConfig = await promptPublisherDetails(); + writeFileSync(publisherPath, JSON.stringify(publisherConfig, null, 2)); + console.log(chalk.green('βœ… Publisher configuration created!')); + } + } + else { + const updatePublisher = await confirm({ + message: 'Update existing publisher.json?', + default: false + }); + if (updatePublisher) { + console.log(chalk.blue('\nπŸ“‹ Updating Publisher Configuration')); + try { + const existingPublisher = JSON.parse(readFileSync(publisherPath, 'utf8')); + const publisherConfig = await promptPublisherDetails(existingPublisher); + writeFileSync(publisherPath, JSON.stringify(publisherConfig, null, 2)); + console.log(chalk.green('βœ… Publisher configuration updated!')); + } + catch (error) { + console.log(chalk.yellow('⚠️ Could not parse existing publisher.json, creating new one')); + const publisherConfig = await promptPublisherDetails(); + writeFileSync(publisherPath, JSON.stringify(publisherConfig, null, 2)); + } + } + } + // Use shared prompt logic + const answers = await promptToolDetails(existingManifest); + const newTool = { + name: answers.toolName, + description: answers.toolDescription, + endpoint: answers.endpoint, + inputs: answers.inputTypes.map((dataType, index) => ({ + name: dataType === 'DSP/Note' ? 'note' : + dataType === 'DSP/IterativeTranscript' ? 'iterative-transcript' : + dataType === 'DSP/IterativeAudio' ? 'iterative-audio' : + dataType === 'DSP/Transcript' ? 'transcript' : + `input-${index + 1}`, + description: getInputDescription(dataType), + data: dataType + })), + outputs: answers.outputs + }; + let manifest; + if (existingManifest) { + manifest = existingManifest; + manifest.tools.push(newTool); + } + else { + // For new manifests, collect auth details + console.log(chalk.blue('\nπŸ” Authentication Configuration')); + console.log(chalk.gray('New manifest requires authentication configuration.\n')); + const authDetails = await promptAuthDetails(); + manifest = { + manifestVersion: 3, + name: 'my-extension', + description: 'A Dragon Copilot extension', + version: '0.0.1', + auth: { + tenantId: authDetails.tenantId + }, + tools: [newTool], + automationScripts: [], + eventTriggers: [], + dependencies: [] + }; + } + const yamlContent = dump(manifest, { lineWidth: -1 }); + writeFileSync(options.output || 'extension.yaml', yamlContent); + console.log(chalk.green('\nβœ… Tool added to manifest successfully!')); + console.log(chalk.gray(`πŸ“ Manifest saved to: ${options.output || 'extension.yaml'}`)); +} +async function generateFromTemplate(options) { + if (!options.template) { + console.log(chalk.red('❌ Template name is required')); + return; + } + try { + const template = getTemplate(options.template); + const yamlContent = dump(template, { lineWidth: -1 }); + writeFileSync(options.output || 'extension.yaml', yamlContent); + console.log(chalk.green(`βœ… Manifest generated from template: ${options.template}`)); + console.log(chalk.gray(`πŸ“ Manifest saved to: ${options.output || 'extension.yaml'}`)); + // Offer to create publisher.json for template-based generation + const publisherPath = 'publisher.json'; + const publisherExists = existsSync(publisherPath); + if (!publisherExists) { + const createPublisher = await confirm({ + message: 'Create publisher configuration file (publisher.json)?', + default: true + }); + if (createPublisher) { + console.log(chalk.blue('\nπŸ“‹ Publisher Configuration')); + const publisherConfig = await promptPublisherDetails(); + writeFileSync(publisherPath, JSON.stringify(publisherConfig, null, 2)); + console.log(chalk.green('βœ… Publisher configuration created!')); + } + } + } + catch (error) { + if (error instanceof Error) { + console.log(chalk.red(`❌ Error generating from template: ${error.message}`)); + } + else { + console.log(chalk.red('❌ Unknown error occurred while generating from template')); + } + } +} +//# sourceMappingURL=generate.js.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/domains/extension/commands/generate.js.map b/tools/dragon-copilot-cli/dist/domains/extension/commands/generate.js.map new file mode 100644 index 0000000..b7c50af --- /dev/null +++ b/tools/dragon-copilot-cli/dist/domains/extension/commands/generate.js.map @@ -0,0 +1 @@ +{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../../src/domains/extension/commands/generate.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/domains/extension/commands/init.d.ts b/tools/dragon-copilot-cli/dist/domains/extension/commands/init.d.ts new file mode 100644 index 0000000..99f0643 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/domains/extension/commands/init.d.ts @@ -0,0 +1,3 @@ +import type { InitOptions } from '../types.js'; +export declare function initProject(options: InitOptions): Promise; +//# sourceMappingURL=init.d.ts.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/domains/extension/commands/init.d.ts.map b/tools/dragon-copilot-cli/dist/domains/extension/commands/init.d.ts.map new file mode 100644 index 0000000..8780edd --- /dev/null +++ b/tools/dragon-copilot-cli/dist/domains/extension/commands/init.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../src/domains/extension/commands/init.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,WAAW,EAKZ,MAAM,aAAa,CAAC;AAYrB,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAuQrE"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/domains/extension/commands/init.js b/tools/dragon-copilot-cli/dist/domains/extension/commands/init.js new file mode 100644 index 0000000..a649999 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/domains/extension/commands/init.js @@ -0,0 +1,228 @@ +import { confirm } from '@inquirer/prompts'; +import fs from 'fs-extra'; +const { writeFileSync } = fs; +import yaml from 'js-yaml'; +const { dump } = yaml; +import path from 'path'; +import chalk from 'chalk'; +import { bootstrapAssetsDirectory } from '../../../common/index.js'; +import { promptExtensionDetails, promptToolDetails, promptPublisherDetails, promptAuthDetails, promptAutomationScriptDetails, promptEventTriggerDetails, promptDependencyDetails, getInputDescription } from '../shared/prompts.js'; +export async function initProject(options) { + console.log(chalk.blue('πŸ‰ Dragon Copilot Extension Generator')); + console.log(chalk.gray('Initializing a new extension project...\n')); + // Step 1: Extension Details + console.log(chalk.blue('πŸ“ Step 1: Extension Details')); + console.log(chalk.gray('Let\'s start with basic information about your extension.\n')); + const extensionDetails = await promptExtensionDetails({ + ...(options.name ? { name: options.name } : {}), + ...(options.description ? { description: options.description } : {}), + ...(options.version ? { version: options.version } : {}) + }); + // Step 2: Authentication Configuration + console.log(chalk.blue('\nπŸ” Step 2: Authentication Configuration')); + console.log(chalk.gray('Configure Azure Entra ID authentication for your extension.\n')); + const authDetails = await promptAuthDetails(); + // Step 3: Publisher Configuration + console.log(chalk.blue('\nπŸ“‹ Step 3: Publisher Configuration')); + console.log(chalk.gray('Publisher information is required for deployment and marketplace listing.')); + console.log(chalk.gray('This creates a separate publisher.json file that can be reused across extensions.\n')); + const createPublisherConfig = await confirm({ + message: 'Create publisher configuration file (publisher.json)?', + default: true + }); + let publisherConfig = null; + if (createPublisherConfig) { + publisherConfig = await promptPublisherDetails(); + } + // Step 4: Assets Setup + console.log(chalk.blue('\n🎨 Step 4: Assets Setup')); + console.log(chalk.gray('Extensions require a large logo (216x216 to 350x350 px) for marketplace listing.')); + console.log(chalk.gray('We\'ll create an assets directory with a sample logo to get you started.\n')); + const setupAssets = await confirm({ + message: 'Create assets directory with sample logo?', + default: true + }); + if (setupAssets) { + await bootstrapAssetsDirectory(options.output || '.', { + assetsDirName: 'assets' + }); + } + // Step 5: Extension Tools + console.log(chalk.blue('\nπŸ› οΈ Step 5: Extension Tools')); + console.log(chalk.gray('Tools define the AI-powered functionality your extension provides.')); + console.log(chalk.gray('Each tool processes specific types of clinical data and returns results.\n')); + const addTool = await confirm({ + message: 'Add an initial tool?', + default: true + }); + const manifest = { + manifestVersion: 3, + name: extensionDetails.name, + description: extensionDetails.description, + version: extensionDetails.version, + auth: { + tenantId: authDetails.tenantId + }, + tools: [] + }; + if (addTool) { + // Use shared prompt for tool details (single input for init) + const toolDetails = await promptToolDetails(undefined, { + allowMultipleInputs: true, // Allow multiple inputs for flexibility + defaults: { + toolName: 'my-tool', + toolDescription: 'Processes clinical data', + endpoint: 'https://api.example.com/tool-route/v1/process' + } + }); + manifest.tools.push({ + name: toolDetails.toolName, + description: toolDetails.toolDescription, + endpoint: toolDetails.endpoint, + inputs: toolDetails.inputTypes.map((dataType, index) => ({ + name: dataType === 'DSP/Note' ? 'note' : + dataType === 'DSP/IterativeTranscript' ? 'iterative-transcript' : + dataType === 'DSP/IterativeAudio' ? 'iterative-audio' : + dataType === 'DSP/Transcript' ? 'transcript' : + `input-${index + 1}`, + description: getInputDescription(dataType), + data: dataType + })), + outputs: toolDetails.outputs + }); + } + const automationScripts = []; + const configureAutomationScripts = await confirm({ + message: 'Add automation scripts for your extension?', + default: false + }); + if (configureAutomationScripts) { + let addAnotherScript = true; + while (addAnotherScript) { + const scriptDetails = await promptAutomationScriptDetails(automationScripts); + const script = { + name: scriptDetails.name, + entryPoint: scriptDetails.entryPoint, + runtime: scriptDetails.runtime + }; + if (scriptDetails.description) { + script.description = scriptDetails.description; + } + if (typeof scriptDetails.timeoutSeconds === 'number') { + script.timeoutSeconds = scriptDetails.timeoutSeconds; + } + automationScripts.push(script); + addAnotherScript = await confirm({ + message: 'Add another automation script?', + default: false + }); + } + } + if (automationScripts.length > 0) { + manifest.automationScripts = automationScripts; + } + const eventTriggers = []; + if (automationScripts.length > 0) { + const configureEventTriggers = await confirm({ + message: 'Configure event triggers that call automation scripts?', + default: true + }); + if (configureEventTriggers) { + let addAnotherTrigger = true; + while (addAnotherTrigger) { + const triggerDetails = await promptEventTriggerDetails(eventTriggers, automationScripts); + const trigger = { + name: triggerDetails.name, + eventType: triggerDetails.eventType, + scriptName: triggerDetails.scriptName + }; + if (triggerDetails.description) { + trigger.description = triggerDetails.description; + } + if (triggerDetails.conditions) { + trigger.conditions = triggerDetails.conditions; + } + eventTriggers.push(trigger); + addAnotherTrigger = await confirm({ + message: 'Add another event trigger?', + default: false + }); + } + } + } + if (eventTriggers.length > 0) { + manifest.eventTriggers = eventTriggers; + } + const dependencies = []; + const addDependencies = await confirm({ + message: 'Declare external dependencies?', + default: false + }); + if (addDependencies) { + let addAnotherDependency = true; + while (addAnotherDependency) { + const dependencyDetails = await promptDependencyDetails(dependencies); + const dependency = { + name: dependencyDetails.name, + version: dependencyDetails.version + }; + if (dependencyDetails.type) { + dependency.type = dependencyDetails.type; + } + dependencies.push(dependency); + addAnotherDependency = await confirm({ + message: 'Add another dependency?', + default: false + }); + } + } + if (dependencies.length > 0) { + manifest.dependencies = dependencies; + } + const outputPath = path.join(options.output || '.', 'extension.yaml'); + const yamlContent = dump(manifest, { lineWidth: -1 }); + writeFileSync(outputPath, yamlContent); + // Create publisher.json if requested + if (publisherConfig) { + const publisherPath = path.join(options.output || '.', 'publisher.json'); + writeFileSync(publisherPath, JSON.stringify(publisherConfig, null, 2)); + console.log(chalk.green('\nβœ… Publisher configuration created successfully!')); + console.log(chalk.gray(`πŸ“ Publisher config created at: ${publisherPath}`)); + } + console.log(chalk.green('\nβœ… Extension project initialized successfully!')); + console.log(chalk.gray(`πŸ“ Manifest created at: ${outputPath}`)); + if (setupAssets) { + console.log(chalk.gray(`🎨 Assets directory created at: assets/`)); + } + // Enhanced next steps with better organization + console.log(chalk.blue('\n🎯 What\'s Next?')); + if (setupAssets) { + console.log(chalk.yellow('🎨 Logo Requirements:')); + console.log(chalk.gray(' β€’ Replace assets/logo_large.png with your own logo')); + console.log(chalk.gray(' β€’ Size: 216x216 to 350x350 pixels (PNG format)')); + console.log(chalk.gray(' β€’ This will be used to generate Medium (90x90) and Small (48x48) logos')); + } + if (addTool) { + console.log(chalk.yellow('οΏ½ Development Steps:')); + console.log(chalk.gray(' 1. Update the endpoint URL with your actual API')); + console.log(chalk.gray(' 2. Customize inputs and outputs as needed')); + console.log(chalk.gray(' 3. Test your extension locally')); + if (publisherConfig) { + console.log(chalk.yellow('\nπŸ“¦ Deployment Steps:')); + console.log(chalk.gray(' 1. Review and update publisher configuration')); + console.log(chalk.gray(' 2. Package your extension: dragon-copilot extension package')); + console.log(chalk.gray(' 3. Deploy to the marketplace')); + } + } + else { + console.log(chalk.yellow('πŸ”§ Next Steps:')); + console.log(chalk.gray(' 1. Add tools to your extension: dragon-copilot extension generate --interactive')); + console.log(chalk.gray(' 2. Update the manifest with your API endpoints')); + console.log(chalk.gray(' 3. Test and package your extension')); + } + console.log(chalk.blue('\nπŸ“š Resources:')); + console.log(chalk.gray(' β€’ Validate your extension: dragon-copilot extension validate')); + console.log(chalk.gray(' β€’ Add more tools: dragon-copilot extension generate --interactive')); + console.log(chalk.gray(' β€’ Package for deployment: dragon-copilot extension package')); +} +//# sourceMappingURL=init.js.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/domains/extension/commands/init.js.map b/tools/dragon-copilot-cli/dist/domains/extension/commands/init.js.map new file mode 100644 index 0000000..4075e63 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/domains/extension/commands/init.js.map @@ -0,0 +1 @@ +{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../../src/domains/extension/commands/init.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/domains/extension/commands/package.d.ts b/tools/dragon-copilot-cli/dist/domains/extension/commands/package.d.ts new file mode 100644 index 0000000..cd49c95 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/domains/extension/commands/package.d.ts @@ -0,0 +1,3 @@ +import type { PackageOptions } from '../types.js'; +export declare function packageExtension(options: PackageOptions): Promise; +//# sourceMappingURL=package.d.ts.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/domains/extension/commands/package.d.ts.map b/tools/dragon-copilot-cli/dist/domains/extension/commands/package.d.ts.map new file mode 100644 index 0000000..1758292 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/domains/extension/commands/package.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"package.d.ts","sourceRoot":"","sources":["../../../../src/domains/extension/commands/package.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAA4C,MAAM,aAAa,CAAC;AAI5F,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA6M7E"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/domains/extension/commands/package.js b/tools/dragon-copilot-cli/dist/domains/extension/commands/package.js new file mode 100644 index 0000000..41bfae4 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/domains/extension/commands/package.js @@ -0,0 +1,189 @@ +import fs from 'fs-extra'; +const { readFileSync, createWriteStream, pathExists } = fs; +import yaml from 'js-yaml'; +const { load } = yaml; +import archiver from 'archiver'; +import path from 'path'; +import chalk from 'chalk'; +import { logMessage, validatePngLogo } from '../../../common/index.js'; +import { validateExtensionManifest, validatePublisherConfig } from '../shared/schema-validator.js'; +export async function packageExtension(options) { + const isQuiet = options.silent || process.env.NODE_ENV === 'test'; + logMessage(chalk.blue('πŸ‰ Packaging Dragon Copilot Extension'), isQuiet); + const manifestPath = options.manifest || 'extension.yaml'; + const publisherPath = 'publisher.json'; + const logoPath = 'assets/logo_large.png'; + // Step 1: Validate required files exist + logMessage(chalk.blue('πŸ“‹ Validating required files...'), isQuiet); + if (!(await pathExists(manifestPath))) { + logMessage(chalk.red(`❌ Extension manifest not found: ${manifestPath}`), isQuiet); + logMessage(chalk.gray(' Create one using: dragon-copilot extension init'), isQuiet); + throw new Error(`Extension manifest not found: ${manifestPath}`); + } + if (!(await pathExists(publisherPath))) { + logMessage(chalk.red(`❌ Publisher configuration not found: ${publisherPath}`), isQuiet); + logMessage(chalk.gray(' A publisher.json file is required for packaging'), isQuiet); + logMessage(chalk.gray(' Create one using: dragon-copilot extension init --with-publisher'), isQuiet); + throw new Error(`Publisher configuration not found: ${publisherPath}`); + } + // Step 1.5: Validate required logo + logMessage(chalk.blue('🎨 Validating logo requirements...'), isQuiet); + if (!(await pathExists(logoPath))) { + logMessage(chalk.red(`❌ Required logo not found: ${logoPath}`), isQuiet); + logMessage(chalk.gray(' A large logo (PNG, 216x216 to 350x350 px) is required for packaging'), isQuiet); + logMessage(chalk.gray(' Create assets directory with logo using: dragon-copilot extension init'), isQuiet); + throw new Error(`Required logo not found: ${logoPath}`); + } + const isValidLogo = await validatePngLogo(logoPath, { silent: isQuiet }); + if (!isValidLogo) { + logMessage(chalk.red(`❌ Logo validation failed: ${logoPath}`), isQuiet); + logMessage(chalk.gray(' Requirements: PNG file, 216x216 to 350x350 pixels'), isQuiet); + throw new Error(`Logo validation failed: ${logoPath}`); + } + logMessage(chalk.gray(`βœ“ Found extension manifest: ${manifestPath}`), isQuiet); + logMessage(chalk.gray(`βœ“ Found publisher configuration: ${publisherPath}`), isQuiet); + logMessage(chalk.gray(`βœ“ Found required logo: ${logoPath}`), isQuiet); + try { + // Step 2: Validate extension manifest + logMessage(chalk.blue('\nπŸ“‹ Validating extension manifest...'), isQuiet); + const manifestContent = readFileSync(manifestPath, 'utf8'); + const manifest = load(manifestContent); + const manifestValidation = validateExtensionManifest(manifest); + if (!manifestValidation.isValid) { + logMessage(chalk.red('❌ Extension manifest validation failed:'), isQuiet); + manifestValidation.errors.forEach((error) => { + const fieldPath = error.instancePath.replace(/^\//, '').replace(/\//g, '.'); + const fieldName = fieldPath || 'manifest'; + logMessage(chalk.red(` β€’ ${fieldName}: ${error.message}`), isQuiet); + }); + throw new Error('Extension manifest validation failed'); + } + logMessage(chalk.green('βœ… Extension manifest is valid'), isQuiet); + // Step 3: Validate publisher configuration + logMessage(chalk.blue('πŸ“‹ Validating publisher configuration...'), isQuiet); + let publisherConfig; + try { + const publisherContent = readFileSync(publisherPath, 'utf8'); + publisherConfig = JSON.parse(publisherContent); + } + catch (parseError) { + logMessage(chalk.red('❌ Failed to parse publisher.json:'), isQuiet); + if (parseError instanceof Error) { + logMessage(chalk.red(` ${parseError.message}`), isQuiet); + } + throw new Error('Failed to parse publisher.json'); + } + const publisherValidation = validatePublisherConfig(publisherConfig); + if (!publisherValidation.isValid) { + logMessage(chalk.red('❌ Publisher configuration validation failed:'), isQuiet); + publisherValidation.errors.forEach((error) => { + const fieldPath = error.instancePath.replace(/^\//, '').replace(/\//g, '.'); + const fieldName = fieldPath || 'config'; + logMessage(chalk.red(` β€’ ${fieldName}: ${error.message}`), isQuiet); + }); + throw new Error('Publisher configuration validation failed'); + } + logMessage(chalk.green('βœ… Publisher configuration is valid'), isQuiet); + // Step 4: Create package + const outputPath = options.output || `${manifest.name}-${manifest.version}.zip`; + logMessage(chalk.blue(`\nπŸ“¦ Creating package: ${outputPath}`), isQuiet); + logMessage(chalk.gray(`🏒 Publisher: ${publisherConfig.publisherName} (${publisherConfig.publisherId})`), isQuiet); + logMessage(chalk.gray(`πŸ“„ Extension: ${manifest.name} v${manifest.version}`), isQuiet); + logMessage(chalk.gray(`πŸ› οΈ Tools: ${manifest.tools?.length || 0}`), isQuiet); + // Create ZIP archive + const output = createWriteStream(outputPath); + const archive = archiver('zip', { + zlib: { level: 9 } // Maximum compression + }); + // Handle archive events + output.on('close', () => { + const sizeKB = (archive.pointer() / 1024).toFixed(2); + logMessage(chalk.green(`\nβœ… Package created successfully!`), isQuiet); + logMessage(chalk.gray(`πŸ“ File: ${outputPath}`), isQuiet); + logMessage(chalk.gray(`πŸ“ Size: ${sizeKB} KB`), isQuiet); + // Package summary + logMessage(chalk.blue('\nπŸ“Š Package Contents:'), isQuiet); + logMessage(chalk.gray(` β€’ Extension manifest (extension.yaml)`), isQuiet); + logMessage(chalk.gray(` β€’ Publisher configuration (publisher.json)`), isQuiet); + logMessage(chalk.gray(` β€’ Large logo (assets/logo_large.png)`), isQuiet); + if (options.include && options.include.length > 0) { + logMessage(chalk.gray(` β€’ Additional files: ${options.include.length}`), isQuiet); + } + logMessage(chalk.green('\nπŸŽ‰ Ready for deployment!'), isQuiet); + }); + archive.on('warning', (err) => { + if (err.code === 'ENOENT') { + logMessage(chalk.yellow(`⚠️ Warning: ${err.message}`), isQuiet); + } + else { + throw err; + } + }); + archive.on('error', (err) => { + logMessage(chalk.red(`❌ Archive error: ${err.message}`), isQuiet); + throw new Error(`Archive error: ${err.message}`); + }); + archive.pipe(output); + // Add required files with standardized names + // Always name the manifest "extension.yaml" in the package, regardless of source filename + archive.file(manifestPath, { name: 'extension.yaml' }); + logMessage(chalk.gray(`βœ“ Added extension.yaml (from ${path.basename(manifestPath)})`), isQuiet); + // Always name the publisher config "publisher.json" in the package + archive.file(publisherPath, { name: 'publisher.json' }); + logMessage(chalk.gray(`βœ“ Added publisher.json`), isQuiet); + // Add required logo + archive.file(logoPath, { name: 'assets/logo_large.png' }); + logMessage(chalk.gray(`βœ“ Added assets/logo_large.png`), isQuiet); + // Add additional files if specified + if (options.include && options.include.length > 0) { + logMessage(chalk.blue('\nπŸ“ Adding additional files...'), isQuiet); + for (const pattern of options.include) { + if (await pathExists(pattern)) { + const fileName = path.basename(pattern); + archive.file(pattern, { name: fileName }); + logMessage(chalk.gray(`βœ“ Added ${fileName}`), isQuiet); + } + else { + logMessage(chalk.yellow(`⚠️ File not found, skipping: ${pattern}`), isQuiet); + } + } + } + // Add common directories if they exist (excluding assets since we handle it explicitly) + const commonDirectories = [ + { path: 'locales', description: 'localization files' } + ]; + for (const dir of commonDirectories) { + if (await pathExists(dir.path)) { + archive.directory(dir.path, dir.path); + logMessage(chalk.gray(`βœ“ Added ${dir.path}/ directory (${dir.description})`), isQuiet); + } + } + // Add other assets if they exist (but logo_large.png is already handled) + if (await pathExists('assets')) { + const assetsEntries = await fs.readdir('assets'); + const otherAssets = assetsEntries.filter(entry => entry !== 'logo_large.png'); + if (otherAssets.length > 0) { + for (const asset of otherAssets) { + const assetPath = path.join('assets', asset); + if ((await fs.stat(assetPath)).isFile()) { + archive.file(assetPath, { name: `assets/${asset}` }); + logMessage(chalk.gray(`βœ“ Added assets/${asset}`), isQuiet); + } + } + } + } + // Finalize the archive + await archive.finalize(); + } + catch (error) { + if (error instanceof Error) { + logMessage(chalk.red(`❌ Failed to package extension: ${error.message}`), isQuiet); + throw error; // Re-throw for test handling + } + else { + logMessage(chalk.red('❌ Failed to package extension: Unknown error'), isQuiet); + throw new Error('Failed to package extension: Unknown error'); + } + } +} +//# sourceMappingURL=package.js.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/domains/extension/commands/package.js.map b/tools/dragon-copilot-cli/dist/domains/extension/commands/package.js.map new file mode 100644 index 0000000..a793e6a --- /dev/null +++ b/tools/dragon-copilot-cli/dist/domains/extension/commands/package.js.map @@ -0,0 +1 @@ +{"version":3,"file":"package.js","sourceRoot":"","sources":["../../../../src/domains/extension/commands/package.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/domains/extension/commands/validate.d.ts b/tools/dragon-copilot-cli/dist/domains/extension/commands/validate.d.ts new file mode 100644 index 0000000..5d43d07 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/domains/extension/commands/validate.d.ts @@ -0,0 +1,2 @@ +export declare function validateManifest(filePath: string): Promise; +//# sourceMappingURL=validate.d.ts.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/domains/extension/commands/validate.d.ts.map b/tools/dragon-copilot-cli/dist/domains/extension/commands/validate.d.ts.map new file mode 100644 index 0000000..7d32c2d --- /dev/null +++ b/tools/dragon-copilot-cli/dist/domains/extension/commands/validate.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../../src/domains/extension/commands/validate.ts"],"names":[],"mappings":"AAUA,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA+GtE"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/domains/extension/commands/validate.js b/tools/dragon-copilot-cli/dist/domains/extension/commands/validate.js new file mode 100644 index 0000000..55de662 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/domains/extension/commands/validate.js @@ -0,0 +1,112 @@ +import fs from 'fs-extra'; +const { readFileSync, existsSync } = fs; +import yaml from 'js-yaml'; +const { load } = yaml; +import path from 'path'; +import chalk from 'chalk'; +import { validateExtensionManifest, validatePublisherConfig, getFieldDisplayName } from '../shared/schema-validator.js'; +export async function validateManifest(filePath) { + console.log(chalk.blue('πŸ‰ Validating Dragon Copilot Extension Manifest')); + console.log(chalk.gray(`πŸ“„ File: ${filePath}\n`)); + let hasErrors = false; + let hasWarnings = false; + // Validate manifest file + try { + const fileContent = readFileSync(filePath, 'utf8'); + const manifest = load(fileContent); + console.log(chalk.blue('πŸ“‹ Validating Extension Manifest...')); + const manifestResult = validateExtensionManifest(manifest); + if (manifestResult.errors.length > 0) { + hasErrors = true; + console.log(chalk.red('❌ Manifest validation failed with errors:')); + manifestResult.errors.forEach((error) => { + // Convert schema path to friendly field name + const fieldPath = error.instancePath.replace(/^\//, '').replace(/\//g, '.'); + const fieldName = fieldPath || 'manifest'; + console.log(chalk.red(` β€’ ${fieldName}: ${error.message}`)); + }); + } + // Check for publisher.json in the same directory + const manifestDir = path.dirname(filePath); + const publisherPath = path.join(manifestDir, 'publisher.json'); + if (existsSync(publisherPath)) { + console.log(chalk.blue('\nπŸ“‹ Validating Publisher Configuration...')); + try { + const publisherContent = readFileSync(publisherPath, 'utf8'); + const publisherConfig = JSON.parse(publisherContent); + const publisherResult = validatePublisherConfig(publisherConfig); + if (publisherResult.errors.length > 0) { + hasErrors = true; + console.log(chalk.red('❌ Publisher config validation failed with errors:')); + publisherResult.errors.forEach((error) => { + // Convert schema path to friendly field name + const fieldPath = error.instancePath.replace(/^\//, '').replace(/\//g, '.'); + const fieldName = getFieldDisplayName(fieldPath) || fieldPath || 'config'; + console.log(chalk.red(` β€’ ${fieldName}: ${error.message}`)); + }); + } + } + catch (publisherError) { + hasErrors = true; + if (publisherError instanceof Error) { + console.log(chalk.red(`❌ Publisher config parsing error: ${publisherError.message}`)); + } + else { + console.log(chalk.red('❌ Publisher config parsing error: Unknown error')); + } + } + } + else { + hasWarnings = true; + console.log(chalk.yellow('\n⚠️ No publisher.json found - consider creating one for extension publishing')); + } + // Display results summary + if (!hasErrors) { + console.log(chalk.green('\nβœ… Validation passed!')); + // Display summary + console.log(chalk.gray('\nπŸ“Š Extension Summary:')); + console.log(chalk.gray(` β€’ Extension: ${manifest.name} v${manifest.version}`)); + if (manifest.manifestVersion) { + console.log(chalk.gray(` β€’ Manifest Schema Version: ${manifest.manifestVersion}`)); + } + console.log(chalk.gray(` β€’ Description: ${manifest.description}`)); + console.log(chalk.gray(` β€’ Auth Tenant ID: ${manifest.auth?.tenantId || 'Not specified'}`)); + console.log(chalk.gray(` β€’ Tools: ${manifest.tools?.length || 0}`)); + console.log(chalk.gray(` β€’ Automation Scripts: ${manifest.automationScripts?.length || 0}`)); + console.log(chalk.gray(` β€’ Event Triggers: ${manifest.eventTriggers?.length || 0}`)); + console.log(chalk.gray(` β€’ Dependencies: ${manifest.dependencies?.length || 0}`)); + if (existsSync(publisherPath)) { + try { + const publisherConfig = JSON.parse(readFileSync(publisherPath, 'utf8')); + console.log(chalk.gray(` β€’ Publisher: ${publisherConfig.publisherName} (${publisherConfig.publisherId})`)); + console.log(chalk.gray(` β€’ Supported Locales: ${publisherConfig.supportedLocales?.join(', ') || 'None'}`)); + console.log(chalk.gray(` β€’ Supported Regions: ${publisherConfig.regions?.join(', ') || 'None'}`)); + } + catch { + // Ignore parsing errors for summary + } + } + if (manifest.tools && manifest.tools.length > 0) { + manifest.tools.forEach(tool => { + console.log(chalk.gray(` - ${tool.name}: ${tool.inputs?.length || 0} inputs, ${tool.outputs?.length || 0} outputs`)); + }); + } + if (hasWarnings) { + console.log(chalk.yellow('\nπŸ’‘ Consider addressing the warnings above for better compliance.')); + } + } + else { + process.exit(1); + } + } + catch (error) { + if (error instanceof Error) { + console.log(chalk.red(`❌ Failed to parse manifest file: ${error.message}`)); + } + else { + console.log(chalk.red('❌ Failed to parse manifest file: Unknown error')); + } + process.exit(1); + } +} +//# sourceMappingURL=validate.js.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/domains/extension/commands/validate.js.map b/tools/dragon-copilot-cli/dist/domains/extension/commands/validate.js.map new file mode 100644 index 0000000..7e038ad --- /dev/null +++ b/tools/dragon-copilot-cli/dist/domains/extension/commands/validate.js.map @@ -0,0 +1 @@ +{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../../src/domains/extension/commands/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC;AACxC,OAAO,IAAI,MAAM,SAAS,CAAC;AAC3B,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;AACtB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,yBAAyB,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAGxH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAgB;IACrD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,QAAQ,IAAI,CAAC,CAAC,CAAC;IAElD,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,WAAW,GAAG,KAAK,CAAC;IAExB,yBAAyB;IACzB,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAA4B,CAAC;QAE9D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC,CAAC;QAC/D,MAAM,cAAc,GAAG,yBAAyB,CAAC,QAAQ,CAAC,CAAC;QAE3D,IAAI,cAAc,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrC,SAAS,GAAG,IAAI,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC,CAAC;YACpE,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAkB,EAAE,EAAE;gBACnD,6CAA6C;gBAC7C,MAAM,SAAS,GAAG,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;gBAC5E,MAAM,SAAS,GAAG,SAAS,IAAI,UAAU,CAAC;gBAC1C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,SAAS,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAC/D,CAAC,CAAC,CAAC;QACL,CAAC;QAED,iDAAiD;QACjD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC3C,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;QAE/D,IAAI,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC,CAAC;YACtE,IAAI,CAAC;gBACH,MAAM,gBAAgB,GAAG,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;gBAC7D,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAoB,CAAC;gBAExE,MAAM,eAAe,GAAG,uBAAuB,CAAC,eAAe,CAAC,CAAC;gBAEjE,IAAI,eAAe,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACtC,SAAS,GAAG,IAAI,CAAC;oBACjB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC,CAAC;oBAC5E,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAkB,EAAE,EAAE;wBACpD,6CAA6C;wBAC7C,MAAM,SAAS,GAAG,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;wBAC5E,MAAM,SAAS,GAAG,mBAAmB,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,QAAQ,CAAC;wBAC1E,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,SAAS,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;oBAC/D,CAAC,CAAC,CAAC;gBACL,CAAC;YAEH,CAAC;YAAC,OAAO,cAAc,EAAE,CAAC;gBACxB,SAAS,GAAG,IAAI,CAAC;gBACjB,IAAI,cAAc,YAAY,KAAK,EAAE,CAAC;oBACpC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,qCAAqC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;gBACxF,CAAC;qBAAM,CAAC;oBACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC,CAAC;gBAC5E,CAAC;YACH,CAAC;QACH,CAAC;aAAM,CAAC;YACN,WAAW,GAAG,IAAI,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,gFAAgF,CAAC,CAAC,CAAC;QAC9G,CAAC;QAED,0BAA0B;QAC1B,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC,CAAC;YAEnD,kBAAkB;YAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC,CAAC;YACnD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,kBAAkB,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAChF,IAAI,QAAQ,CAAC,eAAe,EAAE,CAAC;gBAC7B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gCAAgC,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;YACtF,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;YACpE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,uBAAuB,QAAQ,CAAC,IAAI,EAAE,QAAQ,IAAI,eAAe,EAAE,CAAC,CAAC,CAAC;YAC7F,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YACzE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,2BAA2B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YAC9F,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,uBAAuB,QAAQ,CAAC,aAAa,EAAE,MAAM,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YACtF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,QAAQ,CAAC,YAAY,EAAE,MAAM,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;YAE/E,IAAI,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;gBAC9B,IAAI,CAAC;oBACH,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAoB,CAAC;oBAC3F,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,kBAAkB,eAAe,CAAC,aAAa,KAAK,eAAe,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;oBAC5G,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,0BAA0B,eAAe,CAAC,gBAAgB,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC;oBAC5G,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,0BAA0B,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC;gBACrG,CAAC;gBAAC,MAAM,CAAC;oBACP,oCAAoC;gBACtC,CAAC;YACH,CAAC;YAED,IAAI,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChD,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;oBAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,YAAY,IAAI,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;gBAC1H,CAAC,CAAC,CAAC;YACL,CAAC;YAED,IAAI,WAAW,EAAE,CAAC;gBAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,oEAAoE,CAAC,CAAC,CAAC;YAClG,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IAEH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,oCAAoC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC9E,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC,CAAC;QAC3E,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/domains/extension/index.d.ts b/tools/dragon-copilot-cli/dist/domains/extension/index.d.ts new file mode 100644 index 0000000..6b52e9f --- /dev/null +++ b/tools/dragon-copilot-cli/dist/domains/extension/index.d.ts @@ -0,0 +1,10 @@ +import type { Command } from 'commander'; +import type { PackageOptions, InitOptions, GenerateOptions } from './types.js'; +export * from './types.js'; +export * from './shared/prompts.js'; +export declare function initProject(options: InitOptions): Promise; +export declare function generateManifest(options: GenerateOptions): Promise; +export declare function validateManifest(file: string): Promise; +export declare function packageExtension(options: PackageOptions): Promise; +export declare function registerExtensionCommands(program: Command): void; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/domains/extension/index.d.ts.map b/tools/dragon-copilot-cli/dist/domains/extension/index.d.ts.map new file mode 100644 index 0000000..5b149ef --- /dev/null +++ b/tools/dragon-copilot-cli/dist/domains/extension/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/domains/extension/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE/E,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AAEpC,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrE;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAG9E;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGlE;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAG7E;AAED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAsFhE"} \ No newline at end of file diff --git a/tools/dragon-copilot-cli/dist/domains/extension/index.js b/tools/dragon-copilot-cli/dist/domains/extension/index.js new file mode 100644 index 0000000..27e7f93 --- /dev/null +++ b/tools/dragon-copilot-cli/dist/domains/extension/index.js @@ -0,0 +1,90 @@ +export * from './types.js'; +export * from './shared/prompts.js'; +export async function initProject(options) { + const module = await import('./commands/init.js'); + return module.initProject(options); +} +export async function generateManifest(options) { + const module = await import('./commands/generate.js'); + return module.generateManifest(options); +} +export async function validateManifest(file) { + const module = await import('./commands/validate.js'); + return module.validateManifest(file); +} +export async function packageExtension(options) { + const module = await import('./commands/package.js'); + return module.packageExtension(options); +} +export function registerExtensionCommands(program) { + const extension = program + .command('extension') + .description('Commands for Dragon Copilot extension projects'); + extension + .command('init') + .description('Initialize a new extension project') + .option('-n, --name ', 'Extension name') + .option('-d, --description ', 'Extension description') + .option('-v, --version ', 'Extension version', '0.0.1') + .option('-o, --output ', 'Output directory', '.') + .action(async (options) => { + const normalizedOptions = { output: options.output }; + if (options.name !== undefined) { + normalizedOptions.name = options.name; + } + if (options.description !== undefined) { + normalizedOptions.description = options.description; + } + if (options.version !== undefined) { + normalizedOptions.version = options.version; + } + await initProject(normalizedOptions); + }); + extension + .command('generate') + .description('Generate or update an extension manifest') + .option('-t, --template