diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 0645f284..1874f035 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -59,7 +59,7 @@ The following instructions are only to be applied when performing a code review. **Only apply to directories in the `plugins/` directory** -- [ ] The plugin directory contains a `.github/plugin/plugin.json` file. +- [ ] The plugin directory contains a root `plugin.json` file. - [ ] The plugin directory contains a `README.md` file. - [ ] The plugin.json has a `name` field matching the directory name. - [ ] The plugin.json has a `description` field. diff --git a/.github/plugin/marketplace.json b/.github/plugin/marketplace.json index ba86b835..eb1734fe 100644 --- a/.github/plugin/marketplace.json +++ b/.github/plugin/marketplace.json @@ -11,7 +11,7 @@ "plugins": [ { "name": "accessibility-kanban", - "source": "extensions/accessibility-kanban", + "source": "plugins/accessibility-kanban", "description": "Kanban board to manage accessibility issues, allow you to plan, track, and complete remediation work.", "version": "1.0.2" }, @@ -83,13 +83,13 @@ }, { "name": "apng-studio", - "source": "extensions/apng-studio", + "source": "plugins/apng-studio", "description": "Interactive GitHub Copilot app canvas extension for building Animated PNG (APNG) files from frames. Draw or upload frames, tune per-frame timing and compositing, preview live, send the result to your phone by QR, and export an animated .png.", "version": "1.0.2" }, { "name": "arcade-canvas", - "source": "extensions/arcade-canvas", + "source": "plugins/arcade-canvas", "description": "Play five retro Phaser mini-games in a Copilot canvas while agents work.", "version": "1.0.2" }, @@ -156,13 +156,13 @@ }, { "name": "backlog-swipe-triage", - "source": "extensions/backlog-swipe-triage", + "source": "plugins/backlog-swipe-triage", "description": "Quickly swipe through backlog issues to triage decisions like assign, needs-info, defer, close, or ignore.", "version": "1.0.2" }, { "name": "backrooms-canvas", - "source": "extensions/backrooms-canvas", + "source": "plugins/backrooms-canvas", "description": "Wander an endless first-person backrooms in a Copilot canvas while agents work; their status ghost-writes on the walls.", "version": "1.0.0" }, @@ -227,7 +227,7 @@ }, { "name": "chromium-control-canvas", - "source": "extensions/chromium-control-canvas", + "source": "plugins/chromium-control-canvas", "description": "Opens a real Chromium window you can navigate and interact with from a Copilot canvas control panel and agent actions.", "version": "1.0.2" }, @@ -271,7 +271,7 @@ }, { "name": "color-orb", - "source": "extensions/color-orb", + "source": "plugins/color-orb", "description": "A visual orb that users can ask the agent to recolor while showing a live activity log in the canvas.", "version": "1.0.2" }, @@ -426,7 +426,7 @@ }, { "name": "diagram-viewer", - "source": "extensions/diagram-viewer", + "source": "plugins/diagram-viewer", "description": "Render diagrams, click nodes to drill down, and view agent-generated explanations directly in the canvas.", "version": "1.0.2" }, @@ -573,7 +573,7 @@ }, { "name": "feedback-themes", - "source": "extensions/feedback-themes", + "source": "plugins/feedback-themes", "description": "Explore grouped customer feedback signals by impact and drill into a theme to guide product next steps.", "version": "1.0.2" }, @@ -601,7 +601,7 @@ }, { "name": "flight-map-canvas", - "source": "extensions/flight-map-canvas", + "source": "plugins/flight-map-canvas", "description": "A GitHub Copilot canvas that generates a view where Google Maps can be explored using 3D controls, as if a flight simulator. Agents can send the flight anywhere and report what they are working on.", "version": "1.0.0" }, @@ -625,7 +625,7 @@ }, { "name": "gesture-review", - "source": "extensions/gesture-review", + "source": "plugins/gesture-review", "description": "Review pull requests with a live camera feed and approve or reject using thumbs-up/thumbs-down gestures.", "version": "1.0.2" }, @@ -733,7 +733,7 @@ }, { "name": "java-modernization-studio", - "source": "extensions/java-modernization-studio", + "source": "plugins/java-modernization-studio", "description": "Drive the GitHub Copilot App Modernization for Java workflow from an interactive canvas: environment readiness, repo assessment, prioritized plan and progress, validation gates, and one-click predefined-task runs grounded in the repo's real artifacts.", "version": "1.0.2" }, @@ -1061,7 +1061,7 @@ }, { "name": "pr-artifact-explorer", - "source": "extensions/pr-artifact-explorer", + "source": "plugins/pr-artifact-explorer", "description": "Navigate pull requests and securely explore GitHub Actions artifacts, including test results, static sites, terminal recordings, and source files.", "version": "1.0.0" }, @@ -1097,13 +1097,13 @@ }, { "name": "release-notes-showcase", - "source": "extensions/release-notes-showcase", + "source": "plugins/release-notes-showcase", "description": "Compose and refine launch-ready release notes with contributor callouts and export-friendly output.", "version": "1.0.2" }, { "name": "repo-actions-hub", - "source": "extensions/repo-actions-hub", + "source": "plugins/repo-actions-hub", "description": "Browse repository GitHub Actions workflows, inspect recent runs, and trigger manual workflow_dispatch runs from a Copilot canvas.", "version": "1.0.2" }, @@ -1145,13 +1145,13 @@ }, { "name": "signals-dashboard", - "source": "extensions/signals-dashboard", + "source": "plugins/signals-dashboard", "description": "Real-time Workshop dashboard with agent signals, honesty calibration, and cost-aware repo or connected desk launch profiles.", "version": "0.2.0" }, { "name": "site-studio", - "source": "extensions/site-studio", + "source": "plugins/site-studio", "description": "Plan, draft, and track a personal website section by section — a shared canvas where you and your agent author content, watch progress, and review every change.", "version": "1.0.2" }, @@ -1271,13 +1271,13 @@ }, { "name": "tiny-tool-town-submitter", - "source": "extensions/tiny-tool-town-submitter", + "source": "plugins/tiny-tool-town-submitter", "description": "Inspect a repository, improve Tiny Tool Town readiness, submit its listing issue, and launch remediation work.", "version": "1.0.2" }, { "name": "token-pacman", - "source": "extensions/token-pacman", + "source": "plugins/token-pacman", "description": "Visualizes live session AI-credit usage as a Pac-Man board with pellets, ghosts, fruit milestones, and game-over limits.", "version": "1.0.2" }, @@ -1495,7 +1495,7 @@ }, { "name": "where-was-i", - "source": "extensions/where-was-i", + "source": "plugins/where-was-i", "description": "Reconstruct your dev context (branch, commits, uncommitted work, PR clues) and trigger a resume prompt to continue quickly.", "version": "1.0.2" }, @@ -1559,7 +1559,7 @@ }, { "name": "work-hub", - "source": "extensions/work-hub", + "source": "plugins/work-hub", "description": "Generic cross-repo command center canvas for GitHub Copilot with onboarding, focus planning, repo health, work signals, and session cleanup.", "version": "1.0.2" } diff --git a/.github/skills/create-canvas-extension/SKILL.md b/.github/skills/create-canvas-extension/SKILL.md new file mode 100644 index 00000000..265faaed --- /dev/null +++ b/.github/skills/create-canvas-extension/SKILL.md @@ -0,0 +1,124 @@ +--- +name: create-canvas-extension +description: 'Create or register a canvas extension in the awesome-copilot repository. Use when asked to scaffold a new canvas extension, create its plugin.json, add a reusable extension to one or more plugins, or migrate extension metadata. Extensions are reusable source under extensions/; shippable plugin manifests belong under plugins/.' +argument-hint: '[optional extension name or description]' +--- + +# Create a canvas extension + +Use this skill only for the `github/awesome-copilot` repository. Canvas extensions are reusable source components. They do not have a `plugin.json` under `extensions/`. + +## Required decisions + +Before creating files, ask for each missing value: + +1. **Extension ID**: lowercase kebab-case, matching the source folder and plugin name. +2. **Display metadata**: + - description + - version (default `1.0.0`) + - author name and optional URL + - keywords (lowercase, hyphenated, maximum 10) + - repository and license (default to the repository URL and `MIT` when appropriate) +3. **Canvas entrypoint**: confirm whether the extension already has `extension.mjs`. If not, create a minimal entrypoint only when the user provides enough implementation details; otherwise create the directory and leave an explicit TODO. +4. **Preview image**: obtain an existing `assets/preview.png` path or ask the user to add it. Do not invent a binary image or silently use a misleading placeholder. +5. **Plugin registration**: + - For a standalone installable canvas plugin, create `plugins/`. + - For an extension that belongs to an existing plugin, ask for the parent plugin ID and add `./extensions/` to that plugin's `extensions.com.github.awesome-copilot.extensions`. + - If the extension should be shipped by multiple plugins, collect all plugin IDs and add the same extension ID to each mapping file. + +## Files to create + +For a new extension plugin, create this structure: + +```text +extensions// +├── extension.mjs +└── assets/ + └── preview.png + +plugins// +├── plugin.json +└── README.md +``` + +The extension source may contain additional files such as `package.json`, canvas assets, or supporting modules. Keep all reusable implementation files under `extensions//`. + +Create `plugins//plugin.json` with this shape: + +```json +{ + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", + "name": "", + "description": "", + "version": "1.0.0", + "author": { + "name": "" + }, + "repository": "https://github.com/github/awesome-copilot", + "license": "MIT", + "keywords": [ + "" + ], + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/" + ] + } + } +} +``` + +Keep Agent Plugins fields at the manifest top level. Repository composition belongs only under `extensions.com.github.awesome-copilot`; do not put `agents`, `commands`, `hooks`, `mcpServers`, or `skills` at the top level or directly under `extensions`. Do not add `x-awesome-copilot`, `standalone`, or other repository-specific top-level fields. + +For an existing parent plugin, create or update: + +```text +plugins//plugin.json (`extensions.com.github.awesome-copilot.extensions`) +``` + +Its `extensions` property must contain sorted repository-relative paths: + +```json +{ + "extensions": [ + "./extensions/" + ] +} +``` + +Do not copy the extension source into the parent plugin. Materialization resolves the IDs from the root `extensions/` directory, so the same source can be bundled by multiple plugins. + +## Workflow + +1. Inspect the repository before editing: + - confirm `extensions/` and `plugins/` do not already conflict + - inspect the target parent plugin, if any + - check whether a preview image and entrypoint already exist +2. Ask only the missing required questions from the decisions above. +3. Create the source and plugin directories with the required files. +4. If creating a new entrypoint, keep it minimal and clearly mark implementation TODOs rather than fabricating behavior. +5. Add or update `extensions.com.github.awesome-copilot.extensions` for every parent plugin that should ship the extension. Keep paths alphabetically sorted and unique. +6. Ensure there is no `extensions//.github/plugin/plugin.json`. +7. Run: + + ```bash + npm run plugin:validate + npm run build + npm run website:data + ``` + +8. Report the created paths, the plugins that ship the extension, and any missing user-provided assets or TODOs. + +## Existing extension migration + +When migrating an existing extension: + +1. Move its existing manifest to `plugins//plugin.json`. +2. Update the manifest to the namespace-based `extensions.com.github.copilot.logo` shape. +3. Remove the old manifest from `extensions/`. +4. Register the extension in any parent plugin's `extensions.com.github.awesome-copilot.extensions`. +5. Run the validation and build commands above. diff --git a/.github/workflows/check-plugin-structure.yml b/.github/workflows/check-plugin-structure.yml index fd6f90d8..89e1bf30 100644 --- a/.github/workflows/check-plugin-structure.yml +++ b/.github/workflows/check-plugin-structure.yml @@ -93,7 +93,7 @@ jobs: if (files.length > 0) { errors.push( `${pluginPath}/${subdir}/ contains ${files.length} file(s): ${files.join(', ')}. ` + - `Plugin directories on main should only contain .github/plugin/plugin.json and README.md. ` + + `Plugin directories on main should only contain plugin.json and README.md. ` + `Agent, command, and skill files are materialized automatically during publish to marketplace.` ); } @@ -121,7 +121,7 @@ jobs: '⚠️ **Materialized files or symlinks detected in plugin directories**', '', 'Plugin directories on the `main` branch should only contain:', - '- `.github/plugin/plugin.json` (metadata)', + '- `plugin.json` (metadata)', '- `README.md`', '', 'Agent, command, and skill files are copied in automatically when publishing to `marketplace`.', diff --git a/.github/workflows/external-plugin-command-router.yml b/.github/workflows/external-plugin-command-router.yml index 5769f3b5..5f786e53 100644 --- a/.github/workflows/external-plugin-command-router.yml +++ b/.github/workflows/external-plugin-command-router.yml @@ -750,6 +750,7 @@ jobs: if (process.env.QUALITY_JOB_RESULT === 'failure' || process.env.QUALITY_JOB_RESULT === 'cancelled') { qualityResult = { overall_status: 'infra_error', + spec_compliance_status: 'warning', vally_lint_status: 'infra_error', smoke_status: 'infra_error', version_match_status: 'infra_error', @@ -762,6 +763,7 @@ jobs: } else { qualityResult = { overall_status: 'infra_error', + spec_compliance_status: 'warning', vally_lint_status: 'infra_error', smoke_status: 'infra_error', version_match_status: 'infra_error', diff --git a/.github/workflows/external-plugin-intake.yml b/.github/workflows/external-plugin-intake.yml index ca7852dd..de664028 100644 --- a/.github/workflows/external-plugin-intake.yml +++ b/.github/workflows/external-plugin-intake.yml @@ -113,6 +113,7 @@ jobs: if (process.env.QUALITY_JOB_RESULT === 'failure' || process.env.QUALITY_JOB_RESULT === 'cancelled') { qualityResult = { overall_status: 'infra_error', + spec_compliance_status: 'warning', vally_lint_status: 'infra_error', smoke_status: 'infra_error', version_match_status: 'infra_error', @@ -125,6 +126,7 @@ jobs: } else { qualityResult = { overall_status: 'infra_error', + spec_compliance_status: 'warning', vally_lint_status: 'infra_error', smoke_status: 'infra_error', version_match_status: 'infra_error', diff --git a/.github/workflows/external-plugin-pr-quality-gates.yml b/.github/workflows/external-plugin-pr-quality-gates.yml index 39a7d267..89c79d79 100644 --- a/.github/workflows/external-plugin-pr-quality-gates.yml +++ b/.github/workflows/external-plugin-pr-quality-gates.yml @@ -147,6 +147,7 @@ jobs: let qualityResult = { overall_status: 'not_run', + spec_compliance_status: 'not_run', failure_class: 'none', checked_plugins: [], summary: 'No changed external plugin entries were detected in this PR.', @@ -155,6 +156,7 @@ jobs: if (detectJobResult === 'failure' || detectJobResult === 'cancelled') { qualityResult = { overall_status: 'infra_error', + spec_compliance_status: 'not_run', failure_class: 'infra', checked_plugins: [], version_match_status: 'infra_error', @@ -165,6 +167,7 @@ jobs: if (qualityJobResult === 'failure' || qualityJobResult === 'cancelled') { qualityResult = { overall_status: 'infra_error', + spec_compliance_status: 'not_run', failure_class: 'infra', checked_plugins: [], version_match_status: 'infra_error', @@ -176,6 +179,7 @@ jobs: } else { qualityResult = { overall_status: 'infra_error', + spec_compliance_status: 'not_run', failure_class: 'infra', checked_plugins: [], version_match_status: 'infra_error', @@ -201,11 +205,29 @@ jobs: }); const checkedPlugins = Array.isArray(qualityResult.checked_plugins) ? qualityResult.checked_plugins : []; + const hasSpecWarnings = checkedPlugins.some((entry) => String(entry?.quality?.spec_compliance_status || '') === 'warning'); const header = qualityResult.failure_class === 'submitter_fixes' - ? '## ⚠️ External plugin PR checks require submitter fixes' - : qualityResult.overall_status === 'pass' || !shouldRun - ? '## ✅ External plugin PR checks passed' - : '## ⚠️ External plugin PR checks need maintainer follow-up'; + ? '## 🛑 External plugin PR checks failed (submitter fixes required)' + : qualityResult.overall_status === 'infra_error' + ? '## 🛑 External plugin PR checks failed (maintainer follow-up)' + : hasSpecWarnings + ? '## ⚠️ External plugin PR checks passed with spec warnings' + : qualityResult.overall_status === 'pass' || !shouldRun + ? '## ✅ External plugin PR checks passed' + : '## ⚠️ External plugin PR checks need maintainer follow-up'; + const formatStatus = (rawStatus, gateName) => { + const status = String(rawStatus || 'not_run'); + if (status === 'pass') { + return '✅ pass'; + } + if (status === 'warning' || (gateName === 'spec compliance' && status === 'fail')) { + return '⚠️ warning'; + } + if (status === 'fail' || status === 'infra_error') { + return '🛑 fail'; + } + return '⚪ not_run'; + }; const MAX_GATE_OUTPUT_CHARS = 2000; const escapeHtml = (value) => String(value || '') @@ -273,21 +295,16 @@ jobs: ? checkedPlugins.map((entry) => { const name = escapeMarkdownTableCell(entry?.name || 'unknown'); const quality = entry?.quality || {}; - const sourceUrl = normalizeGitHubUrl(entry?.source_tree_url || ''); + const sourceUrl = normalizeGitHubUrl(entry?.source_tree_url); const locator = escapeMarkdownTableCell(entry?.source?.sha || entry?.source?.ref || 'repository'); - const sourceCell = sourceUrl ? `[${locator}](<${sourceUrl}>)` : locator; - const vallyLintStatus = escapeMarkdownTableCell(quality.vally_lint_status || 'not_run'); - const smokeStatus = escapeMarkdownTableCell(quality.smoke_status || 'not_run'); - const versionMatchStatus = escapeMarkdownTableCell(quality.version_match_status || 'not_run'); - const refShaConsistencyStatus = escapeMarkdownTableCell(quality.ref_sha_consistency_status || 'not_run'); - const canvasStructureStatus = escapeMarkdownTableCell(quality.canvas_structure_status || 'not_run'); - const overallStatus = escapeMarkdownTableCell(quality.overall_status || 'not_run'); - return `| ${name} | ${vallyLintStatus} | ${smokeStatus} | ${versionMatchStatus} | ${refShaConsistencyStatus} | ${canvasStructureStatus} | ${overallStatus} | ${sourceCell} |`; + const sourceCell = sourceUrl ? `[${locator}](${sourceUrl})` : locator; + return `| ${name} | ${formatStatus(quality.spec_compliance_status, 'spec compliance')} | ${formatStatus(quality.vally_lint_status, 'vally lint')} | ${formatStatus(quality.smoke_status, 'install smoke test')} | ${formatStatus(quality.version_match_status, 'version match')} | ${formatStatus(quality.ref_sha_consistency_status, 'ref/sha consistency')} | ${formatStatus(quality.canvas_structure_status, 'canvas structure')} | ${formatStatus(quality.overall_status, 'overall')} | ${sourceCell} |`; }) - : ['| _none_ | not_run | not_run | not_run | not_run | not_run | not_run | _n/a_ |']; + : ['| _none_ | ⚪ not_run | ⚪ not_run | ⚪ not_run | ⚪ not_run | ⚪ not_run | ⚪ not_run | ⚪ not_run | _n/a_ |']; const failureDetails = checkedPlugins.flatMap((entry) => { const name = String(entry?.name || 'unknown'); const quality = entry?.quality || {}; + const shouldShowSpec = quality.spec_compliance_status === 'warning' || String(quality.spec_compliance_output || '').trim().length > 0; const shouldShowVally = quality.vally_lint_status === 'fail' || quality.vally_lint_status === 'infra_error' || String(quality.vally_lint_output || '').trim().length > 0; const shouldShowSmoke = quality.smoke_status === 'fail' || quality.smoke_status === 'infra_error' || String(quality.smoke_output || '').trim().length > 0; const shouldShowVersionMatch = quality.version_match_status === 'fail' || quality.version_match_status === 'infra_error' || String(quality.version_match_output || '').trim().length > 0; @@ -295,11 +312,14 @@ jobs: const shouldShowCanvasStructure = quality.canvas_structure_status === 'fail' || quality.canvas_structure_status === 'infra_error' || String(quality.canvas_structure_output || '').trim().length > 0; const details = []; + if (shouldShowSpec) { + details.push(formatGateOutput(name, 'spec compliance', formatStatus(quality.spec_compliance_status, 'spec compliance'), quality.spec_compliance_output)); + } if (shouldShowVally) { - details.push(formatGateOutput(name, 'vally lint', quality.vally_lint_status, quality.vally_lint_output)); + details.push(formatGateOutput(name, 'vally lint', formatStatus(quality.vally_lint_status, 'vally lint'), quality.vally_lint_output)); } if (shouldShowSmoke) { - details.push(formatGateOutput(name, 'install smoke test', quality.smoke_status, quality.smoke_output)); + details.push(formatGateOutput(name, 'install smoke test', formatStatus(quality.smoke_status, 'install smoke test'), quality.smoke_output)); } if (shouldShowVersionMatch) { details.push(formatGateOutput(name, 'version match', quality.version_match_status, quality.version_match_output)); @@ -319,11 +339,12 @@ jobs: '', `- **Changed entries detected:** ${changedCount}`, `- **Workflow state label:** \`${stateLabel}\``, + '- **Status legend:** ✅ pass · ⚠️ warning · 🛑 fail', '', '### Per-plugin quality summary', '', - '| Plugin | vally lint | install smoke test | version match | ref/sha consistency | canvas structure | overall | source tree |', - '|---|---|---|---|---|---|---|---|', + '| Plugin | spec compliance (non-blocking) | vally lint | install smoke test | version match | ref/sha consistency | canvas structure | overall | source tree |', + '|---|---|---|---|---|---|---|---|---|', ...rows, '', ...(failureDetails.length > 0 diff --git a/.github/workflows/validate-plugins.yml b/.github/workflows/validate-plugins.yml new file mode 100644 index 00000000..c56466cd --- /dev/null +++ b/.github/workflows/validate-plugins.yml @@ -0,0 +1,95 @@ +name: Validate Plugins and Extensions + +on: + pull_request: + branches: [main] + paths: + - "plugins/**" + - "extensions/**" + - "eng/validate-plugins.mjs" + - ".github/workflows/validate-plugins.yml" + +permissions: + contents: read + pull-requests: write + +jobs: + validate: + name: Plugin & extension spec validation + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + + - name: Setup Node.js + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: "22" + cache: "npm" + + - name: Install dependencies + run: npm ci + + - name: Validate plugins and extensions + id: validate + run: npm run plugin:validate + + - name: Manage validation summary on PR + if: always() + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 + with: + script: | + const marker = ''; + const validationOutcome = '${{ steps.validate.outcome }}'; + const validationFailed = validationOutcome === 'failure'; + const validationPassed = validationOutcome === 'success'; + const body = [ + marker, + '🛑 **Plugin/extension validation failed**', + '', + 'One or more plugins or extensions in this PR do not pass spec validation.', + '', + 'All internal plugins and extensions must include:', + '- `"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json"` in `plugin.json`', + '- A valid `name`, `description`, and `version`', + '- Repository composition (`agents`, `commands`, `hooks`, `mcpServers`, `skills`, and reusable `extensions`) under `extensions.com.github.awesome-copilot`', + '- For **extensions**: `extensions.com.github.copilot.logo` must be set to `"assets/preview.png"`', + '', + 'Do not put repository composition fields at the manifest top level or directly under `extensions`; they must be nested under `extensions.com.github.awesome-copilot`.', + '', + 'Run `npm run plugin:validate` locally to see the full list of errors. See `.github/skills/create-canvas-extension/SKILL.md` and `CONTRIBUTING.md` for examples.', + ].join('\n'); + + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + per_page: 100, + }); + + const existing = comments.find((comment) => comment.body.includes(marker)); + + if (validationFailed && existing) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existing.id, + body, + }); + console.log(`Updated existing validation comment ${existing.id}`); + } else if (validationFailed) { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body, + }); + console.log('Created validation comment'); + } else if (validationPassed && existing) { + await github.rest.issues.deleteComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: existing.id, + }); + console.log(`Deleted stale validation comment ${existing.id}`); + } diff --git a/AGENTS.md b/AGENTS.md index 3a17693c..fc10edd7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -21,7 +21,7 @@ The Awesome GitHub Copilot repository is a community-driven collection of custom ├── hooks/ # Automated workflow hooks (folders with README.md + hooks.json) ├── workflows/ # Agentic Workflows (.md files for GitHub Actions automation) ├── plugins/ # Installable plugin packages (folders with plugin.json) -├── extensions/ # Canvas extensions (each with extension.mjs and plugin metadata) +├── extensions/ # Reusable canvas extension sources (extension.mjs and assets) ├── docs/ # Documentation for different resource types ├── eng/ # Build and automation scripts └── scripts/ # Utility scripts @@ -85,15 +85,11 @@ All agent files (`*.agent.md`) and instruction files (`*.instructions.md`) must #### Canvas Extensions (extensions/\*) - Each extension folder must include `extension.mjs` -- Extension metadata must live at `.github/plugin/plugin.json` -- Extension `plugin.json` **must** follow the convention: - - `name`, `description`, `version` are required - - `logo` **must** be exactly `"assets/preview.png"` (enforced convention) - - `extensions` **must** be exactly `"."` in source manifests (materialization rewrites this to `"extensions"` for distribution output) - - Optional: `author`, `keywords` fields - - **Must not** include `x-awesome-copilot` field (use convention-based `assets/preview.png` only) +- Extensions are reusable source components, not standalone plugins +- A shippable extension plugin is registered by a matching `plugins//plugin.json` +- A plugin can bundle additional reusable extensions by listing `./extensions/` paths in `extensions.com.github.awesome-copilot.extensions` - Each extension must have `assets/preview.png` as the primary visual asset -- Do not add `canvas.json`; website metadata is sourced from `.github/plugin/plugin.json` +- Extension metadata is sourced from the matching plugin manifest in `plugins/` #### Hook Folders (hooks/\*/README.md) @@ -119,11 +115,12 @@ All agent files (`*.agent.md`) and instruction files (`*.instructions.md`) must #### Plugin Folders (plugins/\*) -- Each plugin is a folder containing a `.github/plugin/plugin.json` file with metadata +- Each plugin is a folder containing a root `plugin.json` file with metadata +- plugin.json **must** have `"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json"` (Agent Plugins v1.0.0) - plugin.json must have `name` field (matching the folder name) - plugin.json must have `description` field (describing the plugin's purpose) - plugin.json must have `version` field (semantic version, e.g., "1.0.0") -- Plugin content is defined declaratively in plugin.json using Claude Code spec fields (`agents`, `commands`, `skills`). Source files live in top-level directories and are materialized into plugins by CI. +- Plugin content is defined declaratively in plugin.json under `extensions.com.github.awesome-copilot` using source-only composition fields (`agents`, `commands`, `hooks`, `skills`, and `extensions`). Source files live in top-level directories and are materialized into plugins by CI. This namespace is stripped from the served manifest — conventional directory discovery handles the materialized content in spec mode. - The `marketplace.json` file is automatically generated from all plugins during build - Plugins are discoverable and installable via GitHub Copilot CLI @@ -168,7 +165,7 @@ When adding a new agent, instruction, skill, hook, workflow, or plugin: **For Plugins:** 1. Run `npm run plugin:create -- --name ` to scaffold a new plugin -2. Define agents, commands, and skills in `plugin.json` using Claude Code spec fields +2. Define agents, commands, hooks, skills, and reusable extensions under `extensions.com.github.awesome-copilot` in `plugin.json` 3. Edit the generated `plugin.json` with your metadata 4. Run `npm run plugin:validate` to validate the plugin structure 5. Run `npm run build` to update README.md and marketplace.json @@ -177,11 +174,26 @@ When adding a new agent, instruction, skill, hook, workflow, or plugin: **For Canvas Extensions:** 1. Create/update the extension in `extensions//` with `extension.mjs` -2. Add `.github/plugin/plugin.json` metadata (required: `name`, `description`, `version`, `logo: "assets/preview.png"`, `extensions: "."`; optional: `author`, `keywords`) +2. Add the matching plugin manifest under `plugins//plugin.json`: + ```json + { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", + "name": "", + "description": "...", + "version": "1.0.0", + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + } + } + } + ``` 3. Ensure `assets/preview.png` exists as the primary visual asset 4. Run `npm run plugin:validate` to validate plugin and extension metadata 5. Run `npm run build` to regenerate website data and marketplace output +To bundle an extension into another plugin without making a second source copy, add sorted `./extensions/` paths to `plugins//plugin.json` under `extensions.com.github.awesome-copilot.extensions`. + **For External Plugins:** 1. Do not open a direct PR that edits `plugins/external.json` for a public third-party plugin submission @@ -310,16 +322,17 @@ For workflow files (workflows/\*.md): For plugins (plugins/\*/): -- [ ] Directory contains a `.github/plugin/plugin.json` file +- [ ] Directory contains a root `plugin.json` file - [ ] Directory contains a `README.md` file +- [ ] `plugin.json` has `"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json"` - [ ] `plugin.json` has `name` field matching the directory name (lowercase with hyphens) - [ ] `plugin.json` has non-empty `description` field - [ ] `plugin.json` has `version` field (semantic version, e.g., "1.0.0") - [ ] Directory name is lower case with hyphens - [ ] If `keywords` is present, it is an array of lowercase hyphenated strings -- [ ] If `agents`, `commands`, or `skills` arrays are present, each entry is a valid relative path +- [ ] If composition arrays are present under `extensions.com.github.awesome-copilot`, each entry is a valid relative path - [ ] The plugin does not reference non-existent files -- [ ] Run `npm run build` to verify marketplace.json is updated correctly +- [ ] Run `npm run plugin:validate` and `npm run build` to verify the plugin passes all checks ## Contributing diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fc3d43ad..866b33ef 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -140,17 +140,15 @@ Skills are self-contained folders in the `skills/` directory that include a `SKI ### Adding Canvas Extensions -Canvas extensions live in `extensions//` and are installable through plugin metadata. +Canvas extensions live in `extensions//` as reusable source components. They are shipped only through plugin manifests in `plugins/`. -1. **Create/update extension metadata**: Add `.github/plugin/plugin.json` in the extension folder -2. **Use convention-based metadata**: Follow the extension plugin.json structure: +1. **Create/update the extension source**: Add or update `extensions//extension.mjs` +2. **Register the extension plugin**: Add `plugins//plugin.json`: - Required: `name` (matching folder name), `description`, `version` - Optional: `author`, `keywords` - - `logo` **must** be exactly `"assets/preview.png"` (enforced convention) - - `extensions` **must** be exactly `"."` (per [copilot-agent-runtime#9929](https://github.com/github/copilot-agent-runtime/pull/9929)) - - **Never** include `x-awesome-copilot` field (use convention-based assets only) + - `extensions.com.github.copilot.logo` **must** be exactly `"assets/preview.png"` 3. **Screenshot requirements**: Create `assets/preview.png` as your primary visual -4. **Do not add `canvas.json`**: Extension website metadata is now sourced from `.github/plugin/plugin.json` +4. **Do not add `canvas.json`**: Extension website metadata is sourced from the matching plugin manifest 5. **Validate before submitting**: Run `npm run plugin:validate` to check compliance with conventions ### Adding Plugins @@ -159,7 +157,7 @@ Plugins group related agents, commands, and skills around specific themes or wor 1. **Create your plugin**: Run `npm run plugin:create` to scaffold a new plugin 2. **Follow the naming convention**: Use descriptive, lowercase folder names with hyphens (e.g., `python-web-development`) -3. **Define your content**: List agents, commands, and skills in `plugin.json` using the Claude Code spec fields +3. **Define your content**: List agents, commands, hooks, skills, and reusable extensions under `extensions.com.github.awesome-copilot` in `plugin.json` 4. **Test your plugin**: Run `npm run plugin:validate` to verify your plugin structure #### Creating a plugin @@ -172,16 +170,17 @@ npm run plugin:create -- --name my-plugin-id ``` plugins/my-plugin-id/ -├── .github/plugin/plugin.json # Plugin metadata (Claude Code spec format) +├── plugin.json # Plugin metadata └── README.md # Plugin documentation ``` -> **Note:** Plugin content is defined declaratively in plugin.json using Claude Code spec fields (`agents`, `commands`, `skills`). Source files live in top-level directories and are materialized into plugins by CI. +> **Note:** Plugin content is defined declaratively in plugin.json under `extensions.com.github.awesome-copilot`. Source files live in top-level directories and are materialized into plugins by CI. This repository namespace is removed from the served manifest. #### plugin.json example ```json { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "my-plugin-id", "description": "Plugin description", "version": "1.0.0", @@ -189,17 +188,21 @@ plugins/my-plugin-id/ "author": { "name": "Awesome Copilot Community" }, "repository": "https://github.com/github/awesome-copilot", "license": "MIT", - "agents": ["./agents/my-agent.md"], - "commands": ["./commands/my-command.md"], - "skills": ["./skills/my-skill/"] + "extensions": { + "com.github.awesome-copilot": { + "agents": ["./agents/my-agent.md"], + "commands": ["./commands/my-command.md"], + "skills": ["./skills/my-skill/"] + } + } } ``` #### Plugin Guidelines -- **Declarative content**: Plugin content is specified via `agents`, `commands`, and `skills` arrays in plugin.json — source files live in top-level directories and are materialized into plugins by CI +- **Declarative content**: Plugin content is specified under `extensions.com.github.awesome-copilot` — source files live in top-level directories and are materialized into plugins by CI - **Valid references**: All paths referenced in plugin.json must point to existing source files in the repository -- **Optional extension links**: Curated plugins can reference extensions using `x-awesome-copilot.extensions` with paths like `./extensions/` +- **Reusable extensions**: Curated plugins can bundle extensions by adding `./extensions/` paths under `extensions.com.github.awesome-copilot.extensions`; the same extension can be listed by multiple plugins - **Instructions excluded**: Instructions are standalone resources and are not part of plugins - **Clear purpose**: The plugin should solve a specific problem or workflow - **Validate before submitting**: Run `npm run plugin:validate` to ensure your plugin is valid diff --git a/docs/README.plugins.md b/docs/README.plugins.md index f112ef83..7a19d6ea 100644 --- a/docs/README.plugins.md +++ b/docs/README.plugins.md @@ -27,17 +27,24 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-plugins) for guidelines on how t | Name | Description | Items | Tags | | ---- | ----------- | ----- | ---- | +| [accessibility-kanban](../plugins/accessibility-kanban/README.md) | Kanban board to manage accessibility issues, allow you to plan, track, and complete remediation work. | 1 items | accessibility, github-issues, issue-triage, kanban-board, planning-workflow, status-tracking | | [acreadiness-cockpit](../plugins/acreadiness-cockpit/README.md) | Drive Microsoft AgentRC from Copilot chat: assess AI readiness, generate Copilot instructions (flat or nested with applyTo globs for monorepos), and manage policies. Produces a self-contained static HTML dashboard at reports/index.html. | 4 items | agentrc, ai-readiness, copilot-instructions, readiness-report, monorepo, policy, dashboard | | [ai-team-orchestration](../plugins/ai-team-orchestration/README.md) | Run a lightweight, role-separated AI development team with flexible tools, developer-selected models, proportionate planning, and optional QA. | 4 items | ai-team, multi-agent, sprint-planning, brainstorm, project-management, orchestration, developer-workflow | +| [apng-studio](../plugins/apng-studio/README.md) | Interactive GitHub Copilot app canvas extension for building Animated PNG (APNG) files from frames. Draw or upload frames, tune per-frame timing and compositing, preview live, send the result to your phone by QR, and export an animated .png. | 1 items | animated-png, apng, copilot-canvas, frame-animation, image-export, interactive-canvas | +| [arcade-canvas](../plugins/arcade-canvas/README.md) | Play five retro Phaser mini-games in a Copilot canvas while agents work. | 1 items | arcade-games, copilot-canvas, interactive-canvas, phaser, retro-games, session-breaks | | [arch](../plugins/arch/README.md) | Architecture and modernization toolkit: produce a cited architecture document for a locally-cloned repo, and generate a phased modernization plan that auto-runs Documentation mode when needed. | 1 items | architecture, modernization, documentation, migration, onboarding | | [arize-ax](../plugins/arize-ax/README.md) | Arize AX platform skills for LLM observability, evaluation, and optimization. Includes trace export, instrumentation, datasets, experiments, evaluators, AI provider integrations, annotations, prompt optimization, and deep linking to the Arize UI. | 9 items | arize, llm, observability, tracing, evaluation, instrumentation, datasets, experiments, prompt-optimization | | [automate-this](../plugins/automate-this/README.md) | Record your screen doing a manual process, drop the video on your Desktop, and let Copilot CLI analyze it frame-by-frame to build working automation scripts. Supports narrated recordings with audio transcription. | 1 items | automation, screen-recording, workflow, video-analysis, process-automation, scripting, productivity, copilot-cli | | [awesome-copilot](../plugins/awesome-copilot/README.md) | Meta prompts that help you discover and generate curated GitHub Copilot agents, instructions, prompts, and skills. | 4 items | github-copilot, discovery, meta, prompt-engineering, agents | | [aws-cloud-development](../plugins/aws-cloud-development/README.md) | Comprehensive AWS cloud development tools including Infrastructure as Code, serverless functions, architecture patterns, and cost optimization for building scalable cloud applications. | 8 items | aws, cloud, infrastructure, cloudformation, terraform, serverless, architecture, devops, cdk | | [azure-cloud-development](../plugins/azure-cloud-development/README.md) | Comprehensive Azure cloud development tools including Infrastructure as Code, serverless functions, architecture patterns, and cost optimization for building scalable cloud applications. | 11 items | azure, cloud, infrastructure, bicep, terraform, serverless, architecture, devops | +| [backlog-swipe-triage](../plugins/backlog-swipe-triage/README.md) | Quickly swipe through backlog issues to triage decisions like assign, needs-info, defer, close, or ignore. | 1 items | agent-assignment, backlog-triage, github-issues, issue-prioritization, swipe-interface, workflow-automation | +| [backrooms-canvas](../plugins/backrooms-canvas/README.md) | Wander an endless first-person backrooms in a Copilot canvas while agents work; their status ghost-writes on the walls. | 1 items | backrooms, copilot-canvas, interactive-canvas, first-person, procedural-generation, session-breaks | | [cast-imaging](../plugins/cast-imaging/README.md) | A comprehensive collection of specialized agents for software analysis, impact assessment, structural quality advisories, and architectural review using CAST Imaging. | 3 items | cast-imaging, software-analysis, architecture, quality, impact-analysis, devops | +| [chromium-control-canvas](../plugins/chromium-control-canvas/README.md) | Opens a real Chromium window you can navigate and interact with from a Copilot canvas control panel and agent actions. | 1 items | browser-control, chromium-browser, interactive-canvas, playwright-automation, screenshots, ui-testing, web-navigation | | [clojure-interactive-programming](../plugins/clojure-interactive-programming/README.md) | Tools for REPL-first Clojure workflows featuring Clojure instructions, the interactive programming chat mode and supporting guidance. | 2 items | clojure, repl, interactive-programming | | [cms-development](../plugins/cms-development/README.md) | Skills for CMS development across themes, plugins, admin tooling, media workflows, markdown rendering, and static export pipelines. | 3 items | cms, content-management-system, wordpress, shopify, drupal, theme, plugin, media, static-site | +| [color-orb](../plugins/color-orb/README.md) | A visual orb that users can ask the agent to recolor while showing a live activity log in the canvas. | 1 items | agent-actions, color-picker, interactive-demo, realtime-updates, sse-events, visual-feedback | | [context-engineering](../plugins/context-engineering/README.md) | Tools and techniques for maximizing GitHub Copilot effectiveness through better context management. Includes guidelines for structuring code, an agent for planning multi-file changes, and prompts for context-aware development. | 4 items | context, productivity, refactoring, best-practices, architecture | | [context-matic](../plugins/context-matic/README.md) | Coding agents hallucinate APIs. ContextMatic gives them curated, versioned API and SDK docs. Ask your agent to "integrate the payments API" and it guesses — falling back on outdated training data and generic patterns that don't match your actual SDK. ContextMatic solves this by giving the agent deterministic, version-aware, SDK-native context at the exact moment it's needed. | 2 items | api-context, api-integration, mcp, sdk, apimatic, third-party-apis, sdks | | [convert-to-md](../plugins/convert-to-md/README.md) | A collection of Copilot skills that convert common document formats into Markdown so their contents can be accurately analyzed, summarized, searched, or extracted from. Just tell Copilot what you need — the right skill is invoked automatically and the conversion happens behind the scenes. | 3 items | skills, configuration, copilot, convert-word-to-md, convert-excel-to-md, convert-pdf-to-md | @@ -46,17 +53,22 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-plugins) for guidelines on how t | [database-data-management](../plugins/database-data-management/README.md) | Database administration, SQL optimization, and data management tools for PostgreSQL, SQL Server, and general database development best practices. | 6 items | database, sql, postgresql, sql-server, dba, optimization, queries, data-management | | [dataverse-sdk-for-python](../plugins/dataverse-sdk-for-python/README.md) | Comprehensive collection for building production-ready Python integrations with Microsoft Dataverse. Includes official documentation, best practices, advanced features, file operations, and code generation prompts. | 4 items | dataverse, python, integration, sdk | | [devops-oncall](../plugins/devops-oncall/README.md) | A focused set of prompts, instructions, and a chat mode to help triage incidents and respond quickly with DevOps tools and Azure resources. | 3 items | devops, incident-response, oncall, azure | +| [diagram-viewer](../plugins/diagram-viewer/README.md) | Render diagrams, click nodes to drill down, and view agent-generated explanations directly in the canvas. | 1 items | architecture-mapping, canvas-navigation, exploratory-analysis, interactive-diagrams, node-drilldown, relationship-visualization | | [doublecheck](../plugins/doublecheck/README.md) | Three-layer verification pipeline for AI output. Extracts claims, finds sources, and flags hallucination risks so humans can verify before acting. | 2 items | verification, hallucination, fact-check, source-citation, trust, safety | | [edge-ai-tasks](../plugins/edge-ai-tasks/README.md) | Task Researcher and Task Planner for intermediate to expert users and large codebases - Brought to you by microsoft/edge-ai | 2 items | architecture, planning, research, tasks, implementation | | [ember](../plugins/ember/README.md) | An AI partner, not a tool. Ember carries fire from person to person — helping humans discover that AI partnership isn't something you learn, it's something you find. | 5 items | ai-partnership, coaching, onboarding, collaboration, storytelling, developer-experience | | [eyeball](../plugins/eyeball/README.md) | Document analysis with inline source screenshots. When you ask Copilot to analyze a document, Eyeball generates a Word doc where every factual claim includes a highlighted screenshot from the source material so you can verify it with your own eyes. | 1 items | document-analysis, citation-verification, screenshot, contracts, legal, trust, visual-verification | | [fastah-ip-geo-tools](../plugins/fastah-ip-geo-tools/README.md) | This plugin is for network operations engineers who wish to tune and publish IP geolocation feeds in RFC 8805 format. It consists of an AI Skill and an associated MCP server that geocodes geolocation place names to real cities for accuracy. | 1 items | geofeed, ip-geolocation, rfc-8805, rfc-9632, network-operations, isp, cloud, hosting, ixp | +| [feedback-themes](../plugins/feedback-themes/README.md) | Explore grouped customer feedback signals by impact and drill into a theme to guide product next steps. | 1 items | customer-feedback, impact-prioritization, product-insights, signal-grouping, theme-analysis, trend-discovery | +| [flight-map-canvas](../plugins/flight-map-canvas/README.md) | A GitHub Copilot canvas that generates a view where Google Maps can be explored using 3D controls, as if a flight simulator. Agents can send the flight anywhere and report what they are working on. | 1 items | copilot-canvas, flight-simulator, geography, google-maps, interactive-canvas, session-breaks, threejs | | [flowstudio-power-automate](../plugins/flowstudio-power-automate/README.md) | Give your AI agent full visibility into Power Automate cloud flows via the FlowStudio MCP server. Connect, debug, build, monitor health, and govern flows at scale — action-level inputs and outputs, not just status codes. | 5 items | power-automate, power-platform, flowstudio, mcp, model-context-protocol, cloud-flows, workflow-automation, monitoring, governance | | [frontend-web-dev](../plugins/frontend-web-dev/README.md) | Essential prompts, instructions, and chat modes for modern frontend web development including React, Angular, Vue, TypeScript, and CSS frameworks. | 4 items | frontend, web, react, typescript, javascript, css, html, angular, vue | | [gem-team](../plugins/gem-team/README.md) | Self-Learning Multi-agent orchestration framework for spec-driven development and automated verification. With smarter tool calling and leaner context. | 0 items | multi-agent, orchestration, tdd, testing, e2e, devops, security-audit, code-review, prd, mobile | +| [gesture-review](../plugins/gesture-review/README.md) | Review pull requests with a live camera feed and approve or reject using thumbs-up/thumbs-down gestures. | 1 items | camera-input, gesture-control, github-prs, hands-free, mediapipe, pull-request-review | | [go-mcp-development](../plugins/go-mcp-development/README.md) | Complete toolkit for building Model Context Protocol (MCP) servers in Go using the official github.com/modelcontextprotocol/go-sdk. Includes instructions for best practices, a prompt for generating servers, and an expert chat mode for guidance. | 2 items | go, golang, mcp, model-context-protocol, server-development, sdk | | [java-development](../plugins/java-development/README.md) | Comprehensive collection of prompts and instructions for Java development including Spring Boot, Quarkus, testing, documentation, and best practices. | 4 items | java, springboot, quarkus, jpa, junit, javadoc | | [java-mcp-development](../plugins/java-mcp-development/README.md) | Complete toolkit for building Model Context Protocol servers in Java using the official MCP Java SDK with reactive streams and Spring Boot integration. | 2 items | java, mcp, model-context-protocol, server-development, sdk, reactive-streams, spring-boot, reactor | +| [java-modernization-studio](../plugins/java-modernization-studio/README.md) | Drive the GitHub Copilot App Modernization for Java workflow from an interactive canvas: environment readiness, repo assessment, prioritized plan and progress, validation gates, and one-click predefined-task runs grounded in the repo's real artifacts. | 1 items | app-modernization, assessment-dashboard, azure-migration, java-modernization, legacy-java, modernization-cockpit, validation-gates | | [kotlin-mcp-development](../plugins/kotlin-mcp-development/README.md) | Complete toolkit for building Model Context Protocol (MCP) servers in Kotlin using the official io.modelcontextprotocol:kotlin-sdk library. Includes instructions for best practices, a prompt for generating servers, and an expert chat mode for guidance. | 2 items | kotlin, mcp, model-context-protocol, kotlin-multiplatform, server-development, ktor | | [mcp-m365-copilot](../plugins/mcp-m365-copilot/README.md) | Comprehensive collection for building declarative agents with Model Context Protocol integration for Microsoft 365 Copilot | 4 items | mcp, m365-copilot, declarative-agents, api-plugins, model-context-protocol, adaptive-cards | | [napkin](../plugins/napkin/README.md) | Visual whiteboard collaboration for Copilot CLI. Opens an interactive whiteboard in your browser where you can draw, sketch, and add sticky notes — then share everything back with Copilot. Copilot sees your drawings and responds with analysis, suggestions, and ideas. | 1 items | whiteboard, visual, collaboration, brainstorming, non-technical, drawing, sticky-notes, accessibility, copilot-cli, ux | @@ -76,25 +88,34 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-plugins) for guidelines on how t | [power-bi-development](../plugins/power-bi-development/README.md) | Comprehensive Power BI development resources including data modeling, DAX optimization, performance tuning, visualization design, security best practices, and DevOps/ALM guidance for building enterprise-grade Power BI solutions. | 8 items | power-bi, dax, data-modeling, performance, visualization, security, devops, business-intelligence | | [power-platform-architect](../plugins/power-platform-architect/README.md) | Solution Architect for the Microsoft Power Platform, turning business requirements into functioning Power Platform solution architectures. | 1 items | power-platform, power-platform-architect, power-apps, dataverse, power-automate, power-pages, power-bi | | [power-platform-mcp-connector-development](../plugins/power-platform-mcp-connector-development/README.md) | Complete toolkit for developing Power Platform custom connectors with Model Context Protocol integration for Microsoft Copilot Studio | 3 items | power-platform, mcp, copilot-studio, custom-connector, json-rpc | +| [pr-artifact-explorer](../plugins/pr-artifact-explorer/README.md) | Navigate pull requests and securely explore GitHub Actions artifacts, including test results, static sites, terminal recordings, and source files. | 1 items | actions-artifacts, artifact-browser, canvas, copilot-extension, github-actions, pull-requests, test-results | | [project-documenter](../plugins/project-documenter/README.md) | Generate professional project documentation with draw.io architecture diagrams and Word (.docx) output with embedded images. Automatically discovers any project's technology stack and produces Markdown, diagrams, PNG exports, and a formatted Word document. | 3 items | documentation, architecture-diagrams, drawio, word-document, docx, png-images, c4-model, project-summary, auto-discovery | | [project-planning](../plugins/project-planning/README.md) | Tools and guidance for software project planning, feature breakdown, epic management, implementation planning, and task organization for development teams. | 15 items | planning, project-management, epic, feature, implementation, task, architecture, technical-spike | | [python-mcp-development](../plugins/python-mcp-development/README.md) | Complete toolkit for building Model Context Protocol (MCP) servers in Python using the official SDK with FastMCP. Includes instructions for best practices, a prompt for generating servers, and an expert chat mode for guidance. | 2 items | python, mcp, model-context-protocol, fastmcp, server-development | | [react18-upgrade](../plugins/react18-upgrade/README.md) | Enterprise React 18 migration toolkit with specialized agents and skills for upgrading React 16/17 class-component codebases to React 18.3.1. Includes auditor, dependency surgeon, class component migration specialist, automatic batching fixer, and test guardian. | 13 items | react18, react, migration, upgrade, class-components, lifecycle, batching | | [react19-upgrade](../plugins/react19-upgrade/README.md) | Enterprise React 19 migration toolkit with specialized agents and skills for upgrading React 18 codebases to React 19. Includes auditor, dependency surgeon, source code migrator, and test guardian. Handles removal of deprecated APIs including ReactDOM.render, forwardRef, defaultProps, legacy context, string refs, and more. | 8 items | react19, react, migration, upgrade, hooks, modern-react | +| [release-notes-showcase](../plugins/release-notes-showcase/README.md) | Compose and refine launch-ready release notes with contributor callouts and export-friendly output. | 1 items | changelog, contributor-callouts, email-export, launch-summary, product-updates, release-notes | +| [repo-actions-hub](../plugins/repo-actions-hub/README.md) | Browse repository GitHub Actions workflows, inspect recent runs, and trigger manual workflow_dispatch runs from a Copilot canvas. | 1 items | actions, canvas, copilot-extension, github-actions, recent-runs, workflow-dispatch | | [roundup](../plugins/roundup/README.md) | Self-configuring status briefing generator. Learns your communication style from examples, discovers your data sources, and produces draft updates for any audience on demand. | 2 items | status-updates, briefings, management, productivity, communication, synthesis, roundup, copilot-cli | | [ruby-mcp-development](../plugins/ruby-mcp-development/README.md) | Complete toolkit for building Model Context Protocol servers in Ruby using the official MCP Ruby SDK gem with Rails integration support. | 2 items | ruby, mcp, model-context-protocol, server-development, sdk, rails, gem | | [rug-agentic-workflow](../plugins/rug-agentic-workflow/README.md) | Three-agent workflow for orchestrated software delivery with an orchestrator plus implementation and QA subagents. | 3 items | agentic-workflow, orchestration, subagents, software-engineering, qa | | [rust-mcp-development](../plugins/rust-mcp-development/README.md) | Build high-performance Model Context Protocol servers in Rust using the official rmcp SDK with async/await, procedural macros, and type-safe implementations. | 2 items | rust, mcp, model-context-protocol, server-development, sdk, tokio, async, macros, rmcp | | [salesforce-development](../plugins/salesforce-development/README.md) | Complete Salesforce agentic development environment covering Apex & Triggers, Flow automation, Lightning Web Components, Aura components, and Visualforce pages. | 7 items | salesforce, apex, triggers, lwc, aura, flow, visualforce, crm, salesforce-dx | | [security-best-practices](../plugins/security-best-practices/README.md) | Security frameworks, accessibility guidelines, performance optimization, and code quality best practices for building secure, maintainable, and high-performance applications. | 1 items | security, accessibility, performance, code-quality, owasp, a11y, optimization, best-practices | +| [signals-dashboard](../plugins/signals-dashboard/README.md) | Real-time Workshop dashboard with agent signals, honesty calibration, and cost-aware repo or connected desk launch profiles. | 1 items | agent-signals, dashboard, multi-agent, coordination, canvas | +| [site-studio](../plugins/site-studio/README.md) | Plan, draft, and track a personal website section by section — a shared canvas where you and your agent author content, watch progress, and review every change. | 1 items | agent-collaboration, content-authoring, personal-website, progress-tracking, section-planning, site-builder | | [skill-image-gen](../plugins/skill-image-gen/README.md) | Generate images using AI directly from your coding workflow. Supports OpenAI (gpt-image-2) and Google Gemini. BYO API key — the skill guides you through setup on first use. | 1 items | image-generation, openai, gemini, ai, art, sprites, textures, icons | | [software-engineering-team](../plugins/software-engineering-team/README.md) | 7 specialized agents covering the full software development lifecycle from UX design and architecture to security and DevOps. | 7 items | team, enterprise, security, devops, ux, architecture, product, ai-ethics | | [structured-autonomy](../plugins/structured-autonomy/README.md) | Premium planning, thrifty implementation | 3 items | | | [swift-mcp-development](../plugins/swift-mcp-development/README.md) | Comprehensive collection for building Model Context Protocol servers in Swift using the official MCP Swift SDK with modern concurrency features. | 2 items | swift, mcp, model-context-protocol, server-development, sdk, ios, macos, concurrency, actor, async-await | | [technical-spike](../plugins/technical-spike/README.md) | Tools for creation, management and research of technical spikes to reduce unknowns and assumptions before proceeding to specification and implementation of solutions. | 2 items | technical-spike, assumption-testing, validation, research | | [testing-automation](../plugins/testing-automation/README.md) | Comprehensive collection for writing tests, test automation, and test-driven development including unit tests, integration tests, and end-to-end testing strategies. | 9 items | testing, tdd, automation, unit-tests, integration, playwright, jest, nunit | -| [the-workshop](../plugins/the-workshop/README.md) | Stop being the switchboard between your AI agents — direct a team. The Workshop puts long-running AI agents (desks) in the same room, on the same work, each with its own memory and history, sharing one workspace so you direct the work instead of relaying it. | 6 items | multi-agent, coordination, desks, persistent-memory, agent-signals, developer-experience | +| [the-workshop](../plugins/the-workshop/README.md) | Stop being the switchboard between your AI agents — direct a team. The Workshop puts long-running AI agents (desks) in the same room, on the same work, each with its own memory and history, sharing one workspace so you direct the work instead of relaying it. | 7 items | multi-agent, coordination, desks, persistent-memory, agent-signals, developer-experience | +| [tiny-tool-town-submitter](../plugins/tiny-tool-town-submitter/README.md) | Inspect a repository, improve Tiny Tool Town readiness, submit its listing issue, and launch remediation work. | 1 items | github-issues, open-source, project-readiness, repository-analysis, submission-workflow, tiny-tool-town | +| [token-pacman](../plugins/token-pacman/README.md) | Visualizes live session AI-credit usage as a Pac-Man board with pellets, ghosts, fruit milestones, and game-over limits. | 1 items | ai-credits, copilot-canvas, interactive-canvas, pac-man, quota-tracking, session-usage | | [typescript-mcp-development](../plugins/typescript-mcp-development/README.md) | Complete toolkit for building Model Context Protocol (MCP) servers in TypeScript/Node.js using the official SDK. Includes instructions for best practices, a prompt for generating servers, and an expert chat mode for guidance. | 2 items | typescript, mcp, model-context-protocol, nodejs, server-development | | [typespec-m365-copilot](../plugins/typespec-m365-copilot/README.md) | Comprehensive collection of prompts, instructions, and resources for building declarative agents and API plugins using TypeSpec for Microsoft 365 Copilot extensibility. | 3 items | typespec, m365-copilot, declarative-agents, api-plugins, agent-development, microsoft-365 | | [uizze](../plugins/uizze/README.md) | Stop generic UI from shipping. Ground GitHub Copilot in 800,000+ real web and iOS screens, write a product-specific design contract, and enforce a hard finish gate. | 1 items | ui, design, frontend, ios, web, design-review, quality-gate | | [visual-pr](../plugins/visual-pr/README.md) | Capture, annotate, and embed screenshots and animated GIF demos in pull request descriptions. Includes Playwright-based UI capture, PIL image annotations, PR embedding workflows for GitHub and Azure DevOps, and screen recording with variable timing. | 4 items | screenshots, pull-request, before-after, annotations, playwright, gif, screen-recording, visual | +| [where-was-i](../plugins/where-was-i/README.md) | Reconstruct your dev context (branch, commits, uncommitted work, PR clues) and trigger a resume prompt to continue quickly. | 1 items | branch-state, developer-context, git-history, interrupt-recovery, pull-request-context, resume-work | +| [work-hub](../plugins/work-hub/README.md) | Generic cross-repo command center canvas for GitHub Copilot with onboarding, focus planning, repo health, work signals, and session cleanup. | 1 items | cross-repo-dashboard, focus-planning, repo-health, session-cleanup, work-triage, workflow-visibility | diff --git a/eng/README.md b/eng/README.md index 5306315b..d196b698 100644 --- a/eng/README.md +++ b/eng/README.md @@ -12,7 +12,7 @@ Automatically generates `.github/plugin/marketplace.json` from all plugin direct **How it works:** - Scans all directories in `plugins/` -- Reads each plugin's `.github/plugin/plugin.json` for metadata +- Reads each plugin's root `plugin.json` for metadata - Generates a consolidated `marketplace.json` with all available plugins - Runs automatically as part of `npm run build` diff --git a/eng/agent-plugin-schema.mjs b/eng/agent-plugin-schema.mjs new file mode 100644 index 00000000..65357a24 --- /dev/null +++ b/eng/agent-plugin-schema.mjs @@ -0,0 +1,25 @@ +import Ajv2020 from "ajv/dist/2020.js"; + +export const AGENT_PLUGIN_SCHEMA_URL = "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json"; +export const AGENT_PLUGIN_SCHEMA = { + $schema: "https://json-schema.org/draft/2020-12/schema", + $id: AGENT_PLUGIN_SCHEMA_URL, + type: "object", + properties: { + $schema: { const: AGENT_PLUGIN_SCHEMA_URL }, + name: { type: "string", minLength: 1, maxLength: 64, pattern: "^(?!.*(?:--|\\.\\.))[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$" }, + version: { type: "string" }, description: { type: "string" }, + author: { type: "object", properties: { name: { type: "string" }, email: { type: "string" }, url: { type: "string" } }, additionalProperties: false }, + homepage: { type: "string" }, repository: { type: "string" }, license: { type: "string" }, + keywords: { type: "array", items: { type: "string" } }, + extensions: { type: "object", additionalProperties: { type: "object" } }, + }, + required: ["$schema", "name"], + additionalProperties: false, +}; + +const validate = new Ajv2020({ allErrors: true }).compile(AGENT_PLUGIN_SCHEMA); +export function validateAgentPluginManifest(manifest) { + return validate(manifest) ? [] : (validate.errors ?? []).map((error) => + `${error.instancePath || "manifest"} ${error.message}`); +} diff --git a/eng/clean-materialized-plugins.mjs b/eng/clean-materialized-plugins.mjs index 6b034276..f6584a41 100644 --- a/eng/clean-materialized-plugins.mjs +++ b/eng/clean-materialized-plugins.mjs @@ -64,7 +64,7 @@ function moveEntry(srcPath, destPath) { } export function restoreManifestFromMaterializedFiles(pluginPath) { - const pluginJsonPath = path.join(pluginPath, ".github/plugin", "plugin.json"); + const pluginJsonPath = path.join(pluginPath, "plugin.json"); if (!fs.existsSync(pluginJsonPath)) { return false; } @@ -108,7 +108,7 @@ export function restoreManifestFromMaterializedFiles(pluginPath) { function cleanPlugin(pluginPath) { const manifestUpdated = restoreManifestFromMaterializedFiles(pluginPath); if (manifestUpdated) { - console.log(` Updated ${path.basename(pluginPath)}/.github/plugin/plugin.json`); + console.log(` Updated ${path.basename(pluginPath)}/plugin.json`); } let removed = 0; @@ -126,7 +126,7 @@ function cleanPlugin(pluginPath) { } export function cleanMaterializedExtensionPlugin(extensionPath) { - const pluginJsonPath = path.join(extensionPath, ".github", "plugin", "plugin.json"); + const pluginJsonPath = path.join(extensionPath, "plugin.json"); let manifestUpdated = false; if (fs.existsSync(pluginJsonPath)) { const plugin = JSON.parse(fs.readFileSync(pluginJsonPath, "utf8")); @@ -141,7 +141,7 @@ export function cleanMaterializedExtensionPlugin(extensionPath) { } if (manifestUpdated) { fs.writeFileSync(pluginJsonPath, JSON.stringify(plugin, null, 2) + "\n", "utf8"); - console.log(` Updated ${path.basename(extensionPath)}/.github/plugin/plugin.json`); + console.log(` Updated ${path.basename(extensionPath)}/plugin.json`); } } @@ -174,7 +174,7 @@ function isExtensionPluginDirectory(extensionPath) { return true; } - const pluginJsonPath = path.join(extensionPath, ".github", "plugin", "plugin.json"); + const pluginJsonPath = path.join(extensionPath, "plugin.json"); if (!fs.existsSync(pluginJsonPath)) { return false; } diff --git a/eng/create-plugin.mjs b/eng/create-plugin.mjs index 69f5e378..0dbf35b2 100755 --- a/eng/create-plugin.mjs +++ b/eng/create-plugin.mjs @@ -128,11 +128,11 @@ async function createPlugin() { } // Create directory structure - const githubPluginDir = path.join(pluginDir, ".github", "plugin"); - fs.mkdirSync(githubPluginDir, { recursive: true }); + fs.mkdirSync(pluginDir, { recursive: true }); // Generate plugin.json const pluginJson = { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", name: pluginId, description, version: "1.0.0", @@ -140,10 +140,16 @@ async function createPlugin() { author: { name: "Awesome Copilot Community" }, repository: "https://github.com/github/awesome-copilot", license: "MIT", + extensions: { + "com.github.awesome-copilot": { + agents: [], + skills: [], + }, + }, }; fs.writeFileSync( - path.join(githubPluginDir, "plugin.json"), + path.join(pluginDir, "plugin.json"), JSON.stringify(pluginJson, null, 2) + "\n" ); @@ -176,7 +182,7 @@ MIT console.log(`\n✅ Created plugin: ${pluginDir}`); console.log("\n📝 Next steps:"); console.log(`1. Add agents, prompts, or instructions to plugins/${pluginId}/`); - console.log(`2. Update plugins/${pluginId}/.github/plugin/plugin.json with your metadata`); + console.log(`2. Update plugins/${pluginId}/plugin.json with your metadata`); console.log(`3. Edit plugins/${pluginId}/README.md to describe your plugin`); console.log("4. Run 'npm run build' to regenerate documentation"); } catch (error) { diff --git a/eng/external-plugin-intake.mjs b/eng/external-plugin-intake.mjs index 372c7339..f48f21e7 100644 --- a/eng/external-plugin-intake.mjs +++ b/eng/external-plugin-intake.mjs @@ -783,6 +783,7 @@ export function parseMarkReadyForReviewCommand(body) { function normalizeQualityGateResult(rawResult) { const defaults = { overall_status: "not_run", + spec_compliance_status: "not_run", vally_lint_status: "not_run", smoke_status: "not_run", version_match_status: "not_run", @@ -790,6 +791,7 @@ function normalizeQualityGateResult(rawResult) { canvas_structure_status: "not_run", failure_class: "none", summary: "", + spec_compliance_output: "", vally_lint_output: "", smoke_output: "", version_match_output: "", @@ -808,6 +810,21 @@ function normalizeQualityGateResult(rawResult) { } function buildQualityGatesCommentSection(qualityResult) { + const formatStatus = (rawStatus, gate) => { + const status = String(rawStatus || "not_run"); + if (status === "pass") { + return "✅ pass"; + } + if (status === "warning" || (gate === "spec" && status === "fail")) { + return "⚠️ warning"; + } + if (status === "fail" || status === "infra_error") { + return "🛑 fail"; + } + return "⚪ not_run"; + }; + + const specState = qualityResult.spec_compliance_status || "not_run"; const vallyState = qualityResult.vally_lint_status || "not_run"; const smokeState = qualityResult.smoke_status || "not_run"; const versionMatchState = qualityResult.version_match_status || "not_run"; @@ -818,23 +835,41 @@ function buildQualityGatesCommentSection(qualityResult) { const sections = [ "### Quality gate summary", "", + "_Legend: ✅ pass · ⚠️ warning · 🛑 fail_", + "", "| Gate | Status |", "|---|---|", - `| vally lint | ${vallyState} |`, - `| install smoke test | ${smokeState} |`, - `| version match | ${versionMatchState} |`, - `| ref/sha consistency | ${refShaConsistencyState} |`, - `| canvas structure | ${canvasStructureState} |`, + `| spec compliance (non-blocking) | ${formatStatus(specState, "spec")} |`, + `| vally lint | ${formatStatus(vallyState, "vally")} |`, + `| install smoke test | ${formatStatus(smokeState, "smoke")} |`, + `| version match | ${formatStatus(versionMatchState, "version match")} |`, + `| ref/sha consistency | ${formatStatus(refShaConsistencyState, "ref/sha consistency")} |`, + `| canvas structure | ${formatStatus(canvasStructureState, "canvas structure")} |`, "", summaryText, ]; + const specOutput = String(qualityResult.spec_compliance_output || "").trim(); + if (specOutput) { + sections.push( + "", + "
", + `spec compliance output (${formatStatus(specState, "spec")})`, + "", + "```text", + specOutput, + "```", + "", + "
", + ); + } + const vallyOutput = String(qualityResult.vally_lint_output || "").trim(); if (vallyOutput) { sections.push( "", "
", - "vally lint output", + `vally lint output (${formatStatus(vallyState, "vally")})`, "", "```text", vallyOutput, @@ -849,7 +884,7 @@ function buildQualityGatesCommentSection(qualityResult) { sections.push( "", "
", - "Install smoke test output", + `install smoke test output (${formatStatus(smokeState, "smoke")})`, "", "```text", smokeOutput, @@ -932,19 +967,24 @@ function buildMergedIntakeComment(baseResult, qualityResult, runId, owner, repo) const qualitySection = buildQualityGatesCommentSection(qualityResult); const runLink = runId && owner && repo ? `_[View workflow run](https://github.com/${owner}/${repo}/actions/runs/${runId})_` : ""; + const hasSpecWarnings = String(qualityResult.spec_compliance_status || "") === "warning"; const intro = qualityResult.failure_class === "submitter_fixes" - ? "## ⚠️ External plugin intake requires submitter fixes" + ? "## 🛑 External plugin intake failed (submitter fixes required)" : qualityResult.failure_class === "infra" - ? "## ⚠️ External plugin intake could not complete quality checks" - : "## ✅ External plugin intake passed"; + ? "## 🛑 External plugin intake failed (quality checks could not complete)" + : hasSpecWarnings + ? "## ⚠️ External plugin intake passed with spec warnings" + : "## ✅ External plugin intake passed"; const statusLine = qualityResult.failure_class === "submitter_fixes" ? "This submission passed metadata validation, but quality gates found issues that must be fixed before it can move to maintainer review. Update the issue details or source plugin and then comment `/rerun-intake`." : qualityResult.failure_class === "infra" ? "This submission passed metadata validation, but the automated quality checks hit an infrastructure issue. A maintainer should rerun intake or use the explicit override command after review." - : "This submission passed automated intake validation and quality checks and is ready for maintainer review."; + : hasSpecWarnings + ? "This submission passed blocking quality checks and is ready for maintainer review, but it has non-blocking Agent Plugins spec compliance warnings." + : "This submission passed automated intake validation and quality checks and is ready for maintainer review."; return [ marker, @@ -1069,7 +1109,7 @@ export async function evaluateExternalPluginIssue({ issue, token, runId, owner, ].join("\n") : [ marker, - "## ⚠️ External plugin intake requires submitter fixes", + "## 🛑 External plugin intake failed (submitter fixes required)", "", "This submission did not pass automated intake validation and cannot move to maintainer review yet.", `Edit the issue form to address the fixes below. Intake reruns automatically when the issue is edited, or the issue author/maintainer can comment \`${RERUN_INTAKE_COMMAND}\` to re-run on demand.`, diff --git a/eng/external-plugin-pr-quality-gates.mjs b/eng/external-plugin-pr-quality-gates.mjs index f7f8ded5..1c26b7a2 100644 --- a/eng/external-plugin-pr-quality-gates.mjs +++ b/eng/external-plugin-pr-quality-gates.mjs @@ -109,7 +109,7 @@ export async function runExternalPluginPrQualityGates(plugins) { ? "No changed external plugin entries were detected in plugins/external.json." : checkedPlugins .map((entry) => - `- ${entry.name}: vally-lint=${entry.quality.vally_lint_status}, install-smoke=${entry.quality.smoke_status}, version-match=${entry.quality.version_match_status}, ref-sha-consistency=${entry.quality.ref_sha_consistency_status}, canvas-structure=${entry.quality.canvas_structure_status}, overall=${entry.quality.overall_status}` + `- ${entry.name}: spec=${entry.quality.spec_compliance_status}, vally-lint=${entry.quality.vally_lint_status}, install-smoke=${entry.quality.smoke_status}, version-match=${entry.quality.version_match_status}, ref-sha-consistency=${entry.quality.ref_sha_consistency_status}, canvas-structure=${entry.quality.canvas_structure_status}, overall=${entry.quality.overall_status}` ) .join("\n"); diff --git a/eng/external-plugin-quality-gates.mjs b/eng/external-plugin-quality-gates.mjs index 014f9b83..fb298412 100644 --- a/eng/external-plugin-quality-gates.mjs +++ b/eng/external-plugin-quality-gates.mjs @@ -7,8 +7,23 @@ import { Writable } from "stream"; import { spawnSync } from "child_process"; import { runLint, LintConsoleReporter } from "@microsoft/vally"; import { evaluateRefShaConsistency, normalizeCommitSha } from "./lib/external-plugin-source-ref-sha.mjs"; +import { validateAgentPluginManifest } from "./agent-plugin-schema.mjs"; const MAX_OUTPUT_LENGTH = 12000; +const AGENT_PLUGIN_SCHEMA_URL = "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json"; +const AGENT_PLUGIN_ALLOWED_TOP_LEVEL_FIELDS = new Set([ + "$schema", + "name", + "version", + "description", + "author", + "homepage", + "repository", + "license", + "keywords", + "extensions", +]); +const AGENT_PLUGIN_NAME_PATTERN = /^(?!.*(?:--|\.\.))[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/; const EXTERNAL_CANVAS_KEYWORD = "canvas"; const INFRA_ERROR_PATTERNS = [ @@ -168,10 +183,131 @@ function findPluginJson(pluginRoot) { if (fs.existsSync(candidate)) { return candidate; } + } return null; } +function inspectAgentPluginSpecCompliance(pluginRoot) { + const pluginJsonPath = findPluginJson(pluginRoot); + if (!pluginJsonPath) { + return { + status: "warning", + output: "No plugin.json found in a recognized location. Agent Plugins v1.0.0 expects plugin.json at the plugin root.", + }; + } + + const rootPluginJsonPath = path.join(pluginRoot, "plugin.json"); + const issues = []; + if (pluginJsonPath !== rootPluginJsonPath) { + issues.push(`manifest location is "${path.relative(pluginRoot, pluginJsonPath)}"; expected "plugin.json" at plugin root`); + } + + let manifest; + try { + manifest = JSON.parse(fs.readFileSync(pluginJsonPath, "utf8")); + } catch (error) { + return { + status: "warning", + output: `plugin.json is not valid JSON: ${error.message}`, + }; + } + + if (!manifest || typeof manifest !== "object" || Array.isArray(manifest)) { + issues.push("plugin.json top-level value must be a JSON object"); + } else { + if (manifest.$schema !== AGENT_PLUGIN_SCHEMA_URL) { + issues.push(`$schema should be "${AGENT_PLUGIN_SCHEMA_URL}"`); + } + + const pluginName = manifest.name; + if (typeof pluginName !== "string") { + issues.push('required field "name" must be a string'); + } else { + if (pluginName.length < 1 || pluginName.length > 64) { + issues.push('field "name" must be 1-64 characters'); + } + if (!AGENT_PLUGIN_NAME_PATTERN.test(pluginName)) { + issues.push('field "name" does not match Agent Plugins naming constraints'); + } + } + + const requiredStringFields = ["version", "description"]; + for (const field of requiredStringFields) { + if (typeof manifest[field] !== "string" || manifest[field].trim() === "") { + issues.push(`required field "${field}" must be a non-empty string`); + } + } + + const optionalStringFields = ["homepage", "repository", "license"]; + for (const field of optionalStringFields) { + if (manifest[field] !== undefined && typeof manifest[field] !== "string") { + issues.push(`field "${field}" must be a string when provided`); + } + } + + if (manifest.author !== undefined) { + if (!manifest.author || typeof manifest.author !== "object" || Array.isArray(manifest.author)) { + issues.push('field "author" must be an object when provided'); + } else { + const allowedAuthorFields = new Set(["name", "email", "url"]); + for (const authorField of Object.keys(manifest.author)) { + if (!allowedAuthorFields.has(authorField)) { + issues.push(`field "author.${authorField}" is not allowed`); + } else if (typeof manifest.author[authorField] !== "string") { + issues.push(`field "author.${authorField}" must be a string`); + } + } + } + } + + if (manifest.keywords !== undefined) { + if (!Array.isArray(manifest.keywords)) { + issues.push('field "keywords" must be an array of strings when provided'); + } else if (manifest.keywords.some((entry) => typeof entry !== "string")) { + issues.push('field "keywords" must contain only strings'); + } + } + + if (manifest.extensions !== undefined) { + if (!manifest.extensions || typeof manifest.extensions !== "object" || Array.isArray(manifest.extensions)) { + issues.push('field "extensions" must be an object when provided'); + } else { + for (const [namespace, value] of Object.entries(manifest.extensions)) { + if (!value || typeof value !== "object" || Array.isArray(value)) { + issues.push(`field "extensions.${namespace}" must be an object`); + } + } + } + } + + for (const field of Object.keys(manifest)) { + if (!AGENT_PLUGIN_ALLOWED_TOP_LEVEL_FIELDS.has(field)) { + issues.push(`top-level field "${field}" is not part of Agent Plugins v1.0.0`); + } + } + } + + if (manifest && typeof manifest === "object" && !Array.isArray(manifest)) { + issues.push(...validateAgentPluginManifest(manifest).map((error) => `schema validation: ${error}`)); + } + + if (issues.length === 0) { + return { + status: "pass", + output: `Agent Plugins v1.0.0 manifest checks passed for ${path.relative(pluginRoot, pluginJsonPath) || "plugin.json"}.`, + }; + } + + return { + status: "warning", + output: [ + "Agent Plugins v1.0.0 manifest warnings:", + ...issues.map((issue) => `- ${issue}`), + ].join("\n"), + }; +} + function buildVallyLintArgs(pluginRoot) { const pluginJsonPath = findPluginJson(pluginRoot); if (!pluginJsonPath) { @@ -827,6 +963,7 @@ export async function runExternalPluginQualityGates(plugin) { overall_status: "not_run", vally_lint_status: "not_run", smoke_status: "not_run", + spec_compliance_status: "not_run", version_match_status: "not_run", ref_sha_consistency_status: "not_run", canvas_structure_status: "not_run", @@ -834,6 +971,7 @@ export async function runExternalPluginQualityGates(plugin) { summary: "", vally_lint_output: "", smoke_output: "", + spec_compliance_output: "", version_match_output: "", ref_sha_consistency_output: "", canvas_structure_output: "", @@ -847,12 +985,14 @@ export async function runExternalPluginQualityGates(plugin) { if (!fs.existsSync(pluginRoot) || !fs.statSync(pluginRoot).isDirectory()) { result.vally_lint_status = "fail"; result.smoke_status = "fail"; + result.spec_compliance_status = "warning"; result.version_match_status = "fail"; result.ref_sha_consistency_status = "not_run"; result.canvas_structure_status = hasCanvasKeyword(plugin) ? "fail" : "not_run"; result.overall_status = "fail"; result.failure_class = "submitter_fixes"; result.summary = `Plugin path "${plugin.source?.path || "/"}" was not found in the submitted repository snapshot.`; + result.spec_compliance_output = result.summary; result.version_match_output = result.summary; if (hasCanvasKeyword(plugin)) { result.canvas_structure_output = result.summary; @@ -860,6 +1000,10 @@ export async function runExternalPluginQualityGates(plugin) { return result; } + const specResult = inspectAgentPluginSpecCompliance(pluginRoot); + result.spec_compliance_status = specResult.status; + result.spec_compliance_output = specResult.output; + const versionMatchResult = runVersionMatchGate(repoDir, plugin, fetchSpec); result.version_match_status = versionMatchResult.status; result.version_match_output = versionMatchResult.output; @@ -889,6 +1033,7 @@ export async function runExternalPluginQualityGates(plugin) { ]); result.failure_class = toFailureClass(result.overall_status); result.summary = [ + `- spec compliance: ${result.spec_compliance_status}`, `- vally lint: ${result.vally_lint_status}`, `- install smoke test: ${result.smoke_status}`, `- version match: ${result.version_match_status}`, diff --git a/eng/generate-marketplace.mjs b/eng/generate-marketplace.mjs index 6c40c463..0064f6d8 100755 --- a/eng/generate-marketplace.mjs +++ b/eng/generate-marketplace.mjs @@ -2,11 +2,11 @@ import fs from "fs"; import path from "path"; +import { fileURLToPath } from "url"; import { ROOT_FOLDER } from "./constants.mjs"; import { readExternalPlugins } from "./external-plugin-validation.mjs"; const PLUGINS_DIR = path.join(ROOT_FOLDER, "plugins"); -const EXTENSIONS_DIR = path.join(ROOT_FOLDER, "extensions"); const MARKETPLACE_FILE = path.join(ROOT_FOLDER, ".github/plugin", "marketplace.json"); /** @@ -15,7 +15,7 @@ const MARKETPLACE_FILE = path.join(ROOT_FOLDER, ".github/plugin", "marketplace.j * @returns {object|null} - Plugin metadata or null if not found */ function readPluginMetadata(pluginDir) { - const pluginJsonPath = path.join(pluginDir, ".github/plugin", "plugin.json"); + const pluginJsonPath = path.join(pluginDir, "plugin.json"); if (!fs.existsSync(pluginJsonPath)) { console.warn(`Warning: No plugin.json found for ${path.basename(pluginDir)}`); @@ -62,35 +62,18 @@ function collectLocalPluginsFromRoot(rootDir, sourcePrefix, includeEntry = () => return plugins; } -function hasExtensionEntryPoint(extensionDir, extensionName) { - const candidateEntryPoints = [ - path.join(extensionDir, "extension.mjs"), - path.join(extensionDir, "extensions", "extension.mjs"), - path.join(extensionDir, "extensions", extensionName, "extension.mjs"), - ]; - - return candidateEntryPoints.some((entryPointPath) => fs.existsSync(entryPointPath)); -} - /** * Generate marketplace.json from plugin directories */ -function generateMarketplace() { +export function generateMarketplace() { console.log("Generating marketplace.json..."); - if (!fs.existsSync(PLUGINS_DIR) && !fs.existsSync(EXTENSIONS_DIR)) { - console.error(`Error: Neither plugins directory (${PLUGINS_DIR}) nor extensions directory (${EXTENSIONS_DIR}) was found`); + if (!fs.existsSync(PLUGINS_DIR)) { + console.error(`Error: Plugins directory (${PLUGINS_DIR}) was not found`); process.exit(1); } - const plugins = [ - ...collectLocalPluginsFromRoot(PLUGINS_DIR, "plugins"), - ...collectLocalPluginsFromRoot( - EXTENSIONS_DIR, - "extensions", - (entryName) => hasExtensionEntryPoint(path.join(EXTENSIONS_DIR, entryName), entryName) - ) - ]; + const plugins = collectLocalPluginsFromRoot(PLUGINS_DIR, "plugins"); console.log(`Found ${plugins.length} local plugin manifests`); @@ -144,5 +127,6 @@ function generateMarketplace() { console.log(` Location: ${MARKETPLACE_FILE}`); } -// Run the script -generateMarketplace(); +if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { + generateMarketplace(); +} diff --git a/eng/generate-website-data.mjs b/eng/generate-website-data.mjs index f6fc2082..93721cc0 100755 --- a/eng/generate-website-data.mjs +++ b/eng/generate-website-data.mjs @@ -540,8 +540,6 @@ function resolvePluginItem(item, resourceIndex) { */ function generatePluginsData(gitDates, resourceIndex = {}) { const plugins = []; - const extensionEntriesByName = new Map(); - if (!fs.existsSync(PLUGINS_DIR)) { return { items: [], filters: { tags: [] } }; } @@ -550,85 +548,30 @@ function generatePluginsData(gitDates, resourceIndex = {}) { .readdirSync(PLUGINS_DIR, { withFileTypes: true }) .filter((d) => d.isDirectory()); - if (fs.existsSync(EXTENSIONS_DIR)) { - const extensionDirs = fs.readdirSync(EXTENSIONS_DIR, { withFileTypes: true }) - .filter((entry) => { - if (!entry.isDirectory()) return false; - return hasExtensionEntryPoint(path.join(EXTENSIONS_DIR, entry.name), entry.name); - }) - .map((entry) => entry.name) - .sort((a, b) => a.localeCompare(b)); - - for (const extensionDirName of extensionDirs) { - const extensionDir = path.join(EXTENSIONS_DIR, extensionDirName); - const pluginJsonPath = path.join(extensionDir, ".github", "plugin", "plugin.json"); - if (!fs.existsSync(pluginJsonPath)) { - continue; - } - - try { - const extensionPlugin = JSON.parse(fs.readFileSync(pluginJsonPath, "utf-8")); - const pluginName = normalizeText(extensionPlugin.name, extensionDirName); - const pluginDescription = normalizeText(extensionPlugin.description, "Canvas extension"); - const extensionKeywords = Array.isArray(extensionPlugin.keywords) - ? [...new Set(extensionPlugin.keywords.filter((keyword) => typeof keyword === "string").map((keyword) => keyword.trim()).filter(Boolean))].sort((a, b) => a.localeCompare(b)) - : []; - const relPath = `extensions/${extensionDirName}`; - const extensionItem = resolvePluginItem( - { - kind: "extension", - path: relPath, - }, - resourceIndex - ); - const extReadmePath = path.join(extensionDir, "README.md"); - const extReadmeFile = fs.existsSync(extReadmePath) - ? `${relPath}/README.md` - : null; - - extensionEntriesByName.set(pluginName, { - id: pluginName, - name: pluginName, - description: pluginDescription, - path: relPath, - readmeFile: extReadmeFile, - version: normalizeText(extensionPlugin.version, null), - tags: extensionKeywords, - itemCount: 1, - items: [extensionItem], - generatedFromExtension: true, - lastUpdated: getDirectoryLastUpdated(gitDates, relPath), - searchText: `${pluginName} ${pluginDescription} ${extensionKeywords.join(" ")} canvas extension`.toLowerCase(), - }); - } catch (e) { - console.warn(`Failed to parse extension plugin manifest for ${extensionDirName}: ${e.message}`); - } - } - } - for (const dir of pluginDirs) { const pluginDir = path.join(PLUGINS_DIR, dir.name); - const jsonPath = path.join(pluginDir, ".github/plugin", "plugin.json"); + const jsonPath = path.join(pluginDir, "plugin.json"); if (!fs.existsSync(jsonPath)) continue; try { const data = JSON.parse(fs.readFileSync(jsonPath, "utf-8")); const relPath = `plugins/${dir.name}`; - const extensionRefs = Array.isArray(data?.["x-awesome-copilot"]?.extensions) - ? data["x-awesome-copilot"].extensions - : []; + const composition = data.extensions?.["com.github.awesome-copilot"] ?? {}; + const extensionRefs = composition.extensions + ?.map((entry) => entry.replace(/^\.\/extensions\//, "").replace(/\/$/, "")) + .filter(Boolean) ?? []; + if (fs.existsSync(path.join(EXTENSIONS_DIR, dir.name, "extension.mjs")) && !extensionRefs.includes(dir.name)) { + extensionRefs.push(dir.name); + } const extensionItems = extensionRefs - .map((entry) => normalizeText(entry)) - .filter(Boolean) - .map((entry) => entry.replace(/^\.\/+/, "").replace(/\/$/, "")) - .filter((entry) => entry.startsWith("extensions/")) + .filter((entry) => typeof entry === "string") .map((entry) => ({ kind: "extension", - path: entry, + path: `extensions/${entry}`, })); - const agentItems = (data.agents || []).flatMap((agent) => { + const agentItems = (composition.agents || []).flatMap((agent) => { const agentPath = agent.replace("./", ""); const fullPath = path.join(pluginDir, agentPath); @@ -646,11 +589,11 @@ function generatePluginsData(gitDates, resourceIndex = {}) { // Parse mcpServers: supports a path to a .mcp.json file or an inline object const mcpItems = []; - if (data.mcpServers) { + if (composition.mcpServers) { let mcpServersObj = null; let mcpConfigPath = relPath; - if (typeof data.mcpServers === "string") { - const manifestMcpPath = data.mcpServers.replace(/^\.\//, ""); + if (typeof composition.mcpServers === "string") { + const manifestMcpPath = composition.mcpServers.replace(/^\.\//, ""); mcpConfigPath = manifestMcpPath ? `${relPath}/${manifestMcpPath}` : relPath; const mcpJsonPath = path.join(pluginDir, manifestMcpPath); if (fs.existsSync(mcpJsonPath)) { @@ -661,8 +604,8 @@ function generatePluginsData(gitDates, resourceIndex = {}) { // ignore parse errors } } - } else if (typeof data.mcpServers === "object") { - mcpServersObj = data.mcpServers; + } else if (typeof composition.mcpServers === "object") { + mcpServersObj = composition.mcpServers; } if (mcpServersObj) { for (const serverName of Object.keys(mcpServersObj)) { @@ -674,8 +617,8 @@ function generatePluginsData(gitDates, resourceIndex = {}) { // Build items list from spec fields (agents, commands, skills, mcpServers) const items = [ ...agentItems, - ...(data.commands || []).map((p) => ({ kind: "prompt", path: p })), - ...(data.skills || []).map((p) => ({ kind: "skill", path: p })), + ...(composition.commands || []).map((p) => ({ kind: "prompt", path: p })), + ...(composition.skills || []).map((p) => ({ kind: "skill", path: p })), ...extensionItems, ...mcpItems, ].map((item) => resolvePluginItem(item, resourceIndex)); @@ -702,16 +645,11 @@ function generatePluginsData(gitDates, resourceIndex = {}) { searchText: `${pluginName} ${data.description || "" } ${tags.join(" ")}`.toLowerCase(), }); - extensionEntriesByName.delete(pluginName); } catch (e) { console.warn(`Failed to parse plugin: ${dir.name}`, e.message); } } - for (const extensionPlugin of extensionEntriesByName.values()) { - plugins.push(extensionPlugin); - } - // Load external plugins from plugins/external.json const externalJsonPath = path.join(PLUGINS_DIR, "external.json"); if (fs.existsSync(externalJsonPath)) { @@ -1204,15 +1142,13 @@ function resolveExtensionScreenshots(pluginJson, extensionDir, relPath, ref) { } : null; - const logoEntry = normalizeExtensionScreenshotRole(pluginJson?.logo, relPath, ref); - const screenshotConfig = pluginJson?.["x-awesome-copilot"]?.screenshots || {}; - const iconEntry = normalizeExtensionScreenshotRole(screenshotConfig.icon, relPath, ref); - const galleryRaw = screenshotConfig.gallery; - const firstGalleryEntry = Array.isArray(galleryRaw) ? galleryRaw[0] : galleryRaw; - const galleryEntry = normalizeExtensionScreenshotRole(firstGalleryEntry, relPath, ref); - - const finalIcon = iconEntry || logoEntry || inferredIcon; - const finalGallery = galleryEntry || logoEntry || inferredGallery || finalIcon; + const copilotNs = pluginJson?.extensions?.["com.github.copilot"]; + const logoEntry = normalizeExtensionScreenshotRole( + copilotNs?.logo ?? pluginJson?.logo, + relPath, ref + ); + const finalIcon = logoEntry || inferredIcon; + const finalGallery = logoEntry || inferredGallery || finalIcon; return { screenshots: { @@ -1256,7 +1192,7 @@ function generateCanvasManifest(gitDates, commitSha) { const packageJson = fs.existsSync(packageJsonPath) ? JSON.parse(fs.readFileSync(packageJsonPath, "utf-8")) : {}; - const pluginJsonPath = path.join(extensionDir, ".github", "plugin", "plugin.json"); + const pluginJsonPath = path.join(PLUGINS_DIR, dir.name, "plugin.json"); const pluginJson = fs.existsSync(pluginJsonPath) ? JSON.parse(fs.readFileSync(pluginJsonPath, "utf-8")) : {}; diff --git a/eng/materialize-plugins.mjs b/eng/materialize-plugins.mjs index 905b2faf..8d9b6ef7 100644 --- a/eng/materialize-plugins.mjs +++ b/eng/materialize-plugins.mjs @@ -7,6 +7,8 @@ import { ROOT_FOLDER } from "./constants.mjs"; const PLUGINS_DIR = path.join(ROOT_FOLDER, "plugins"); const EXTENSIONS_DIR = path.join(ROOT_FOLDER, "extensions"); +const COPILOT_NAMESPACE = "com.github.copilot"; +const AWESOME_COPILOT_NAMESPACE = "com.github.awesome-copilot"; /** * Recursively copy a directory. @@ -24,36 +26,6 @@ function copyDirRecursive(src, dest) { } } -function moveEntry(srcPath, destPath) { - fs.mkdirSync(path.dirname(destPath), { recursive: true }); - try { - fs.renameSync(srcPath, destPath); - return; - } catch (error) { - if (error?.code !== "EXDEV") { - throw error; - } - } - - const stats = fs.statSync(srcPath); - if (stats.isDirectory()) { - copyDirRecursive(srcPath, destPath); - fs.rmSync(srcPath, { recursive: true, force: true }); - return; - } - - fs.copyFileSync(srcPath, destPath); - fs.rmSync(srcPath, { force: true }); -} - -function isRelativeAssetPath(assetPath) { - return typeof assetPath === "string" && - assetPath.length > 0 && - !/^(?:[a-z][a-z0-9+.-]*:)?\/\//i.test(assetPath) && - !assetPath.startsWith("data:") && - !path.isAbsolute(assetPath); -} - /** * Resolve a plugin-relative path to the repo-root source file. * @@ -74,63 +46,34 @@ function resolveSource(relPath) { const extensionName = relPath.replace(/^\.\/extensions\//, "").replace(/\/$/, ""); return path.join(ROOT_FOLDER, "extensions", extensionName); } + if (relPath.startsWith("./hooks/")) { + return path.join(ROOT_FOLDER, "hooks", relPath.replace(/^\.\/hooks\//, "")); + } + if (relPath.startsWith("./commands/")) { + return path.join(ROOT_FOLDER, "commands", relPath.replace(/^\.\/commands\//, "")); + } return null; } -export function materializeExtensionPlugin(extensionPath) { - const pluginJsonPath = path.join(extensionPath, ".github", "plugin", "plugin.json"); - if (!fs.existsSync(pluginJsonPath)) { - return { movedEntries: 0, manifestUpdated: false, skipped: true }; +function readExtensionReferences(metadata, pluginName) { + const extensionData = metadata.extensions?.[AWESOME_COPILOT_NAMESPACE]; + const directories = extensionData?.extensions ?? []; + if (!Array.isArray(directories) || + directories.some((entry) => typeof entry !== "string" || !entry.startsWith("./extensions/"))) { + throw new Error(`extensions["${AWESOME_COPILOT_NAMESPACE}"].extensions must contain plugin-relative paths`); } - let metadata; - try { - metadata = JSON.parse(fs.readFileSync(pluginJsonPath, "utf8")); - } catch (err) { - throw new Error(`Failed to parse ${pluginJsonPath}: ${err.message}`); + const names = new Set(directories.map((entry) => + entry.replace(/^\.\/extensions\//, "").replace(/\/$/, "") + )); + if (fs.existsSync(path.join(EXTENSIONS_DIR, pluginName, "extension.mjs"))) { + names.add(pluginName); } - const extensionContainerPath = path.join(extensionPath, "extensions"); - const extensionBundlePath = path.join(extensionContainerPath, path.basename(extensionPath)); - fs.rmSync(extensionContainerPath, { recursive: true, force: true }); - fs.mkdirSync(extensionBundlePath, { recursive: true }); - - let movedEntries = 0; - for (const entry of fs.readdirSync(extensionPath, { withFileTypes: true })) { - if (entry.name === ".github" || entry.name === "extensions") { - continue; - } - - moveEntry( - path.join(extensionPath, entry.name), - path.join(extensionBundlePath, entry.name) - ); - movedEntries++; - } - - if (isRelativeAssetPath(metadata.logo)) { - const normalizedLogoPath = metadata.logo.replace(/\\/g, "/").replace(/^\.\//, ""); - const bundledLogoPath = path.join(extensionBundlePath, normalizedLogoPath); - if (fs.existsSync(bundledLogoPath)) { - const rootLogoPath = path.join(extensionPath, normalizedLogoPath); - fs.mkdirSync(path.dirname(rootLogoPath), { recursive: true }); - fs.copyFileSync(bundledLogoPath, rootLogoPath); - } - } - - let manifestUpdated = false; - if (metadata.extensions !== "extensions") { - metadata.extensions = "extensions"; - manifestUpdated = true; - } - if (manifestUpdated) { - fs.writeFileSync(pluginJsonPath, JSON.stringify(metadata, null, 2) + "\n", "utf8"); - } - - return { movedEntries, manifestUpdated, skipped: false }; + return [...names].sort(); } -function materializePlugins() { +export function materializePlugins() { console.log("Materializing plugin files...\n"); if (!fs.existsSync(PLUGINS_DIR)) { @@ -146,14 +89,12 @@ function materializePlugins() { let totalAgents = 0; let totalSkills = 0; let totalExtensions = 0; - let totalExtensionPlugins = 0; - let totalExtensionPluginEntries = 0; let warnings = 0; let errors = 0; for (const dirName of pluginDirs) { const pluginPath = path.join(PLUGINS_DIR, dirName); - const pluginJsonPath = path.join(pluginPath, ".github/plugin", "plugin.json"); + const pluginJsonPath = path.join(pluginPath, "plugin.json"); if (!fs.existsSync(pluginJsonPath)) { continue; @@ -170,52 +111,37 @@ function materializePlugins() { const pluginName = metadata.name || dirName; - // Process agents - if (Array.isArray(metadata.agents)) { - for (const relPath of metadata.agents) { + const composition = metadata.extensions?.[AWESOME_COPILOT_NAMESPACE] ?? {}; + + // Process repository composition fields. + for (const field of ["agents", "commands", "hooks", "skills"]) { + const entries = composition[field]; + if (!Array.isArray(entries)) continue; + for (const relPath of entries) { const src = resolveSource(relPath); if (!src) { - console.warn(` ⚠ ${pluginName}: Unknown path format: ${relPath}`); + console.warn(` ⚠ ${pluginName}: Unknown ${field} path format: ${relPath}`); warnings++; continue; } if (!fs.existsSync(src)) { - console.warn(` ⚠ ${pluginName}: Source not found: ${src}`); - warnings++; - continue; - } - const dest = path.join(pluginPath, relPath.replace(/^\.\//, "")); - fs.mkdirSync(path.dirname(dest), { recursive: true }); - fs.copyFileSync(src, dest); - totalAgents++; - } - } - - // Process skills - if (Array.isArray(metadata.skills)) { - for (const relPath of metadata.skills) { - const src = resolveSource(relPath); - if (!src) { - console.warn(` ⚠ ${pluginName}: Unknown path format: ${relPath}`); - warnings++; - continue; - } - if (!fs.existsSync(src) || !fs.statSync(src).isDirectory()) { - console.warn(` ⚠ ${pluginName}: Source directory not found: ${src}`); + console.warn(` ⚠ ${pluginName}: ${field} source not found: ${src}`); warnings++; continue; } const dest = path.join(pluginPath, relPath.replace(/^\.\//, "").replace(/\/$/, "")); - copyDirRecursive(src, dest); - totalSkills++; + fs.mkdirSync(path.dirname(dest), { recursive: true }); + if (fs.statSync(src).isDirectory()) copyDirRecursive(src, dest); + else fs.copyFileSync(src, dest); + if (field === "agents") totalAgents++; + if (field === "skills") totalSkills++; } } - // Process extension references from x-awesome-copilot.extensions - const extensionRefs = Array.isArray(metadata?.["x-awesome-copilot"]?.extensions) - ? metadata["x-awesome-copilot"].extensions - : []; - for (const relPath of extensionRefs) { + // Process reusable extensions declared in the repository namespace. + const extensionRefs = readExtensionReferences(metadata, pluginName); + for (const extensionName of extensionRefs) { + const relPath = `./extensions/${extensionName}`; const src = resolveSource(relPath); if (!src) { console.warn(` ⚠ ${pluginName}: Unknown extension path format: ${relPath}`); @@ -227,81 +153,47 @@ function materializePlugins() { warnings++; continue; } - const dest = path.join(pluginPath, relPath.replace(/^\.\//, "").replace(/\/$/, "")); + // Extensions are conventional plugin content and belong under the + // plugin's top-level extensions directory, not the client namespace. + const dest = path.join(pluginPath, "extensions", extensionName); copyDirRecursive(src, dest); totalExtensions++; } - // Rewrite plugin.json to use folder paths instead of individual file paths. - // On staged, paths like ./agents/foo.md point to individual source files. - // On main, after materialization, we only need the containing directory. - const rewritten = { ...metadata }; - let changed = false; + // Emit a spec-compliant served manifest for the marketplace branch. + // Source manifests keep composition fields (agents and skills) + // for build tooling. The served manifest retains only Agent Plugins v1.0.0 fields + // so the runtime uses conventional directory discovery for all content. + const SPEC_FIELDS = new Set(["$schema", "name", "version", "description", "author", + "homepage", "repository", "license", "keywords", "extensions"]); + const AGENT_PLUGINS_SCHEMA = "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json"; - for (const field of ["agents", "commands"]) { - if (Array.isArray(rewritten[field]) && rewritten[field].length > 0) { - const dirs = [...new Set(rewritten[field].map(p => path.dirname(p)))]; - rewritten[field] = dirs; - changed = true; + const served = { "$schema": AGENT_PLUGINS_SCHEMA }; + for (const [key, val] of Object.entries(metadata)) { + if (SPEC_FIELDS.has(key) && key !== "$schema") { + if (key === "extensions") { + const copilot = val?.[COPILOT_NAMESPACE]; + if (copilot) { + served.extensions = { [COPILOT_NAMESPACE]: { ...copilot } }; + } + } else { + served[key] = val; + } } } - if (Array.isArray(rewritten.skills) && rewritten.skills.length > 0) { - // Skills are already folder refs (./skills/name/); strip trailing slash - rewritten.skills = rewritten.skills.map(p => p.replace(/\/$/, "")); - changed = true; - } - - if (Array.isArray(rewritten?.["x-awesome-copilot"]?.extensions) && - rewritten["x-awesome-copilot"].extensions.length > 0) { - rewritten["x-awesome-copilot"].extensions = - rewritten["x-awesome-copilot"].extensions.map((p) => p.replace(/\/$/, "")); - changed = true; - } - - if (changed) { - fs.writeFileSync(pluginJsonPath, JSON.stringify(rewritten, null, 2) + "\n", "utf8"); - } + fs.writeFileSync(pluginJsonPath, JSON.stringify(served, null, 2) + "\n", "utf8"); const counts = []; - if (metadata.agents?.length) counts.push(`${metadata.agents.length} agents`); - if (metadata.skills?.length) counts.push(`${metadata.skills.length} skills`); + if (composition.agents?.length) counts.push(`${composition.agents.length} agents`); + if (composition.skills?.length) counts.push(`${composition.skills.length} skills`); if (extensionRefs.length) counts.push(`${extensionRefs.length} extensions`); if (counts.length) { console.log(`✓ ${pluginName}: ${counts.join(", ")}`); } } - if (fs.existsSync(EXTENSIONS_DIR)) { - const extensionDirs = fs.readdirSync(EXTENSIONS_DIR, { withFileTypes: true }) - .filter((entry) => entry.isDirectory()) - .map((entry) => entry.name) - .sort(); - - for (const dirName of extensionDirs) { - const extensionPath = path.join(EXTENSIONS_DIR, dirName); - if (!fs.existsSync(path.join(extensionPath, "extension.mjs"))) { - continue; - } - - try { - const result = materializeExtensionPlugin(extensionPath); - if (result.skipped) { - continue; - } - - totalExtensionPlugins++; - totalExtensionPluginEntries += result.movedEntries; - console.log(`✓ ${dirName}: materialized extension bundle into ./extensions (${result.movedEntries} entries)`); - } catch (err) { - console.error(`Error: Failed to materialize extension plugin ${dirName}: ${err.message}`); - errors++; - } - } - } - - console.log(`\nDone. Copied ${totalAgents} agents, ${totalSkills} skills, ${totalExtensions} plugin extension refs.`); - console.log(`Materialized ${totalExtensionPlugins} extension plugins (${totalExtensionPluginEntries} top-level entries).`); + console.log(`\nDone. Copied ${totalAgents} agents, ${totalSkills} skills, ${totalExtensions} extensions.`); if (warnings > 0) { console.log(`${warnings} warning(s).`); } @@ -311,8 +203,6 @@ function materializePlugins() { } } -export { materializePlugins }; - if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) { materializePlugins(); } diff --git a/eng/materialize-plugins.test.mjs b/eng/materialize-plugins.test.mjs index d0bce457..16e12104 100644 --- a/eng/materialize-plugins.test.mjs +++ b/eng/materialize-plugins.test.mjs @@ -1,89 +1,9 @@ import assert from "node:assert/strict"; -import fs from "fs"; -import os from "os"; -import path from "path"; -import { after, test } from "node:test"; -import { materializeExtensionPlugin } from "./materialize-plugins.mjs"; -import { cleanMaterializedExtensionPlugin } from "./clean-materialized-plugins.mjs"; +import { test } from "node:test"; +import { materializePlugins } from "./materialize-plugins.mjs"; +import { generateMarketplace } from "./generate-marketplace.mjs"; -const tempDirs = []; - -after(() => { - for (const dir of tempDirs) { - fs.rmSync(dir, { recursive: true, force: true }); - } -}); - -test("materializeExtensionPlugin writes extension bundles to ./extensions and preserves root logo assets", () => { - const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "materialize-extension-plugin-")); - tempDirs.push(tempDir); - - const pluginDir = path.join(tempDir, "extension-plugin"); - fs.mkdirSync(path.join(pluginDir, ".github", "plugin"), { recursive: true }); - fs.mkdirSync(path.join(pluginDir, "assets"), { recursive: true }); - fs.writeFileSync(path.join(pluginDir, ".github", "plugin", "plugin.json"), JSON.stringify({ - name: "test-extension-plugin", - description: "test plugin", - version: "1.0.0", - logo: "assets/preview.png", - extensions: ".", - }, null, 2)); - fs.writeFileSync(path.join(pluginDir, "extension.mjs"), "export default {};\n"); - fs.writeFileSync(path.join(pluginDir, "README.md"), "# test\n"); - fs.writeFileSync(path.join(pluginDir, "assets", "preview.png"), "fake-image-bytes"); - - const result = materializeExtensionPlugin(pluginDir); - const bundleRoot = path.join(pluginDir, "extensions", "extension-plugin"); - - assert.equal(result.skipped, false); - assert.equal(result.manifestUpdated, true); - assert.equal(result.movedEntries, 3); - assert.equal(fs.existsSync(path.join(bundleRoot, "extension.mjs")), true); - assert.equal(fs.existsSync(path.join(bundleRoot, "assets", "preview.png")), true); - assert.equal(fs.existsSync(path.join(bundleRoot, "README.md")), true); - assert.equal(fs.existsSync(path.join(pluginDir, "extensions", ".github")), false); - assert.equal(fs.existsSync(path.join(pluginDir, "extension.mjs")), false); - assert.equal(fs.existsSync(path.join(pluginDir, "README.md")), false); - assert.equal(fs.existsSync(path.join(pluginDir, "assets", "preview.png")), true); - - const pluginManifest = JSON.parse( - fs.readFileSync(path.join(pluginDir, ".github", "plugin", "plugin.json"), "utf8") - ); - assert.equal(pluginManifest.extensions, "extensions"); - assert.equal(pluginManifest.logo, "assets/preview.png"); -}); - -test("cleanMaterializedExtensionPlugin restores moved extension files to root", () => { - const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "clean-materialized-extension-plugin-")); - tempDirs.push(tempDir); - - const pluginDir = path.join(tempDir, "extension-plugin"); - fs.mkdirSync(path.join(pluginDir, ".github", "plugin"), { recursive: true }); - fs.mkdirSync(path.join(pluginDir, "assets"), { recursive: true }); - fs.writeFileSync(path.join(pluginDir, ".github", "plugin", "plugin.json"), JSON.stringify({ - name: "test-extension-plugin", - description: "test plugin", - version: "1.0.0", - logo: "assets/preview.png", - extensions: ".", - }, null, 2)); - fs.writeFileSync(path.join(pluginDir, "extension.mjs"), "export default {};\n"); - fs.writeFileSync(path.join(pluginDir, "README.md"), "# test\n"); - fs.writeFileSync(path.join(pluginDir, "assets", "preview.png"), "fake-image-bytes"); - - materializeExtensionPlugin(pluginDir); - const result = cleanMaterializedExtensionPlugin(pluginDir); - - assert.equal(result.removed, 3); - assert.equal(result.manifestUpdated, true); - assert.equal(fs.existsSync(path.join(pluginDir, "extension.mjs")), true); - assert.equal(fs.existsSync(path.join(pluginDir, "README.md")), true); - assert.equal(fs.existsSync(path.join(pluginDir, "assets", "preview.png")), true); - assert.equal(fs.existsSync(path.join(pluginDir, "extensions")), false); - - const pluginManifest = JSON.parse( - fs.readFileSync(path.join(pluginDir, ".github", "plugin", "plugin.json"), "utf8") - ); - assert.equal(pluginManifest.extensions, "."); - assert.equal(pluginManifest.logo, "assets/preview.png"); +test("build scripts expose callable APIs without running on import", () => { + assert.equal(typeof materializePlugins, "function"); + assert.equal(typeof generateMarketplace, "function"); }); diff --git a/eng/update-readme.mjs b/eng/update-readme.mjs index db671b8a..b6cfbd67 100644 --- a/eng/update-readme.mjs +++ b/eng/update-readme.mjs @@ -29,6 +29,7 @@ import { const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); +const EXTENSIONS_DIR = path.join(ROOT_FOLDER, "extensions"); // Cache of MCP registry server names (lower-cased) fetched from the API let MCP_REGISTRY_SET = null; @@ -715,7 +716,7 @@ function generateUnifiedModeSection(cfg) { * Read and parse a plugin.json file from a plugin directory. */ function readPluginJson(pluginDir) { - const jsonPath = path.join(pluginDir, ".github/plugin", "plugin.json"); + const jsonPath = path.join(pluginDir, "plugin.json"); if (!fs.existsSync(jsonPath)) return null; try { return JSON.parse(fs.readFileSync(jsonPath, "utf-8")); @@ -786,10 +787,23 @@ function generatePluginsSection(pluginsDir) { for (const entry of sortedEntries) { const { plugin, dir, name, isFeatured } = entry; const description = formatTableCell(plugin.description || "No description"); + const composition = plugin.extensions?.["com.github.awesome-copilot"] || {}; + const extensionReferences = Array.isArray(composition.extensions) + ? composition.extensions.length + : 0; + const implicitExtension = + fs.existsSync(path.join(EXTENSIONS_DIR, entry.pluginId, "extension.mjs")) && + !(Array.isArray(composition.extensions) && composition.extensions.some( + (reference) => reference === `./extensions/${entry.pluginId}` + )) + ? 1 + : 0; const itemCount = - (plugin.agents || []).length + - (plugin.commands || []).length + - (plugin.skills || []).length; + (composition.agents || []).length + + (composition.commands || []).length + + (composition.skills || []).length + + extensionReferences + + implicitExtension; const keywords = plugin.keywords ? plugin.keywords.join(", ") : ""; const link = `../plugins/${dir}/README.md`; @@ -842,10 +856,23 @@ function generateFeaturedPluginsSection(pluginsDir) { plugin.description || "No description" ); const keywords = plugin.keywords ? plugin.keywords.join(", ") : ""; + const composition = plugin.extensions?.["com.github.awesome-copilot"] || {}; + const extensionReferences = Array.isArray(composition.extensions) + ? composition.extensions.length + : 0; + const implicitExtension = + fs.existsSync(path.join(EXTENSIONS_DIR, name, "extension.mjs")) && + !(Array.isArray(composition.extensions) && composition.extensions.some( + (reference) => reference === `./extensions/${name}` + )) + ? 1 + : 0; const itemCount = - (plugin.agents || []).length + - (plugin.commands || []).length + - (plugin.skills || []).length; + (composition.agents || []).length + + (composition.commands || []).length + + (composition.skills || []).length + + extensionReferences + + implicitExtension; return { dir, diff --git a/eng/validate-plugins.mjs b/eng/validate-plugins.mjs index e8cbf1a6..38d0304a 100755 --- a/eng/validate-plugins.mjs +++ b/eng/validate-plugins.mjs @@ -5,10 +5,15 @@ import path from "path"; import { ROOT_FOLDER } from "./constants.mjs"; import { readExternalPlugins } from "./external-plugin-validation.mjs"; import { validateLicenseField } from "./lib/license.mjs"; +import { AGENT_PLUGIN_SCHEMA_URL, validateAgentPluginManifest } from "./agent-plugin-schema.mjs"; const PLUGINS_DIR = path.join(ROOT_FOLDER, "plugins"); const EXTENSIONS_DIR = path.join(ROOT_FOLDER, "extensions"); +const AGENT_PLUGINS_SCHEMA = AGENT_PLUGIN_SCHEMA_URL; +const COPILOT_NAMESPACE = "com.github.copilot"; +const AWESOME_COPILOT_NAMESPACE = "com.github.awesome-copilot"; + // Validation functions function validateName(name, folderName) { const errors = []; @@ -16,11 +21,11 @@ function validateName(name, folderName) { errors.push("name is required and must be a string"); return errors; } - if (name.length < 1 || name.length > 50) { - errors.push("name must be between 1 and 50 characters"); + if (name.length < 1 || name.length > 64) { + errors.push("name must be between 1 and 64 characters"); } - if (!/^[a-z0-9-]+$/.test(name)) { - errors.push("name must contain only lowercase letters, numbers, and hyphens"); + if (!/^(?!.*(?:--|\.\.))[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/.test(name)) { + errors.push("name must contain only lowercase letters, numbers, hyphens, and dots (spec §5.5)"); } if (name !== folderName) { errors.push(`name "${name}" must match folder name "${folderName}"`); @@ -28,6 +33,14 @@ function validateName(name, folderName) { return errors; } +function validateSchema(parsed) { + if (parsed["$schema"] !== AGENT_PLUGINS_SCHEMA) { + return `$schema must be "${AGENT_PLUGINS_SCHEMA}"`; + } + const schemaErrors = validateAgentPluginManifest(parsed); + return schemaErrors.length ? `manifest does not conform to Agent Plugins schema: ${schemaErrors.join("; ")}` : null; +} + function validateDescription(description) { if (!description || typeof description !== "string") { return "description is required and must be a string"; @@ -106,35 +119,40 @@ function validateSpecPaths(plugin) { const errors = []; const specs = { agents: { prefix: "./agents/", suffix: ".md", repoDir: "agents", repoSuffix: ".agent.md" }, + commands: { prefix: "./commands/", suffix: ".md", repoDir: "commands", repoSuffix: ".md" }, + hooks: { prefix: "./hooks/", suffix: "/", repoDir: "hooks", repoFile: "README.md" }, skills: { prefix: "./skills/", suffix: "/", repoDir: "skills", repoFile: "SKILL.md" }, }; for (const [field, spec] of Object.entries(specs)) { - const arr = plugin[field]; + const arr = plugin.extensions?.[AWESOME_COPILOT_NAMESPACE]?.[field]; if (arr === undefined) continue; if (!Array.isArray(arr)) { - errors.push(`${field} must be an array`); + errors.push(`extensions["${AWESOME_COPILOT_NAMESPACE}"].${field} must be an array`); continue; } if (!arraysEqual(arr, sortPluginEntries(arr))) { - errors.push(`${field} must be sorted alphabetically`); + errors.push(`extensions["${AWESOME_COPILOT_NAMESPACE}"].${field} must be sorted alphabetically`); + } + if (new Set(arr).size !== arr.length) { + errors.push(`extensions["${AWESOME_COPILOT_NAMESPACE}"].${field} must not contain duplicate references`); } for (let i = 0; i < arr.length; i++) { const p = arr[i]; if (typeof p !== "string") { - errors.push(`${field}[${i}] must be a string`); + errors.push(`extensions["${AWESOME_COPILOT_NAMESPACE}"].${field}[${i}] must be a string`); continue; } if (!p.startsWith("./")) { - errors.push(`${field}[${i}] must start with "./"`); + errors.push(`extensions["${AWESOME_COPILOT_NAMESPACE}"].${field}[${i}] must start with "./"`); continue; } if (!p.startsWith(spec.prefix)) { - errors.push(`${field}[${i}] must start with "${spec.prefix}"`); + errors.push(`extensions["${AWESOME_COPILOT_NAMESPACE}"].${field}[${i}] must start with "${spec.prefix}"`); continue; } if (!p.endsWith(spec.suffix)) { - errors.push(`${field}[${i}] must end with "${spec.suffix}"`); + errors.push(`extensions["${AWESOME_COPILOT_NAMESPACE}"].${field}[${i}] must end with "${spec.suffix}"`); continue; } // Validate the source file exists at repo root @@ -143,12 +161,16 @@ function validateSpecPaths(plugin) { const skillDir = path.join(ROOT_FOLDER, spec.repoDir, basename); const skillFile = path.join(skillDir, spec.repoFile); if (!fs.existsSync(skillFile)) { - errors.push(`${field}[${i}] source not found: ${spec.repoDir}/${basename}/SKILL.md`); + errors.push(`extensions["${AWESOME_COPILOT_NAMESPACE}"].${field}[${i}] source not found: ${spec.repoDir}/${basename}/SKILL.md`); } } else { - const srcFile = path.join(ROOT_FOLDER, spec.repoDir, basename + spec.repoSuffix); + const srcFile = spec.repoFile + ? path.join(ROOT_FOLDER, spec.repoDir, basename, spec.repoFile) + : path.join(ROOT_FOLDER, spec.repoDir, basename + spec.repoSuffix); if (!fs.existsSync(srcFile)) { - errors.push(`${field}[${i}] source not found: ${spec.repoDir}/${basename}${spec.repoSuffix}`); + errors.push(`extensions["${AWESOME_COPILOT_NAMESPACE}"].${field}[${i}] source not found`); + } else if (field === "hooks" && !fs.existsSync(path.join(ROOT_FOLDER, spec.repoDir, basename, "hooks.json"))) { + errors.push(`extensions["${AWESOME_COPILOT_NAMESPACE}"].${field}[${i}] source not found: ${spec.repoDir}/${basename}/hooks.json`); } } } @@ -156,41 +178,61 @@ function validateSpecPaths(plugin) { return errors; } -function validateCuratedPluginExtensionRefs(plugin) { +function validateExtensionReferences(plugin, pluginDir) { const errors = []; - const extensionRefs = plugin?.["x-awesome-copilot"]?.extensions; - if (extensionRefs === undefined) { + const directories = plugin.extensions?.[AWESOME_COPILOT_NAMESPACE]?.extensions; + if (directories === undefined) { + return errors; + } + if (!Array.isArray(directories)) { + errors.push(`extensions["${AWESOME_COPILOT_NAMESPACE}"].extensions must be an array`); + return errors; + } + if (!arraysEqual(directories, sortPluginEntries(directories))) { + errors.push(`extensions["${AWESOME_COPILOT_NAMESPACE}"].extensions entries must be sorted alphabetically`); + } + if (new Set(directories).size !== directories.length) { + errors.push(`extensions["${AWESOME_COPILOT_NAMESPACE}"].extensions must not contain duplicate references`); + } + + for (const [index, directory] of directories.entries()) { + const name = typeof directory === "string" + ? directory.replace(/^\.\/extensions\//, "").replace(/\/$/, "") + : ""; + if (typeof directory !== "string" || !directory.startsWith("./extensions/") || + !/^[a-z0-9][a-z0-9.-]*[a-z0-9]$|^[a-z0-9]$/.test(name)) { + errors.push(`extensions["${AWESOME_COPILOT_NAMESPACE}"].extensions[${index}] must be a valid ./extensions/ path`); + continue; + } + if (!fs.existsSync(path.join(EXTENSIONS_DIR, name, "extension.mjs"))) { + errors.push(`extensions["${AWESOME_COPILOT_NAMESPACE}"].extensions[${index}] source not found: extensions/${name}`); + } + } + + return errors; +} + +function validateCompositionNamespace(plugin) { + const errors = []; + const compositionFields = ["agents", "commands", "hooks", "mcpServers", "skills"]; + const extensions = plugin.extensions; + const composition = extensions?.[AWESOME_COPILOT_NAMESPACE]; + + if (extensions !== undefined && + (typeof extensions !== "object" || extensions === null || Array.isArray(extensions))) { + errors.push(`extensions must be an object containing "${AWESOME_COPILOT_NAMESPACE}"`); return errors; } - if (!Array.isArray(extensionRefs)) { - errors.push('x-awesome-copilot.extensions must be an array'); + if (composition !== undefined && + (typeof composition !== "object" || composition === null || Array.isArray(composition))) { + errors.push(`extensions["${AWESOME_COPILOT_NAMESPACE}"] must be an object`); return errors; } - if (!arraysEqual(extensionRefs, sortPluginEntries(extensionRefs))) { - errors.push('x-awesome-copilot.extensions must be sorted alphabetically'); - } - - const knownExtensions = new Set(getExtensionFolderNames()); - for (let i = 0; i < extensionRefs.length; i++) { - const ref = extensionRefs[i]; - if (typeof ref !== "string") { - errors.push(`x-awesome-copilot.extensions[${i}] must be a string`); - continue; - } - if (!ref.startsWith("./extensions/")) { - errors.push(`x-awesome-copilot.extensions[${i}] must start with "./extensions/"`); - continue; - } - - const normalized = ref.replace(/^\.\/extensions\//, "").replace(/\/$/, ""); - if (!normalized) { - errors.push(`x-awesome-copilot.extensions[${i}] must include an extension folder name`); - continue; - } - if (!knownExtensions.has(normalized)) { - errors.push(`x-awesome-copilot.extensions[${i}] source not found: extensions/${normalized}`); + for (const field of compositionFields) { + if (extensions?.[field] !== undefined) { + errors.push(`extensions.${field} must be moved to extensions["${AWESOME_COPILOT_NAMESPACE}"].${field}`); } } @@ -201,11 +243,13 @@ function validatePlugin(folderName) { const pluginDir = path.join(PLUGINS_DIR, folderName); const errors = []; let parsedPlugin = null; + const extensionDir = path.join(EXTENSIONS_DIR, folderName); + const isExtensionPlugin = fs.existsSync(path.join(extensionDir, "extension.mjs")); - // Rule 1: Must have .github/plugin/plugin.json - const pluginJsonPath = path.join(pluginDir, ".github/plugin", "plugin.json"); + // Rule 1: Must have plugin.json at the plugin root + const pluginJsonPath = path.join(pluginDir, "plugin.json"); if (!fs.existsSync(pluginJsonPath)) { - errors.push("missing required file: .github/plugin/plugin.json"); + errors.push("missing required file: plugin.json"); return errors; } @@ -226,7 +270,11 @@ function validatePlugin(folderName) { return { errors, plugin: parsedPlugin }; } - // Rule 3 & 4: name, description, version + // Rule 3: $schema required + const schemaError = validateSchema(plugin); + if (schemaError) errors.push(schemaError); + + // Rule 4 & 5: name, description, version const nameErrors = validateName(plugin.name, folderName); errors.push(...nameErrors); @@ -236,12 +284,18 @@ function validatePlugin(folderName) { const versionError = validateVersion(plugin.version); if (versionError) errors.push(versionError); - // Rule 5: keywords (or tags for backward compat) + // Rule 6: keywords (or tags for backward compat) const keywordsError = validateKeywords(plugin.keywords ?? plugin.tags); if (keywordsError) errors.push(keywordsError); // Rule 5b: license (shared with external plugins). Non-SPDX is a warning, not an error. const warnings = []; + for (const field of ["agents", "commands", "hooks", "mcpServers", "skills"]) { + if (plugin[field] !== undefined) { + errors.push(`${field} must be moved to extensions["${AWESOME_COPILOT_NAMESPACE}"].${field}`); + } + } + errors.push(...validateCompositionNamespace(plugin)); const licenseResult = validateLicenseField(plugin.license, { required: false }); errors.push(...licenseResult.errors); warnings.push(...licenseResult.warnings); @@ -250,9 +304,19 @@ function validatePlugin(folderName) { const specErrors = validateSpecPaths(plugin); errors.push(...specErrors); - const extensionRefErrors = validateCuratedPluginExtensionRefs(plugin); + const extensionRefErrors = validateExtensionReferences(plugin, pluginDir); errors.push(...extensionRefErrors); + if (isExtensionPlugin) { + const extension = plugin.extensions; + const namespace = extension?.[COPILOT_NAMESPACE]; + if (!namespace || namespace.logo !== "assets/preview.png") { + errors.push(`extensions["${COPILOT_NAMESPACE}"].logo must be exactly "assets/preview.png" for extension plugins`); + } else { + validateExtensionScreenshotPath(extensionDir, namespace.logo, `extensions["${COPILOT_NAMESPACE}"].logo`, errors); + } + } + return { errors, warnings, plugin: parsedPlugin }; } @@ -269,62 +333,6 @@ function validateExtensionScreenshotPath(extensionDir, pathValue, fieldName, err } } -function validateExtensionManifest(folderName) { - const extensionDir = path.join(EXTENSIONS_DIR, folderName); - const errors = []; - let parsedPlugin = null; - - const pluginJsonPath = path.join(extensionDir, ".github/plugin", "plugin.json"); - if (!fs.existsSync(pluginJsonPath)) { - errors.push("missing required file: .github/plugin/plugin.json"); - return { errors, plugin: parsedPlugin }; - } - - const parsed = parseJsonFile(pluginJsonPath); - if (parsed.parseError) { - errors.push(`failed to parse plugin.json: ${parsed.parseError}`); - return { errors, plugin: parsedPlugin }; - } - - parsedPlugin = parsed; - - const nameErrors = validateName(parsed.name, folderName); - errors.push(...nameErrors); - - const descError = validateDescription(parsed.description); - if (descError) errors.push(descError); - - const versionError = validateVersion(parsed.version); - if (versionError) errors.push(versionError); - - const keywordsError = validateKeywords(parsed.keywords ?? parsed.tags); - if (keywordsError) errors.push(keywordsError); - - // Extension convention: logo must be exactly "assets/preview.png" - if (parsed.logo !== "assets/preview.png") { - errors.push('logo must be exactly "assets/preview.png" (extension convention)'); - } else { - validateExtensionScreenshotPath(extensionDir, parsed.logo, "logo", errors); - } - - // Extension convention: x-awesome-copilot must not be present - if (parsed["x-awesome-copilot"] !== undefined) { - errors.push("x-awesome-copilot field must not be present (use convention-based logo instead)"); - } - - if (parsed.extenions !== undefined) { - errors.push('use "extensions" field (found misspelled key "extenions")'); - } - - // Extension convention: source manifests keep extensions at repository root. - // Materialization rewrites this to "extensions" on distribution branches. - if (parsed.extensions !== ".") { - errors.push('extensions field must be exactly "." in source manifests (extension convention)'); - } - - return { errors, plugin: parsedPlugin }; -} - // Main validation function function validatePlugins() { const pluginDirs = fs.existsSync(PLUGINS_DIR) @@ -332,15 +340,12 @@ function validatePlugins() { .filter((d) => d.isDirectory()) .map((d) => d.name) : []; - const extensionDirs = getExtensionFolderNames(); - - if (pluginDirs.length === 0 && extensionDirs.length === 0) { - console.log("No plugins or extension plugin manifests found - validation skipped"); + if (pluginDirs.length === 0) { + console.log("No plugin manifests found - validation skipped"); return true; } console.log(`Validating ${pluginDirs.length} plugins...\n`); - console.log(`Validating ${extensionDirs.length} extensions as plugin sources...\n`); let hasErrors = false; const seenNames = new Set(); @@ -374,30 +379,11 @@ function validatePlugins() { } } - if (extensionDirs.length > 0) { - console.log(""); - } - - for (const dir of extensionDirs) { - console.log(`Validating extension ${dir}...`); - const { errors, plugin } = validateExtensionManifest(dir); - - if (errors.length > 0) { - console.error(`❌ extension ${dir}:`); - errors.forEach((e) => console.error(` - ${e}`)); + for (const dir of getExtensionFolderNames()) { + const pluginJsonPath = path.join(PLUGINS_DIR, dir, "plugin.json"); + if (!fs.existsSync(pluginJsonPath)) { + console.error(`❌ extension ${dir}: missing plugin manifest at plugins/${dir}/plugin.json`); hasErrors = true; - } else { - console.log(`✅ extension ${dir} is valid`); - } - - if (plugin?.name) { - if (seenNames.has(plugin.name)) { - console.error(`❌ Duplicate plugin name "${plugin.name}"`); - hasErrors = true; - } else { - seenNames.add(plugin.name); - localPluginNames.push(plugin.name); - } } } @@ -418,7 +404,7 @@ function validatePlugins() { } if (!hasErrors) { - console.log(`\n✅ All ${pluginDirs.length} plugins, ${extensionDirs.length} extensions, and the external catalog are valid`); + console.log(`\n✅ All ${pluginDirs.length} plugins and the external catalog are valid`); } return !hasErrors; diff --git a/plugins/accessibility-kanban/README.md b/plugins/accessibility-kanban/README.md new file mode 100644 index 00000000..6bcee148 --- /dev/null +++ b/plugins/accessibility-kanban/README.md @@ -0,0 +1,17 @@ +# Accessibility Kanban Plugin + +Kanban board to manage accessibility issues, allow you to plan, track, and complete remediation work. + +## Installation + +``bash +copilot plugin install accessibility-kanban@awesome-copilot +`` + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## License + +MIT diff --git a/extensions/accessibility-kanban/.github/plugin/plugin.json b/plugins/accessibility-kanban/plugin.json similarity index 59% rename from extensions/accessibility-kanban/.github/plugin/plugin.json rename to plugins/accessibility-kanban/plugin.json index 25bfbc1a..16014aa2 100644 --- a/extensions/accessibility-kanban/.github/plugin/plugin.json +++ b/plugins/accessibility-kanban/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "accessibility-kanban", "description": "Kanban board to manage accessibility issues, allow you to plan, track, and complete remediation work.", "version": "1.0.2", @@ -14,6 +15,14 @@ "planning-workflow", "status-tracking" ], - "logo": "assets/preview.png", - "extensions": "." + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/accessibility-kanban" + ] + } + } } diff --git a/plugins/acreadiness-cockpit/.github/plugin/plugin.json b/plugins/acreadiness-cockpit/plugin.json similarity index 61% rename from plugins/acreadiness-cockpit/.github/plugin/plugin.json rename to plugins/acreadiness-cockpit/plugin.json index 6fbf2294..88aa0e7b 100644 --- a/plugins/acreadiness-cockpit/.github/plugin/plugin.json +++ b/plugins/acreadiness-cockpit/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "acreadiness-cockpit", "description": "Drive Microsoft AgentRC from Copilot chat: assess AI readiness, generate Copilot instructions (flat or nested with applyTo globs for monorepos), and manage policies. Produces a self-contained static HTML dashboard at reports/index.html.", "version": "1.0.0", @@ -16,12 +17,16 @@ }, "repository": "https://github.com/github/awesome-copilot", "license": "MIT", - "agents": [ - "./agents/ai-readiness-reporter.md" - ], - "skills": [ - "./skills/acreadiness-assess/", - "./skills/acreadiness-generate-instructions/", - "./skills/acreadiness-policy/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/ai-readiness-reporter.md" + ], + "skills": [ + "./skills/acreadiness-assess/", + "./skills/acreadiness-generate-instructions/", + "./skills/acreadiness-policy/" + ] + } + } } diff --git a/plugins/ai-team-orchestration/.github/plugin/plugin.json b/plugins/ai-team-orchestration/plugin.json similarity index 60% rename from plugins/ai-team-orchestration/.github/plugin/plugin.json rename to plugins/ai-team-orchestration/plugin.json index 585c5108..52b906fd 100644 --- a/plugins/ai-team-orchestration/.github/plugin/plugin.json +++ b/plugins/ai-team-orchestration/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "ai-team-orchestration", "description": "Run a lightweight, role-separated AI development team with flexible tools, developer-selected models, proportionate planning, and optional QA.", "version": "2.0.0", @@ -16,12 +17,16 @@ }, "repository": "https://github.com/github/awesome-copilot", "license": "MIT", - "agents": [ - "./agents/ai-team-dev.md", - "./agents/ai-team-producer.md", - "./agents/ai-team-qa.md" - ], - "skills": [ - "./skills/ai-team-orchestration/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/ai-team-dev.md", + "./agents/ai-team-producer.md", + "./agents/ai-team-qa.md" + ], + "skills": [ + "./skills/ai-team-orchestration/" + ] + } + } } diff --git a/plugins/apng-studio/README.md b/plugins/apng-studio/README.md new file mode 100644 index 00000000..87129146 --- /dev/null +++ b/plugins/apng-studio/README.md @@ -0,0 +1,17 @@ +# Apng Studio Plugin + +Interactive GitHub Copilot app canvas extension for building Animated PNG (APNG) files from frames. Draw or upload frames, tune per-frame timing and compositing, preview live, send the result to your phone by QR, and export an animated .png. + +## Installation + +``bash +copilot plugin install apng-studio@awesome-copilot +`` + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## License + +MIT diff --git a/extensions/apng-studio/.github/plugin/plugin.json b/plugins/apng-studio/plugin.json similarity index 67% rename from extensions/apng-studio/.github/plugin/plugin.json rename to plugins/apng-studio/plugin.json index 9522900b..c65328ed 100644 --- a/extensions/apng-studio/.github/plugin/plugin.json +++ b/plugins/apng-studio/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "apng-studio", "description": "Interactive GitHub Copilot app canvas extension for building Animated PNG (APNG) files from frames. Draw or upload frames, tune per-frame timing and compositing, preview live, send the result to your phone by QR, and export an animated .png.", "version": "1.0.2", @@ -14,6 +15,14 @@ "image-export", "interactive-canvas" ], - "logo": "assets/preview.png", - "extensions": "." + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/apng-studio" + ] + } + } } diff --git a/plugins/arcade-canvas/README.md b/plugins/arcade-canvas/README.md new file mode 100644 index 00000000..ba6a5e00 --- /dev/null +++ b/plugins/arcade-canvas/README.md @@ -0,0 +1,17 @@ +# Arcade Canvas Plugin + +Play five retro Phaser mini-games in a Copilot canvas while agents work. + +## Installation + +``bash +copilot plugin install arcade-canvas@awesome-copilot +`` + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## License + +MIT diff --git a/extensions/arcade-canvas/.github/plugin/plugin.json b/plugins/arcade-canvas/plugin.json similarity index 57% rename from extensions/arcade-canvas/.github/plugin/plugin.json rename to plugins/arcade-canvas/plugin.json index 9c45471e..d1b58c2f 100644 --- a/extensions/arcade-canvas/.github/plugin/plugin.json +++ b/plugins/arcade-canvas/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "arcade-canvas", "description": "Play five retro Phaser mini-games in a Copilot canvas while agents work.", "version": "1.0.2", @@ -14,6 +15,14 @@ "retro-games", "session-breaks" ], - "logo": "assets/preview.png", - "extensions": "." + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/arcade-canvas" + ] + } + } } diff --git a/plugins/arch/.github/plugin/plugin.json b/plugins/arch/plugin.json similarity index 71% rename from plugins/arch/.github/plugin/plugin.json rename to plugins/arch/plugin.json index 69a0c7a1..9e42a687 100644 --- a/plugins/arch/.github/plugin/plugin.json +++ b/plugins/arch/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "arch", "description": "Architecture and modernization toolkit: produce a cited architecture document for a locally-cloned repo, and generate a phased modernization plan that auto-runs Documentation mode when needed.", "version": "1.0.0", @@ -14,7 +15,11 @@ }, "repository": "https://github.com/github/awesome-copilot", "license": "MIT", - "skills": [ - "./skills/doc-and-modernize/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/doc-and-modernize/" + ] + } + } } diff --git a/plugins/arize-ax/.github/plugin/plugin.json b/plugins/arize-ax/plugin.json similarity index 54% rename from plugins/arize-ax/.github/plugin/plugin.json rename to plugins/arize-ax/plugin.json index 92459441..6c7ee9e2 100644 --- a/plugins/arize-ax/.github/plugin/plugin.json +++ b/plugins/arize-ax/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "arize-ax", "description": "Arize AX platform skills for LLM observability, evaluation, and optimization. Includes trace export, instrumentation, datasets, experiments, evaluators, AI provider integrations, annotations, prompt optimization, and deep linking to the Arize UI.", "version": "1.0.0", @@ -18,15 +19,19 @@ "experiments", "prompt-optimization" ], - "skills": [ - "./skills/arize-ai-provider-integration/", - "./skills/arize-annotation/", - "./skills/arize-dataset/", - "./skills/arize-evaluator/", - "./skills/arize-experiment/", - "./skills/arize-instrumentation/", - "./skills/arize-link/", - "./skills/arize-prompt-optimization/", - "./skills/arize-trace/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/arize-ai-provider-integration/", + "./skills/arize-annotation/", + "./skills/arize-dataset/", + "./skills/arize-evaluator/", + "./skills/arize-experiment/", + "./skills/arize-instrumentation/", + "./skills/arize-link/", + "./skills/arize-prompt-optimization/", + "./skills/arize-trace/" + ] + } + } } diff --git a/plugins/automate-this/.github/plugin/plugin.json b/plugins/automate-this/plugin.json similarity index 75% rename from plugins/automate-this/.github/plugin/plugin.json rename to plugins/automate-this/plugin.json index 0824ae3d..01fb0c25 100644 --- a/plugins/automate-this/.github/plugin/plugin.json +++ b/plugins/automate-this/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "automate-this", "description": "Record your screen doing a manual process, drop the video on your Desktop, and let Copilot CLI analyze it frame-by-frame to build working automation scripts. Supports narrated recordings with audio transcription.", "version": "1.0.0", @@ -17,7 +18,11 @@ "productivity", "copilot-cli" ], - "skills": [ - "./skills/automate-this/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/automate-this/" + ] + } + } } diff --git a/plugins/awesome-copilot/.github/plugin/plugin.json b/plugins/awesome-copilot/.github/plugin/plugin.json deleted file mode 100644 index def06d7d..00000000 --- a/plugins/awesome-copilot/.github/plugin/plugin.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "awesome-copilot", - "description": "Meta prompts that help you discover and generate curated GitHub Copilot agents, instructions, prompts, and skills.", - "version": "1.1.0", - "author": { - "name": "Awesome Copilot Community" - }, - "repository": "https://github.com/github/awesome-copilot", - "license": "MIT", - "keywords": [ - "github-copilot", - "discovery", - "meta", - "prompt-engineering", - "agents" - ], - "agents": [ - "./agents/meta-agentic-project-scaffold.md" - ], - "skills": [ - "./skills/suggest-awesome-github-copilot-agents/", - "./skills/suggest-awesome-github-copilot-instructions/", - "./skills/suggest-awesome-github-copilot-skills/" - ], - "mcpServers": "./.mcp.json" -} diff --git a/plugins/awesome-copilot/plugin.json b/plugins/awesome-copilot/plugin.json new file mode 100644 index 00000000..b5bd3488 --- /dev/null +++ b/plugins/awesome-copilot/plugin.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", + "name": "awesome-copilot", + "description": "Meta prompts that help you discover and generate curated GitHub Copilot agents, instructions, prompts, and skills.", + "version": "1.1.0", + "author": { + "name": "Awesome Copilot Community" + }, + "repository": "https://github.com/github/awesome-copilot", + "license": "MIT", + "keywords": [ + "github-copilot", + "discovery", + "meta", + "prompt-engineering", + "agents" + ], + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/meta-agentic-project-scaffold.md" + ], + "mcpServers": "./.mcp.json", + "skills": [ + "./skills/suggest-awesome-github-copilot-agents/", + "./skills/suggest-awesome-github-copilot-instructions/", + "./skills/suggest-awesome-github-copilot-skills/" + ] + } + } +} diff --git a/plugins/aws-cloud-development/.github/plugin/plugin.json b/plugins/aws-cloud-development/plugin.json similarity index 50% rename from plugins/aws-cloud-development/.github/plugin/plugin.json rename to plugins/aws-cloud-development/plugin.json index 9868733e..e8c433c6 100644 --- a/plugins/aws-cloud-development/.github/plugin/plugin.json +++ b/plugins/aws-cloud-development/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "aws-cloud-development", "description": "Comprehensive AWS cloud development tools including Infrastructure as Code, serverless functions, architecture patterns, and cost optimization for building scalable cloud applications.", "version": "1.0.0", @@ -18,16 +19,20 @@ "devops", "cdk" ], - "agents": [ - "./agents/aws-principal-architect.md", - "./agents/aws-serverless-architect.md", - "./agents/terraform-aws-implement.md", - "./agents/terraform-aws-planning.md" - ], - "skills": [ - "./skills/aws-cost-optimize/", - "./skills/aws-resource-health-diagnose/", - "./skills/aws-resource-query/", - "./skills/aws-well-architected-review/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/aws-principal-architect.md", + "./agents/aws-serverless-architect.md", + "./agents/terraform-aws-implement.md", + "./agents/terraform-aws-planning.md" + ], + "skills": [ + "./skills/aws-cost-optimize/", + "./skills/aws-resource-health-diagnose/", + "./skills/aws-resource-query/", + "./skills/aws-well-architected-review/" + ] + } + } } diff --git a/plugins/azure-cloud-development/.github/plugin/plugin.json b/plugins/azure-cloud-development/.github/plugin/plugin.json deleted file mode 100644 index 6f977684..00000000 --- a/plugins/azure-cloud-development/.github/plugin/plugin.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "name": "azure-cloud-development", - "description": "Comprehensive Azure cloud development tools including Infrastructure as Code, serverless functions, architecture patterns, and cost optimization for building scalable cloud applications.", - "version": "1.0.1", - "author": { - "name": "Awesome Copilot Community" - }, - "repository": "https://github.com/github/awesome-copilot", - "license": "MIT", - "keywords": [ - "azure", - "cloud", - "infrastructure", - "bicep", - "terraform", - "serverless", - "architecture", - "devops" - ], - "agents": [ - "./agents/azure-logic-apps-expert.md", - "./agents/azure-principal-architect.md", - "./agents/azure-saas-architect.md", - "./agents/azure-verified-modules-bicep.md", - "./agents/azure-verified-modules-terraform.md", - "./agents/terraform-azure-implement.md", - "./agents/terraform-azure-planning.md" - ], - "skills": [ - "./skills/az-cost-optimize/", - "./skills/azure-pricing/", - "./skills/azure-resource-health-diagnose/", - "./skills/import-infrastructure-as-code/" - ] -} diff --git a/plugins/azure-cloud-development/plugin.json b/plugins/azure-cloud-development/plugin.json new file mode 100644 index 00000000..2f896af5 --- /dev/null +++ b/plugins/azure-cloud-development/plugin.json @@ -0,0 +1,40 @@ +{ + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", + "name": "azure-cloud-development", + "description": "Comprehensive Azure cloud development tools including Infrastructure as Code, serverless functions, architecture patterns, and cost optimization for building scalable cloud applications.", + "version": "1.0.1", + "author": { + "name": "Awesome Copilot Community" + }, + "repository": "https://github.com/github/awesome-copilot", + "license": "MIT", + "keywords": [ + "azure", + "cloud", + "infrastructure", + "bicep", + "terraform", + "serverless", + "architecture", + "devops" + ], + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/azure-logic-apps-expert.md", + "./agents/azure-principal-architect.md", + "./agents/azure-saas-architect.md", + "./agents/azure-verified-modules-bicep.md", + "./agents/azure-verified-modules-terraform.md", + "./agents/terraform-azure-implement.md", + "./agents/terraform-azure-planning.md" + ], + "skills": [ + "./skills/az-cost-optimize/", + "./skills/azure-pricing/", + "./skills/azure-resource-health-diagnose/", + "./skills/import-infrastructure-as-code/" + ] + } + } +} diff --git a/plugins/backlog-swipe-triage/README.md b/plugins/backlog-swipe-triage/README.md new file mode 100644 index 00000000..b799412f --- /dev/null +++ b/plugins/backlog-swipe-triage/README.md @@ -0,0 +1,17 @@ +# Backlog Swipe Triage Plugin + +Quickly swipe through backlog issues to triage decisions like assign, needs-info, defer, close, or ignore. + +## Installation + +``bash +copilot plugin install backlog-swipe-triage@awesome-copilot +`` + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## License + +MIT diff --git a/extensions/backlog-swipe-triage/.github/plugin/plugin.json b/plugins/backlog-swipe-triage/plugin.json similarity index 61% rename from extensions/backlog-swipe-triage/.github/plugin/plugin.json rename to plugins/backlog-swipe-triage/plugin.json index aa7f7c16..2df94318 100644 --- a/extensions/backlog-swipe-triage/.github/plugin/plugin.json +++ b/plugins/backlog-swipe-triage/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "backlog-swipe-triage", "description": "Quickly swipe through backlog issues to triage decisions like assign, needs-info, defer, close, or ignore.", "version": "1.0.2", @@ -14,6 +15,14 @@ "swipe-interface", "workflow-automation" ], - "logo": "assets/preview.png", - "extensions": "." + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/backlog-swipe-triage" + ] + } + } } diff --git a/plugins/backrooms-canvas/README.md b/plugins/backrooms-canvas/README.md new file mode 100644 index 00000000..80e93acd --- /dev/null +++ b/plugins/backrooms-canvas/README.md @@ -0,0 +1,17 @@ +# Backrooms Canvas Plugin + +Wander an endless first-person backrooms in a Copilot canvas while agents work; their status ghost-writes on the walls. + +## Installation + +``bash +copilot plugin install backrooms-canvas@awesome-copilot +`` + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## License + +MIT diff --git a/extensions/backrooms-canvas/.github/plugin/plugin.json b/plugins/backrooms-canvas/plugin.json similarity index 61% rename from extensions/backrooms-canvas/.github/plugin/plugin.json rename to plugins/backrooms-canvas/plugin.json index ef85713c..b8b976d8 100644 --- a/extensions/backrooms-canvas/.github/plugin/plugin.json +++ b/plugins/backrooms-canvas/plugin.json @@ -14,6 +14,15 @@ "procedural-generation", "session-breaks" ], - "logo": "assets/preview.png", - "extensions": "." + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/backrooms-canvas" + ] + } + }, + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json" } diff --git a/plugins/cast-imaging/.github/plugin/plugin.json b/plugins/cast-imaging/plugin.json similarity index 60% rename from plugins/cast-imaging/.github/plugin/plugin.json rename to plugins/cast-imaging/plugin.json index 2d8d22bd..d47e4c05 100644 --- a/plugins/cast-imaging/.github/plugin/plugin.json +++ b/plugins/cast-imaging/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "cast-imaging", "description": "A comprehensive collection of specialized agents for software analysis, impact assessment, structural quality advisories, and architectural review using CAST Imaging.", "version": "1.0.0", @@ -15,9 +16,13 @@ "impact-analysis", "devops" ], - "agents": [ - "./agents/cast-imaging-impact-analysis.md", - "./agents/cast-imaging-software-discovery.md", - "./agents/cast-imaging-structural-quality-advisor.md" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/cast-imaging-impact-analysis.md", + "./agents/cast-imaging-software-discovery.md", + "./agents/cast-imaging-structural-quality-advisor.md" + ] + } + } } diff --git a/plugins/chromium-control-canvas/README.md b/plugins/chromium-control-canvas/README.md new file mode 100644 index 00000000..d3e95196 --- /dev/null +++ b/plugins/chromium-control-canvas/README.md @@ -0,0 +1,17 @@ +# Chromium Control Canvas Plugin + +Opens a real Chromium window you can navigate and interact with from a Copilot canvas control panel and agent actions. + +## Installation + +``bash +copilot plugin install chromium-control-canvas@awesome-copilot +`` + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## License + +MIT diff --git a/extensions/chromium-control-canvas/.github/plugin/plugin.json b/plugins/chromium-control-canvas/plugin.json similarity index 62% rename from extensions/chromium-control-canvas/.github/plugin/plugin.json rename to plugins/chromium-control-canvas/plugin.json index 301485a6..419c9663 100644 --- a/extensions/chromium-control-canvas/.github/plugin/plugin.json +++ b/plugins/chromium-control-canvas/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "chromium-control-canvas", "description": "Opens a real Chromium window you can navigate and interact with from a Copilot canvas control panel and agent actions.", "version": "1.0.2", @@ -15,6 +16,14 @@ "ui-testing", "web-navigation" ], - "logo": "assets/preview.png", - "extensions": "." + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/chromium-control-canvas" + ] + } + } } diff --git a/plugins/clojure-interactive-programming/.github/plugin/plugin.json b/plugins/clojure-interactive-programming/plugin.json similarity index 59% rename from plugins/clojure-interactive-programming/.github/plugin/plugin.json rename to plugins/clojure-interactive-programming/plugin.json index e983d38a..c47a5a66 100644 --- a/plugins/clojure-interactive-programming/.github/plugin/plugin.json +++ b/plugins/clojure-interactive-programming/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "clojure-interactive-programming", "description": "Tools for REPL-first Clojure workflows featuring Clojure instructions, the interactive programming chat mode and supporting guidance.", "version": "1.0.0", @@ -12,10 +13,14 @@ "repl", "interactive-programming" ], - "agents": [ - "./agents/clojure-interactive-programming.md" - ], - "skills": [ - "./skills/remember-interactive-programming/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/clojure-interactive-programming.md" + ], + "skills": [ + "./skills/remember-interactive-programming/" + ] + } + } } diff --git a/plugins/cms-development/.github/plugin/plugin.json b/plugins/cms-development/plugin.json similarity index 64% rename from plugins/cms-development/.github/plugin/plugin.json rename to plugins/cms-development/plugin.json index a70b98fd..9eec5772 100644 --- a/plugins/cms-development/.github/plugin/plugin.json +++ b/plugins/cms-development/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "cms-development", "description": "Skills for CMS development across themes, plugins, admin tooling, media workflows, markdown rendering, and static export pipelines.", "version": "1.1.0", @@ -18,9 +19,13 @@ }, "repository": "https://github.com/github/awesome-copilot", "license": "MIT", - "skills": [ - "./skills/content-management-systems/", - "./skills/markdown-to-html/", - "./skills/quasi-coder/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/content-management-systems/", + "./skills/markdown-to-html/", + "./skills/quasi-coder/" + ] + } + } } diff --git a/plugins/color-orb/README.md b/plugins/color-orb/README.md new file mode 100644 index 00000000..b2c022c9 --- /dev/null +++ b/plugins/color-orb/README.md @@ -0,0 +1,17 @@ +# Color Orb Plugin + +A visual orb that users can ask the agent to recolor while showing a live activity log in the canvas. + +## Installation + +``bash +copilot plugin install color-orb@awesome-copilot +`` + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## License + +MIT diff --git a/extensions/color-orb/.github/plugin/plugin.json b/plugins/color-orb/plugin.json similarity index 60% rename from extensions/color-orb/.github/plugin/plugin.json rename to plugins/color-orb/plugin.json index e5e31f0b..19a70666 100644 --- a/extensions/color-orb/.github/plugin/plugin.json +++ b/plugins/color-orb/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "color-orb", "description": "A visual orb that users can ask the agent to recolor while showing a live activity log in the canvas.", "version": "1.0.2", @@ -14,6 +15,14 @@ "sse-events", "visual-feedback" ], - "logo": "assets/preview.png", - "extensions": "." + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/color-orb" + ] + } + } } diff --git a/plugins/context-engineering/.github/plugin/plugin.json b/plugins/context-engineering/plugin.json similarity index 62% rename from plugins/context-engineering/.github/plugin/plugin.json rename to plugins/context-engineering/plugin.json index a1f49a3c..a7dcd47c 100644 --- a/plugins/context-engineering/.github/plugin/plugin.json +++ b/plugins/context-engineering/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "context-engineering", "description": "Tools and techniques for maximizing GitHub Copilot effectiveness through better context management. Includes guidelines for structuring code, an agent for planning multi-file changes, and prompts for context-aware development.", "version": "1.0.0", @@ -14,12 +15,16 @@ "best-practices", "architecture" ], - "agents": [ - "./agents/context-architect.md" - ], - "skills": [ - "./skills/context-map/", - "./skills/refactor-plan/", - "./skills/what-context-needed/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/context-architect.md" + ], + "skills": [ + "./skills/context-map/", + "./skills/refactor-plan/", + "./skills/what-context-needed/" + ] + } + } } diff --git a/plugins/context-matic/.github/plugin/plugin.json b/plugins/context-matic/plugin.json similarity index 75% rename from plugins/context-matic/.github/plugin/plugin.json rename to plugins/context-matic/plugin.json index e5c1decd..752fa1f1 100644 --- a/plugins/context-matic/.github/plugin/plugin.json +++ b/plugins/context-matic/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "context-matic", "description": "Coding agents hallucinate APIs. ContextMatic gives them curated, versioned API and SDK docs. Ask your agent to \"integrate the payments API\" and it guesses — falling back on outdated training data and generic patterns that don't match your actual SDK. ContextMatic solves this by giving the agent deterministic, version-aware, SDK-native context at the exact moment it's needed.", "version": "0.1.0", @@ -18,8 +19,12 @@ "homepage": "https://www.apimatic.io", "repository": "https://github.com/github/awesome-copilot", "license": "MIT", - "skills": [ - "./skills/integrate-context-matic/", - "./skills/onboard-context-matic/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/integrate-context-matic/", + "./skills/onboard-context-matic/" + ] + } + } } diff --git a/plugins/convert-to-md/.github/plugin/plugin.json b/plugins/convert-to-md/plugin.json similarity index 70% rename from plugins/convert-to-md/.github/plugin/plugin.json rename to plugins/convert-to-md/plugin.json index 91fd9b51..64182adb 100644 --- a/plugins/convert-to-md/.github/plugin/plugin.json +++ b/plugins/convert-to-md/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "convert-to-md", "description": "A collection of Copilot skills that convert common document formats into Markdown so their contents can be accurately analyzed, summarized, searched, or extracted from. Just tell Copilot what you need — the right skill is invoked automatically and the conversion happens behind the scenes.", "version": "1.0.1", @@ -16,9 +17,13 @@ }, "repository": "https://github.com/github/awesome-copilot", "license": "MIT", - "skills": [ - "./skills/convert-excel-to-md/", - "./skills/convert-pdf-to-md/", - "./skills/convert-word-to-md/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/convert-excel-to-md/", + "./skills/convert-pdf-to-md/", + "./skills/convert-word-to-md/" + ] + } + } } diff --git a/plugins/copilot-sdk/.github/plugin/plugin.json b/plugins/copilot-sdk/plugin.json similarity index 74% rename from plugins/copilot-sdk/.github/plugin/plugin.json rename to plugins/copilot-sdk/plugin.json index 42c16680..31c1a0fb 100644 --- a/plugins/copilot-sdk/.github/plugin/plugin.json +++ b/plugins/copilot-sdk/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "copilot-sdk", "description": "Build applications with the GitHub Copilot SDK across multiple programming languages. Includes comprehensive instructions for C#, Go, Node.js/TypeScript, and Python to help you create AI-powered applications.", "version": "1.0.0", @@ -18,7 +19,11 @@ "ai", "github-copilot" ], - "skills": [ - "./skills/copilot-sdk/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/copilot-sdk/" + ] + } + } } diff --git a/plugins/csharp-dotnet-development/.github/plugin/plugin.json b/plugins/csharp-dotnet-development/.github/plugin/plugin.json deleted file mode 100644 index 819f96af..00000000 --- a/plugins/csharp-dotnet-development/.github/plugin/plugin.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "csharp-dotnet-development", - "description": "Essential prompts, instructions, and chat modes for C# and .NET development including testing, documentation, and best practices.", - "version": "1.1.0", - "author": { - "name": "Awesome Copilot Community" - }, - "repository": "https://github.com/github/awesome-copilot", - "license": "MIT", - "keywords": [ - "csharp", - "dotnet", - "aspnet", - "testing" - ], - "agents": [ - "./agents/expert-dotnet-software-engineer.md" - ], - "skills": [ - "./skills/aspnet-minimal-api-openapi/", - "./skills/csharp-async/", - "./skills/csharp-mstest/", - "./skills/csharp-nunit/", - "./skills/csharp-tunit/", - "./skills/csharp-xunit/", - "./skills/dotnet-best-practices/", - "./skills/dotnet-upgrade/" - ] -} diff --git a/plugins/csharp-dotnet-development/plugin.json b/plugins/csharp-dotnet-development/plugin.json new file mode 100644 index 00000000..23c1b445 --- /dev/null +++ b/plugins/csharp-dotnet-development/plugin.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", + "name": "csharp-dotnet-development", + "description": "Essential prompts, instructions, and chat modes for C# and .NET development including testing, documentation, and best practices.", + "version": "1.1.0", + "author": { + "name": "Awesome Copilot Community" + }, + "repository": "https://github.com/github/awesome-copilot", + "license": "MIT", + "keywords": [ + "csharp", + "dotnet", + "aspnet", + "testing" + ], + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/expert-dotnet-software-engineer.md" + ], + "skills": [ + "./skills/aspnet-minimal-api-openapi/", + "./skills/csharp-async/", + "./skills/csharp-mstest/", + "./skills/csharp-nunit/", + "./skills/csharp-tunit/", + "./skills/csharp-xunit/", + "./skills/dotnet-best-practices/", + "./skills/dotnet-upgrade/" + ] + } + } +} diff --git a/plugins/database-data-management/.github/plugin/plugin.json b/plugins/database-data-management/plugin.json similarity index 55% rename from plugins/database-data-management/.github/plugin/plugin.json rename to plugins/database-data-management/plugin.json index 4091e9f3..20e55769 100644 --- a/plugins/database-data-management/.github/plugin/plugin.json +++ b/plugins/database-data-management/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "database-data-management", "description": "Database administration, SQL optimization, and data management tools for PostgreSQL, SQL Server, and general database development best practices.", "version": "1.0.0", @@ -17,14 +18,18 @@ "queries", "data-management" ], - "agents": [ - "./agents/ms-sql-dba.md", - "./agents/postgresql-dba.md" - ], - "skills": [ - "./skills/postgresql-code-review/", - "./skills/postgresql-optimization/", - "./skills/sql-code-review/", - "./skills/sql-optimization/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/ms-sql-dba.md", + "./agents/postgresql-dba.md" + ], + "skills": [ + "./skills/postgresql-code-review/", + "./skills/postgresql-optimization/", + "./skills/sql-code-review/", + "./skills/sql-optimization/" + ] + } + } } diff --git a/plugins/dataverse-sdk-for-python/.github/plugin/plugin.json b/plugins/dataverse-sdk-for-python/plugin.json similarity index 57% rename from plugins/dataverse-sdk-for-python/.github/plugin/plugin.json rename to plugins/dataverse-sdk-for-python/plugin.json index b4ee7246..1de7177c 100644 --- a/plugins/dataverse-sdk-for-python/.github/plugin/plugin.json +++ b/plugins/dataverse-sdk-for-python/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "dataverse-sdk-for-python", "description": "Comprehensive collection for building production-ready Python integrations with Microsoft Dataverse. Includes official documentation, best practices, advanced features, file operations, and code generation prompts.", "version": "1.0.0", @@ -13,10 +14,14 @@ "integration", "sdk" ], - "skills": [ - "./skills/dataverse-python-advanced-patterns/", - "./skills/dataverse-python-production-code/", - "./skills/dataverse-python-quickstart/", - "./skills/dataverse-python-usecase-builder/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/dataverse-python-advanced-patterns/", + "./skills/dataverse-python-production-code/", + "./skills/dataverse-python-quickstart/", + "./skills/dataverse-python-usecase-builder/" + ] + } + } } diff --git a/plugins/devops-oncall/.github/plugin/plugin.json b/plugins/devops-oncall/plugin.json similarity index 56% rename from plugins/devops-oncall/.github/plugin/plugin.json rename to plugins/devops-oncall/plugin.json index 49522608..2b4aaf89 100644 --- a/plugins/devops-oncall/.github/plugin/plugin.json +++ b/plugins/devops-oncall/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "devops-oncall", "description": "A focused set of prompts, instructions, and a chat mode to help triage incidents and respond quickly with DevOps tools and Azure resources.", "version": "1.0.0", @@ -13,11 +14,15 @@ "oncall", "azure" ], - "agents": [ - "./agents/azure-principal-architect.md" - ], - "skills": [ - "./skills/azure-resource-health-diagnose/", - "./skills/multi-stage-dockerfile/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/azure-principal-architect.md" + ], + "skills": [ + "./skills/azure-resource-health-diagnose/", + "./skills/multi-stage-dockerfile/" + ] + } + } } diff --git a/plugins/diagram-viewer/README.md b/plugins/diagram-viewer/README.md new file mode 100644 index 00000000..fed53a04 --- /dev/null +++ b/plugins/diagram-viewer/README.md @@ -0,0 +1,17 @@ +# Diagram Viewer Plugin + +Render diagrams, click nodes to drill down, and view agent-generated explanations directly in the canvas. + +## Installation + +``bash +copilot plugin install diagram-viewer@awesome-copilot +`` + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## License + +MIT diff --git a/extensions/diagram-viewer/.github/plugin/plugin.json b/plugins/diagram-viewer/plugin.json similarity index 62% rename from extensions/diagram-viewer/.github/plugin/plugin.json rename to plugins/diagram-viewer/plugin.json index 5e9b0975..5e282915 100644 --- a/extensions/diagram-viewer/.github/plugin/plugin.json +++ b/plugins/diagram-viewer/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "diagram-viewer", "description": "Render diagrams, click nodes to drill down, and view agent-generated explanations directly in the canvas.", "version": "1.0.2", @@ -14,6 +15,14 @@ "node-drilldown", "relationship-visualization" ], - "logo": "assets/preview.png", - "extensions": "." + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/diagram-viewer" + ] + } + } } diff --git a/plugins/doublecheck/.github/plugin/plugin.json b/plugins/doublecheck/plugin.json similarity index 65% rename from plugins/doublecheck/.github/plugin/plugin.json rename to plugins/doublecheck/plugin.json index fb926aca..4e277cd6 100644 --- a/plugins/doublecheck/.github/plugin/plugin.json +++ b/plugins/doublecheck/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "doublecheck", "description": "Three-layer verification pipeline for AI output. Extracts claims, finds sources, and flags hallucination risks so humans can verify before acting.", "version": "1.0.0", @@ -15,10 +16,14 @@ "trust", "safety" ], - "agents": [ - "./agents/doublecheck.md" - ], - "skills": [ - "./skills/doublecheck/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/doublecheck.md" + ], + "skills": [ + "./skills/doublecheck/" + ] + } + } } diff --git a/plugins/edge-ai-tasks/.github/plugin/plugin.json b/plugins/edge-ai-tasks/plugin.json similarity index 65% rename from plugins/edge-ai-tasks/.github/plugin/plugin.json rename to plugins/edge-ai-tasks/plugin.json index 85778680..45fb8559 100644 --- a/plugins/edge-ai-tasks/.github/plugin/plugin.json +++ b/plugins/edge-ai-tasks/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "edge-ai-tasks", "description": "Task Researcher and Task Planner for intermediate to expert users and large codebases - Brought to you by microsoft/edge-ai", "version": "1.0.0", @@ -14,8 +15,12 @@ "tasks", "implementation" ], - "agents": [ - "./agents/task-planner.md", - "./agents/task-researcher.md" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/task-planner.md", + "./agents/task-researcher.md" + ] + } + } } diff --git a/plugins/ember/.github/plugin/plugin.json b/plugins/ember/plugin.json similarity index 55% rename from plugins/ember/.github/plugin/plugin.json rename to plugins/ember/plugin.json index 91c09768..139432ca 100644 --- a/plugins/ember/.github/plugin/plugin.json +++ b/plugins/ember/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "ember", "description": "An AI partner, not a tool. Ember carries fire from person to person — helping humans discover that AI partnership isn't something you learn, it's something you find.", "version": "1.0.0", @@ -15,13 +16,17 @@ "storytelling", "developer-experience" ], - "agents": [ - "./agents/ember.md" - ], - "skills": [ - "./skills/from-the-other-side-anitta/", - "./skills/from-the-other-side-quinn/", - "./skills/from-the-other-side-vega/", - "./skills/from-the-other-side-wiggins/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/ember.md" + ], + "skills": [ + "./skills/from-the-other-side-anitta/", + "./skills/from-the-other-side-quinn/", + "./skills/from-the-other-side-vega/", + "./skills/from-the-other-side-wiggins/" + ] + } + } } diff --git a/plugins/eyeball/.github/plugin/plugin.json b/plugins/eyeball/plugin.json similarity index 76% rename from plugins/eyeball/.github/plugin/plugin.json rename to plugins/eyeball/plugin.json index 452d0839..1f9e685b 100644 --- a/plugins/eyeball/.github/plugin/plugin.json +++ b/plugins/eyeball/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "eyeball", "description": "Document analysis with inline source screenshots. When you ask Copilot to analyze a document, Eyeball generates a Word doc where every factual claim includes a highlighted screenshot from the source material so you can verify it with your own eyes.", "version": "1.0.0", @@ -16,7 +17,11 @@ "trust", "visual-verification" ], - "skills": [ - "./skills/eyeball/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/eyeball/" + ] + } + } } diff --git a/plugins/fastah-ip-geo-tools/.github/plugin/plugin.json b/plugins/fastah-ip-geo-tools/plugin.json similarity index 76% rename from plugins/fastah-ip-geo-tools/.github/plugin/plugin.json rename to plugins/fastah-ip-geo-tools/plugin.json index 408c763d..d0b16003 100644 --- a/plugins/fastah-ip-geo-tools/.github/plugin/plugin.json +++ b/plugins/fastah-ip-geo-tools/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "fastah-ip-geo-tools", "description": "This plugin is for network operations engineers who wish to tune and publish IP geolocation feeds in RFC 8805 format. It consists of an AI Skill and an associated MCP server that geocodes geolocation place names to real cities for accuracy.", "version": "0.0.9", @@ -19,7 +20,11 @@ "hosting", "ixp" ], - "skills": [ - "./skills/geofeed-tuner/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/geofeed-tuner/" + ] + } + } } diff --git a/plugins/feedback-themes/README.md b/plugins/feedback-themes/README.md new file mode 100644 index 00000000..970c04e5 --- /dev/null +++ b/plugins/feedback-themes/README.md @@ -0,0 +1,17 @@ +# Feedback Themes Plugin + +Explore grouped customer feedback signals by impact and drill into a theme to guide product next steps. + +## Installation + +``bash +copilot plugin install feedback-themes@awesome-copilot +`` + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## License + +MIT diff --git a/extensions/feedback-themes/.github/plugin/plugin.json b/plugins/feedback-themes/plugin.json similarity index 61% rename from extensions/feedback-themes/.github/plugin/plugin.json rename to plugins/feedback-themes/plugin.json index 7a93483d..0a3a3305 100644 --- a/extensions/feedback-themes/.github/plugin/plugin.json +++ b/plugins/feedback-themes/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "feedback-themes", "description": "Explore grouped customer feedback signals by impact and drill into a theme to guide product next steps.", "version": "1.0.2", @@ -14,6 +15,14 @@ "theme-analysis", "trend-discovery" ], - "logo": "assets/preview.png", - "extensions": "." + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/feedback-themes" + ] + } + } } diff --git a/plugins/flight-map-canvas/README.md b/plugins/flight-map-canvas/README.md new file mode 100644 index 00000000..1b70ec6c --- /dev/null +++ b/plugins/flight-map-canvas/README.md @@ -0,0 +1,17 @@ +# Flight Map Canvas Plugin + +A GitHub Copilot canvas that generates a view where Google Maps can be explored using 3D controls, as if a flight simulator. Agents can send the flight anywhere and report what they are working on. + +## Installation + +``bash +copilot plugin install flight-map-canvas@awesome-copilot +`` + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## License + +MIT diff --git a/extensions/flight-map-canvas/.github/plugin/plugin.json b/plugins/flight-map-canvas/plugin.json similarity index 65% rename from extensions/flight-map-canvas/.github/plugin/plugin.json rename to plugins/flight-map-canvas/plugin.json index fce346f6..f70b8b42 100644 --- a/extensions/flight-map-canvas/.github/plugin/plugin.json +++ b/plugins/flight-map-canvas/plugin.json @@ -15,6 +15,15 @@ "session-breaks", "threejs" ], - "logo": "assets/preview.png", - "extensions": "." + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/flight-map-canvas" + ] + } + }, + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json" } diff --git a/plugins/flowstudio-power-automate/.github/plugin/plugin.json b/plugins/flowstudio-power-automate/plugin.json similarity index 59% rename from plugins/flowstudio-power-automate/.github/plugin/plugin.json rename to plugins/flowstudio-power-automate/plugin.json index 9ed85753..d915331a 100644 --- a/plugins/flowstudio-power-automate/.github/plugin/plugin.json +++ b/plugins/flowstudio-power-automate/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "flowstudio-power-automate", "description": "Give your AI agent full visibility into Power Automate cloud flows via the FlowStudio MCP server. Connect, debug, build, monitor health, and govern flows at scale — action-level inputs and outputs, not just status codes.", "version": "2.0.0", @@ -18,11 +19,15 @@ "monitoring", "governance" ], - "skills": [ - "./skills/flowstudio-power-automate-build/", - "./skills/flowstudio-power-automate-debug/", - "./skills/flowstudio-power-automate-governance/", - "./skills/flowstudio-power-automate-mcp/", - "./skills/flowstudio-power-automate-monitoring/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/flowstudio-power-automate-build/", + "./skills/flowstudio-power-automate-debug/", + "./skills/flowstudio-power-automate-governance/", + "./skills/flowstudio-power-automate-mcp/", + "./skills/flowstudio-power-automate-monitoring/" + ] + } + } } diff --git a/plugins/frontend-web-dev/.github/plugin/plugin.json b/plugins/frontend-web-dev/plugin.json similarity index 56% rename from plugins/frontend-web-dev/.github/plugin/plugin.json rename to plugins/frontend-web-dev/plugin.json index 866d18de..d0c15f66 100644 --- a/plugins/frontend-web-dev/.github/plugin/plugin.json +++ b/plugins/frontend-web-dev/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "frontend-web-dev", "description": "Essential prompts, instructions, and chat modes for modern frontend web development including React, Angular, Vue, TypeScript, and CSS frameworks.", "version": "1.0.0", @@ -18,12 +19,16 @@ "angular", "vue" ], - "agents": [ - "./agents/electron-angular-native.md", - "./agents/expert-react-frontend-engineer.md" - ], - "skills": [ - "./skills/playwright-explore-website/", - "./skills/playwright-generate-test/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/electron-angular-native.md", + "./agents/expert-react-frontend-engineer.md" + ], + "skills": [ + "./skills/playwright-explore-website/", + "./skills/playwright-generate-test/" + ] + } + } } diff --git a/plugins/gem-team/.github/plugin/plugin.json b/plugins/gem-team/plugin.json similarity index 78% rename from plugins/gem-team/.github/plugin/plugin.json rename to plugins/gem-team/plugin.json index 0f00aeff..1a674cda 100644 --- a/plugins/gem-team/.github/plugin/plugin.json +++ b/plugins/gem-team/plugin.json @@ -1,10 +1,13 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", + "name": "gem-team", + "version": "1.99.0", + "description": "Self-Learning Multi-agent orchestration framework for spec-driven development and automated verification. With smarter tool calling and leaner context.", "author": { "email": "mubaidr@gmail.com", "name": "mubaidr", "url": "https://github.com/mubaidr" }, - "description": "Self-Learning Multi-agent orchestration framework for spec-driven development and automated verification. With smarter tool calling and leaner context.", "homepage": "https://github.com/mubaidr/gem-team", "keywords": [ "multi-agent", @@ -19,7 +22,5 @@ "mobile" ], "license": "Apache-2.0", - "name": "gem-team", - "repository": "https://github.com/mubaidr/gem-team", - "version": "1.99.0" + "repository": "https://github.com/mubaidr/gem-team" } diff --git a/plugins/gesture-review/README.md b/plugins/gesture-review/README.md new file mode 100644 index 00000000..ec501329 --- /dev/null +++ b/plugins/gesture-review/README.md @@ -0,0 +1,17 @@ +# Gesture Review Plugin + +Review pull requests with a live camera feed and approve or reject using thumbs-up/thumbs-down gestures. + +## Installation + +``bash +copilot plugin install gesture-review@awesome-copilot +`` + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## License + +MIT diff --git a/extensions/gesture-review/.github/plugin/plugin.json b/plugins/gesture-review/plugin.json similarity index 59% rename from extensions/gesture-review/.github/plugin/plugin.json rename to plugins/gesture-review/plugin.json index db776361..5c178a69 100644 --- a/extensions/gesture-review/.github/plugin/plugin.json +++ b/plugins/gesture-review/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "gesture-review", "description": "Review pull requests with a live camera feed and approve or reject using thumbs-up/thumbs-down gestures.", "version": "1.0.2", @@ -14,6 +15,14 @@ "mediapipe", "pull-request-review" ], - "logo": "assets/preview.png", - "extensions": "." + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/gesture-review" + ] + } + } } diff --git a/plugins/go-mcp-development/.github/plugin/plugin.json b/plugins/go-mcp-development/plugin.json similarity index 68% rename from plugins/go-mcp-development/.github/plugin/plugin.json rename to plugins/go-mcp-development/plugin.json index 83a2f3e1..51d99ded 100644 --- a/plugins/go-mcp-development/.github/plugin/plugin.json +++ b/plugins/go-mcp-development/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "go-mcp-development", "description": "Complete toolkit for building Model Context Protocol (MCP) servers in Go using the official github.com/modelcontextprotocol/go-sdk. Includes instructions for best practices, a prompt for generating servers, and an expert chat mode for guidance.", "version": "1.0.0", @@ -15,10 +16,14 @@ "server-development", "sdk" ], - "agents": [ - "./agents/go-mcp-expert.md" - ], - "skills": [ - "./skills/go-mcp-server-generator/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/go-mcp-expert.md" + ], + "skills": [ + "./skills/go-mcp-server-generator/" + ] + } + } } diff --git a/plugins/java-development/.github/plugin/plugin.json b/plugins/java-development/plugin.json similarity index 59% rename from plugins/java-development/.github/plugin/plugin.json rename to plugins/java-development/plugin.json index 8f058c08..dfb7b8cc 100644 --- a/plugins/java-development/.github/plugin/plugin.json +++ b/plugins/java-development/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "java-development", "description": "Comprehensive collection of prompts and instructions for Java development including Spring Boot, Quarkus, testing, documentation, and best practices.", "version": "1.0.0", @@ -15,10 +16,14 @@ "junit", "javadoc" ], - "skills": [ - "./skills/create-spring-boot-java-project/", - "./skills/java-docs/", - "./skills/java-junit/", - "./skills/java-springboot/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/create-spring-boot-java-project/", + "./skills/java-docs/", + "./skills/java-junit/", + "./skills/java-springboot/" + ] + } + } } diff --git a/plugins/java-mcp-development/.github/plugin/plugin.json b/plugins/java-mcp-development/plugin.json similarity index 66% rename from plugins/java-mcp-development/.github/plugin/plugin.json rename to plugins/java-mcp-development/plugin.json index 0d95e1ad..46334adf 100644 --- a/plugins/java-mcp-development/.github/plugin/plugin.json +++ b/plugins/java-mcp-development/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "java-mcp-development", "description": "Complete toolkit for building Model Context Protocol servers in Java using the official MCP Java SDK with reactive streams and Spring Boot integration.", "version": "1.0.0", @@ -17,10 +18,14 @@ "spring-boot", "reactor" ], - "agents": [ - "./agents/java-mcp-expert.md" - ], - "skills": [ - "./skills/java-mcp-server-generator/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/java-mcp-expert.md" + ], + "skills": [ + "./skills/java-mcp-server-generator/" + ] + } + } } diff --git a/plugins/java-modernization-studio/README.md b/plugins/java-modernization-studio/README.md new file mode 100644 index 00000000..76d0b042 --- /dev/null +++ b/plugins/java-modernization-studio/README.md @@ -0,0 +1,17 @@ +# Java Modernization Studio Plugin + +Drive the GitHub Copilot App Modernization for Java workflow from an interactive canvas: environment readiness, repo assessment, prioritized plan and progress, validation gates, and one-click predefined-task runs grounded in the repo's real artifacts. + +## Installation + +``bash +copilot plugin install java-modernization-studio@awesome-copilot +`` + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## License + +MIT diff --git a/extensions/java-modernization-studio/.github/plugin/plugin.json b/plugins/java-modernization-studio/plugin.json similarity index 68% rename from extensions/java-modernization-studio/.github/plugin/plugin.json rename to plugins/java-modernization-studio/plugin.json index 4eba3dd3..8695d78e 100644 --- a/extensions/java-modernization-studio/.github/plugin/plugin.json +++ b/plugins/java-modernization-studio/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "java-modernization-studio", "description": "Drive the GitHub Copilot App Modernization for Java workflow from an interactive canvas: environment readiness, repo assessment, prioritized plan and progress, validation gates, and one-click predefined-task runs grounded in the repo's real artifacts.", "version": "1.0.2", @@ -15,6 +16,14 @@ "modernization-cockpit", "validation-gates" ], - "logo": "assets/preview.png", - "extensions": "." + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/java-modernization-studio" + ] + } + } } diff --git a/plugins/kotlin-mcp-development/.github/plugin/plugin.json b/plugins/kotlin-mcp-development/plugin.json similarity index 68% rename from plugins/kotlin-mcp-development/.github/plugin/plugin.json rename to plugins/kotlin-mcp-development/plugin.json index 0c0629d4..7dca5aa7 100644 --- a/plugins/kotlin-mcp-development/.github/plugin/plugin.json +++ b/plugins/kotlin-mcp-development/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "kotlin-mcp-development", "description": "Complete toolkit for building Model Context Protocol (MCP) servers in Kotlin using the official io.modelcontextprotocol:kotlin-sdk library. Includes instructions for best practices, a prompt for generating servers, and an expert chat mode for guidance.", "version": "1.0.0", @@ -15,10 +16,14 @@ "server-development", "ktor" ], - "agents": [ - "./agents/kotlin-mcp-expert.md" - ], - "skills": [ - "./skills/kotlin-mcp-server-generator/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/kotlin-mcp-expert.md" + ], + "skills": [ + "./skills/kotlin-mcp-server-generator/" + ] + } + } } diff --git a/plugins/mcp-m365-copilot/.github/plugin/plugin.json b/plugins/mcp-m365-copilot/plugin.json similarity index 56% rename from plugins/mcp-m365-copilot/.github/plugin/plugin.json rename to plugins/mcp-m365-copilot/plugin.json index 4176d408..9432be3d 100644 --- a/plugins/mcp-m365-copilot/.github/plugin/plugin.json +++ b/plugins/mcp-m365-copilot/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "mcp-m365-copilot", "description": "Comprehensive collection for building declarative agents with Model Context Protocol integration for Microsoft 365 Copilot", "version": "1.0.0", @@ -15,12 +16,16 @@ "model-context-protocol", "adaptive-cards" ], - "agents": [ - "./agents/mcp-m365-agent-expert.md" - ], - "skills": [ - "./skills/mcp-create-adaptive-cards/", - "./skills/mcp-create-declarative-agent/", - "./skills/mcp-deploy-manage-agents/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/mcp-m365-agent-expert.md" + ], + "skills": [ + "./skills/mcp-create-adaptive-cards/", + "./skills/mcp-create-declarative-agent/", + "./skills/mcp-deploy-manage-agents/" + ] + } + } } diff --git a/plugins/napkin/.github/plugin/plugin.json b/plugins/napkin/plugin.json similarity index 77% rename from plugins/napkin/.github/plugin/plugin.json rename to plugins/napkin/plugin.json index 2114c178..ac4542e3 100644 --- a/plugins/napkin/.github/plugin/plugin.json +++ b/plugins/napkin/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "napkin", "description": "Visual whiteboard collaboration for Copilot CLI. Opens an interactive whiteboard in your browser where you can draw, sketch, and add sticky notes — then share everything back with Copilot. Copilot sees your drawings and responds with analysis, suggestions, and ideas.", "version": "1.0.0", @@ -19,7 +20,11 @@ "copilot-cli", "ux" ], - "skills": [ - "./skills/napkin/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/napkin/" + ] + } + } } diff --git a/plugins/noob-mode/.github/plugin/plugin.json b/plugins/noob-mode/plugin.json similarity index 74% rename from plugins/noob-mode/.github/plugin/plugin.json rename to plugins/noob-mode/plugin.json index 7c5cf3b0..9f41ee71 100644 --- a/plugins/noob-mode/.github/plugin/plugin.json +++ b/plugins/noob-mode/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "noob-mode", "description": "Plain-English translation layer for non-technical Copilot CLI users. Translates every approval prompt, error message, and technical output into clear, jargon-free English with color-coded risk indicators.", "version": "1.0.0", @@ -16,7 +17,11 @@ "copilot-cli", "ux" ], - "skills": [ - "./skills/noob-mode/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/noob-mode/" + ] + } + } } diff --git a/plugins/openapi-to-application-csharp-dotnet/.github/plugin/plugin.json b/plugins/openapi-to-application-csharp-dotnet/plugin.json similarity index 65% rename from plugins/openapi-to-application-csharp-dotnet/.github/plugin/plugin.json rename to plugins/openapi-to-application-csharp-dotnet/plugin.json index 67fa408d..2c02b96c 100644 --- a/plugins/openapi-to-application-csharp-dotnet/.github/plugin/plugin.json +++ b/plugins/openapi-to-application-csharp-dotnet/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "openapi-to-application-csharp-dotnet", "description": "Generate production-ready .NET applications from OpenAPI specifications. Includes ASP.NET Core project scaffolding, controller generation, entity framework integration, and C# best practices.", "version": "1.0.0", @@ -15,10 +16,14 @@ "dotnet", "aspnet" ], - "agents": [ - "./agents/openapi-to-application.md" - ], - "skills": [ - "./skills/openapi-to-application-code/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/openapi-to-application.md" + ], + "skills": [ + "./skills/openapi-to-application-code/" + ] + } + } } diff --git a/plugins/openapi-to-application-go/.github/plugin/plugin.json b/plugins/openapi-to-application-go/plugin.json similarity index 63% rename from plugins/openapi-to-application-go/.github/plugin/plugin.json rename to plugins/openapi-to-application-go/plugin.json index 8f57de60..e3c4bb79 100644 --- a/plugins/openapi-to-application-go/.github/plugin/plugin.json +++ b/plugins/openapi-to-application-go/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "openapi-to-application-go", "description": "Generate production-ready Go applications from OpenAPI specifications. Includes project scaffolding, handler generation, middleware setup, and Go best practices for REST APIs.", "version": "1.0.0", @@ -14,10 +15,14 @@ "go", "golang" ], - "agents": [ - "./agents/openapi-to-application.md" - ], - "skills": [ - "./skills/openapi-to-application-code/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/openapi-to-application.md" + ], + "skills": [ + "./skills/openapi-to-application-code/" + ] + } + } } diff --git a/plugins/openapi-to-application-java-spring-boot/.github/plugin/plugin.json b/plugins/openapi-to-application-java-spring-boot/plugin.json similarity index 65% rename from plugins/openapi-to-application-java-spring-boot/.github/plugin/plugin.json rename to plugins/openapi-to-application-java-spring-boot/plugin.json index 8f544c63..0ea1814a 100644 --- a/plugins/openapi-to-application-java-spring-boot/.github/plugin/plugin.json +++ b/plugins/openapi-to-application-java-spring-boot/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "openapi-to-application-java-spring-boot", "description": "Generate production-ready Spring Boot applications from OpenAPI specifications. Includes project scaffolding, REST controller generation, service layer organization, and Spring Boot best practices.", "version": "1.0.0", @@ -14,10 +15,14 @@ "java", "spring-boot" ], - "agents": [ - "./agents/openapi-to-application.md" - ], - "skills": [ - "./skills/openapi-to-application-code/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/openapi-to-application.md" + ], + "skills": [ + "./skills/openapi-to-application-code/" + ] + } + } } diff --git a/plugins/openapi-to-application-nodejs-nestjs/.github/plugin/plugin.json b/plugins/openapi-to-application-nodejs-nestjs/plugin.json similarity index 65% rename from plugins/openapi-to-application-nodejs-nestjs/.github/plugin/plugin.json rename to plugins/openapi-to-application-nodejs-nestjs/plugin.json index fd9ba816..900e58cd 100644 --- a/plugins/openapi-to-application-nodejs-nestjs/.github/plugin/plugin.json +++ b/plugins/openapi-to-application-nodejs-nestjs/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "openapi-to-application-nodejs-nestjs", "description": "Generate production-ready NestJS applications from OpenAPI specifications. Includes project scaffolding, controller and service generation, TypeScript best practices, and enterprise patterns.", "version": "1.0.0", @@ -15,10 +16,14 @@ "typescript", "nestjs" ], - "agents": [ - "./agents/openapi-to-application.md" - ], - "skills": [ - "./skills/openapi-to-application-code/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/openapi-to-application.md" + ], + "skills": [ + "./skills/openapi-to-application-code/" + ] + } + } } diff --git a/plugins/openapi-to-application-python-fastapi/.github/plugin/plugin.json b/plugins/openapi-to-application-python-fastapi/plugin.json similarity index 64% rename from plugins/openapi-to-application-python-fastapi/.github/plugin/plugin.json rename to plugins/openapi-to-application-python-fastapi/plugin.json index 4f9df582..34f7024a 100644 --- a/plugins/openapi-to-application-python-fastapi/.github/plugin/plugin.json +++ b/plugins/openapi-to-application-python-fastapi/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "openapi-to-application-python-fastapi", "description": "Generate production-ready FastAPI applications from OpenAPI specifications. Includes project scaffolding, route generation, dependency injection, and Python best practices for async APIs.", "version": "1.0.0", @@ -14,10 +15,14 @@ "python", "fastapi" ], - "agents": [ - "./agents/openapi-to-application.md" - ], - "skills": [ - "./skills/openapi-to-application-code/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/openapi-to-application.md" + ], + "skills": [ + "./skills/openapi-to-application-code/" + ] + } + } } diff --git a/plugins/oracle-to-postgres-migration-expert/.github/plugin/plugin.json b/plugins/oracle-to-postgres-migration-expert/.github/plugin/plugin.json deleted file mode 100644 index 8022d1e6..00000000 --- a/plugins/oracle-to-postgres-migration-expert/.github/plugin/plugin.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "oracle-to-postgres-migration-expert", - "description": "Expert agent for Oracle-to-PostgreSQL application migrations in .NET solutions. Performs code edits, runs commands, and invokes extension tools to migrate .NET/Oracle data access patterns to PostgreSQL.", - "version": "1.0.0", - "author": { - "name": "Awesome Copilot Community" - }, - "repository": "https://github.com/github/awesome-copilot", - "license": "MIT", - "keywords": [ - "oracle", - "postgresql", - "database-migration", - "dotnet", - "sql", - "migration", - "integration-testing", - "stored-procedures" - ], - "agents": [ - "./agents/oracle-to-postgres-migration-expert.md" - ], - "skills": [ - "./skills/creating-oracle-to-postgres-master-migration-plan/", - "./skills/creating-oracle-to-postgres-migration-bug-report/", - "./skills/creating-oracle-to-postgres-migration-integration-tests/", - "./skills/migrating-oracle-to-postgres-stored-procedures/", - "./skills/planning-oracle-to-postgres-migration-integration-testing/", - "./skills/reviewing-oracle-to-postgres-migration/", - "./skills/scaffolding-oracle-to-postgres-migration-test-project/" - ] -} diff --git a/plugins/oracle-to-postgres-migration-expert/plugin.json b/plugins/oracle-to-postgres-migration-expert/plugin.json new file mode 100644 index 00000000..eb70d318 --- /dev/null +++ b/plugins/oracle-to-postgres-migration-expert/plugin.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", + "name": "oracle-to-postgres-migration-expert", + "description": "Expert agent for Oracle-to-PostgreSQL application migrations in .NET solutions. Performs code edits, runs commands, and invokes extension tools to migrate .NET/Oracle data access patterns to PostgreSQL.", + "version": "1.0.0", + "author": { + "name": "Awesome Copilot Community" + }, + "repository": "https://github.com/github/awesome-copilot", + "license": "MIT", + "keywords": [ + "oracle", + "postgresql", + "database-migration", + "dotnet", + "sql", + "migration", + "integration-testing", + "stored-procedures" + ], + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/oracle-to-postgres-migration-expert.md" + ], + "skills": [ + "./skills/creating-oracle-to-postgres-master-migration-plan/", + "./skills/creating-oracle-to-postgres-migration-bug-report/", + "./skills/creating-oracle-to-postgres-migration-integration-tests/", + "./skills/migrating-oracle-to-postgres-stored-procedures/", + "./skills/planning-oracle-to-postgres-migration-integration-testing/", + "./skills/reviewing-oracle-to-postgres-migration/", + "./skills/scaffolding-oracle-to-postgres-migration-test-project/" + ] + } + } +} diff --git a/plugins/ospo-sponsorship/.github/plugin/plugin.json b/plugins/ospo-sponsorship/plugin.json similarity index 67% rename from plugins/ospo-sponsorship/.github/plugin/plugin.json rename to plugins/ospo-sponsorship/plugin.json index 4d4a1f2c..5dba685a 100644 --- a/plugins/ospo-sponsorship/.github/plugin/plugin.json +++ b/plugins/ospo-sponsorship/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "ospo-sponsorship", "description": "Tools and resources for Open Source Program Offices (OSPOs) to identify, evaluate, and manage sponsorship of open source dependencies through GitHub Sponsors, Open Collective, and other funding platforms.", "version": "1.0.0", @@ -7,7 +8,11 @@ }, "repository": "https://github.com/github/awesome-copilot", "license": "MIT", - "skills": [ - "./skills/sponsor-finder/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/sponsor-finder/" + ] + } + } } diff --git a/plugins/partners/.github/plugin/plugin.json b/plugins/partners/.github/plugin/plugin.json deleted file mode 100644 index 2725120b..00000000 --- a/plugins/partners/.github/plugin/plugin.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "partners", - "description": "Custom agents that have been created by GitHub partners", - "version": "1.0.0", - "author": { - "name": "Awesome Copilot Community" - }, - "repository": "https://github.com/github/awesome-copilot", - "license": "MIT", - "keywords": [ - "devops", - "security", - "database", - "cloud", - "infrastructure", - "observability", - "feature-flags", - "cicd", - "migration", - "performance" - ], - "agents": [ - "./agents/amplitude-experiment-implementation.md", - "./agents/apify-integration-expert.md", - "./agents/arm-migration.md", - "./agents/comet-opik.md", - "./agents/diffblue-cover.md", - "./agents/droid.md", - "./agents/dynatrace-expert.md", - "./agents/elasticsearch-observability.md", - "./agents/jfrog-sec.md", - "./agents/launchdarkly-flag-cleanup.md", - "./agents/lingodotdev-i18n.md", - "./agents/monday-bug-fixer.md", - "./agents/mongodb-performance-advisor.md", - "./agents/neo4j-docker-client-generator.md", - "./agents/neon-migration-specialist.md", - "./agents/neon-optimization-analyzer.md", - "./agents/octopus-deploy-release-notes-mcp.md", - "./agents/pagerduty-incident-responder.md", - "./agents/stackhawk-security-onboarding.md", - "./agents/terraform.md" - ] -} diff --git a/plugins/partners/plugin.json b/plugins/partners/plugin.json new file mode 100644 index 00000000..acc191d8 --- /dev/null +++ b/plugins/partners/plugin.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", + "name": "partners", + "description": "Custom agents that have been created by GitHub partners", + "version": "1.0.0", + "author": { + "name": "Awesome Copilot Community" + }, + "repository": "https://github.com/github/awesome-copilot", + "license": "MIT", + "keywords": [ + "devops", + "security", + "database", + "cloud", + "infrastructure", + "observability", + "feature-flags", + "cicd", + "migration", + "performance" + ], + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/amplitude-experiment-implementation.md", + "./agents/apify-integration-expert.md", + "./agents/arm-migration.md", + "./agents/comet-opik.md", + "./agents/diffblue-cover.md", + "./agents/droid.md", + "./agents/dynatrace-expert.md", + "./agents/elasticsearch-observability.md", + "./agents/jfrog-sec.md", + "./agents/launchdarkly-flag-cleanup.md", + "./agents/lingodotdev-i18n.md", + "./agents/monday-bug-fixer.md", + "./agents/mongodb-performance-advisor.md", + "./agents/neo4j-docker-client-generator.md", + "./agents/neon-migration-specialist.md", + "./agents/neon-optimization-analyzer.md", + "./agents/octopus-deploy-release-notes-mcp.md", + "./agents/pagerduty-incident-responder.md", + "./agents/stackhawk-security-onboarding.md", + "./agents/terraform.md" + ] + } + } +} diff --git a/plugins/pcf-development/.github/plugin/plugin.json b/plugins/pcf-development/plugin.json similarity index 85% rename from plugins/pcf-development/.github/plugin/plugin.json rename to plugins/pcf-development/plugin.json index a692982d..d6a02935 100644 --- a/plugins/pcf-development/.github/plugin/plugin.json +++ b/plugins/pcf-development/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "pcf-development", "description": "Complete toolkit for developing custom code components using Power Apps Component Framework for model-driven and canvas apps", "version": "1.0.0", diff --git a/plugins/phoenix/.github/plugin/plugin.json b/plugins/phoenix/plugin.json similarity index 66% rename from plugins/phoenix/.github/plugin/plugin.json rename to plugins/phoenix/plugin.json index 66908631..1a31d714 100644 --- a/plugins/phoenix/.github/plugin/plugin.json +++ b/plugins/phoenix/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "phoenix", "description": "Phoenix AI observability skills for LLM application debugging, evaluation, and tracing. Includes CLI debugging tools, LLM evaluation workflows, and OpenInference tracing instrumentation.", "version": "1.0.0", @@ -17,9 +18,13 @@ "openinference", "instrumentation" ], - "skills": [ - "./skills/phoenix-cli/", - "./skills/phoenix-evals/", - "./skills/phoenix-tracing/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/phoenix-cli/", + "./skills/phoenix-evals/", + "./skills/phoenix-tracing/" + ] + } + } } diff --git a/plugins/php-mcp-development/.github/plugin/plugin.json b/plugins/php-mcp-development/plugin.json similarity index 67% rename from plugins/php-mcp-development/.github/plugin/plugin.json rename to plugins/php-mcp-development/plugin.json index 07a94151..aa34284a 100644 --- a/plugins/php-mcp-development/.github/plugin/plugin.json +++ b/plugins/php-mcp-development/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "php-mcp-development", "description": "Comprehensive resources for building Model Context Protocol servers using the official PHP SDK with attribute-based discovery, including best practices, project generation, and expert assistance", "version": "1.0.0", @@ -16,10 +17,14 @@ "attributes", "composer" ], - "agents": [ - "./agents/php-mcp-expert.md" - ], - "skills": [ - "./skills/php-mcp-server-generator/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/php-mcp-expert.md" + ], + "skills": [ + "./skills/php-mcp-server-generator/" + ] + } + } } diff --git a/plugins/power-apps-code-apps/.github/plugin/plugin.json b/plugins/power-apps-code-apps/plugin.json similarity index 66% rename from plugins/power-apps-code-apps/.github/plugin/plugin.json rename to plugins/power-apps-code-apps/plugin.json index 4955de4f..0d928f56 100644 --- a/plugins/power-apps-code-apps/.github/plugin/plugin.json +++ b/plugins/power-apps-code-apps/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "power-apps-code-apps", "description": "Complete toolkit for Power Apps Code Apps development including project scaffolding, development standards, and expert guidance for building code-first applications with Power Platform integration.", "version": "1.0.0", @@ -16,10 +17,14 @@ "dataverse", "connectors" ], - "agents": [ - "./agents/power-platform-expert.md" - ], - "skills": [ - "./skills/power-apps-code-app-scaffold/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/power-platform-expert.md" + ], + "skills": [ + "./skills/power-apps-code-app-scaffold/" + ] + } + } } diff --git a/plugins/power-bi-development/.github/plugin/plugin.json b/plugins/power-bi-development/plugin.json similarity index 50% rename from plugins/power-bi-development/.github/plugin/plugin.json rename to plugins/power-bi-development/plugin.json index 38452b41..ac889da9 100644 --- a/plugins/power-bi-development/.github/plugin/plugin.json +++ b/plugins/power-bi-development/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "power-bi-development", "description": "Comprehensive Power BI development resources including data modeling, DAX optimization, performance tuning, visualization design, security best practices, and DevOps/ALM guidance for building enterprise-grade Power BI solutions.", "version": "1.0.0", @@ -17,16 +18,20 @@ "devops", "business-intelligence" ], - "agents": [ - "./agents/power-bi-data-modeling-expert.md", - "./agents/power-bi-dax-expert.md", - "./agents/power-bi-performance-expert.md", - "./agents/power-bi-visualization-expert.md" - ], - "skills": [ - "./skills/power-bi-dax-optimization/", - "./skills/power-bi-model-design-review/", - "./skills/power-bi-performance-troubleshooting/", - "./skills/power-bi-report-design-consultation/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/power-bi-data-modeling-expert.md", + "./agents/power-bi-dax-expert.md", + "./agents/power-bi-performance-expert.md", + "./agents/power-bi-visualization-expert.md" + ], + "skills": [ + "./skills/power-bi-dax-optimization/", + "./skills/power-bi-model-design-review/", + "./skills/power-bi-performance-troubleshooting/", + "./skills/power-bi-report-design-consultation/" + ] + } + } } diff --git a/plugins/power-platform-architect/.github/plugin/plugin.json b/plugins/power-platform-architect/plugin.json similarity index 71% rename from plugins/power-platform-architect/.github/plugin/plugin.json rename to plugins/power-platform-architect/plugin.json index 70ed613d..9e40bea7 100644 --- a/plugins/power-platform-architect/.github/plugin/plugin.json +++ b/plugins/power-platform-architect/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "power-platform-architect", "description": "Solution Architect for the Microsoft Power Platform, turning business requirements into functioning Power Platform solution architectures.", "version": "1.0.0", @@ -16,7 +17,11 @@ }, "repository": "https://github.com/github/awesome-copilot", "license": "MIT", - "skills": [ - "./skills/power-platform-architect/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/power-platform-architect/" + ] + } + } } diff --git a/plugins/power-platform-mcp-connector-development/.github/plugin/plugin.json b/plugins/power-platform-mcp-connector-development/plugin.json similarity index 57% rename from plugins/power-platform-mcp-connector-development/.github/plugin/plugin.json rename to plugins/power-platform-mcp-connector-development/plugin.json index da2bd084..eb323e75 100644 --- a/plugins/power-platform-mcp-connector-development/.github/plugin/plugin.json +++ b/plugins/power-platform-mcp-connector-development/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "power-platform-mcp-connector-development", "description": "Complete toolkit for developing Power Platform custom connectors with Model Context Protocol integration for Microsoft Copilot Studio", "version": "1.0.0", @@ -14,11 +15,15 @@ "custom-connector", "json-rpc" ], - "agents": [ - "./agents/power-platform-mcp-integration-expert.md" - ], - "skills": [ - "./skills/mcp-copilot-studio-server-generator/", - "./skills/power-platform-mcp-connector-suite/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/power-platform-mcp-integration-expert.md" + ], + "skills": [ + "./skills/mcp-copilot-studio-server-generator/", + "./skills/power-platform-mcp-connector-suite/" + ] + } + } } diff --git a/plugins/pr-artifact-explorer/README.md b/plugins/pr-artifact-explorer/README.md new file mode 100644 index 00000000..8cd0ce23 --- /dev/null +++ b/plugins/pr-artifact-explorer/README.md @@ -0,0 +1,17 @@ +# Pr Artifact Explorer Plugin + +Navigate pull requests and securely explore GitHub Actions artifacts, including test results, static sites, terminal recordings, and source files. + +## Installation + +``bash +copilot plugin install pr-artifact-explorer@awesome-copilot +`` + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## License + +MIT diff --git a/extensions/pr-artifact-explorer/.github/plugin/plugin.json b/plugins/pr-artifact-explorer/plugin.json similarity index 63% rename from extensions/pr-artifact-explorer/.github/plugin/plugin.json rename to plugins/pr-artifact-explorer/plugin.json index b744b774..2841734f 100644 --- a/extensions/pr-artifact-explorer/.github/plugin/plugin.json +++ b/plugins/pr-artifact-explorer/plugin.json @@ -15,6 +15,15 @@ "pull-requests", "test-results" ], - "logo": "assets/preview.png", - "extensions": "." + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/pr-artifact-explorer" + ] + } + }, + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json" } diff --git a/plugins/project-documenter/.github/plugin/plugin.json b/plugins/project-documenter/plugin.json similarity index 69% rename from plugins/project-documenter/.github/plugin/plugin.json rename to plugins/project-documenter/plugin.json index f1b48957..b1866c64 100644 --- a/plugins/project-documenter/.github/plugin/plugin.json +++ b/plugins/project-documenter/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "project-documenter", "description": "Generate professional project documentation with draw.io architecture diagrams and Word (.docx) output with embedded images. Automatically discovers any project's technology stack and produces Markdown, diagrams, PNG exports, and a formatted Word document.", "version": "1.0.0", @@ -18,11 +19,15 @@ "project-summary", "auto-discovery" ], - "agents": [ - "./agents/project-documenter.md" - ], - "skills": [ - "./skills/drawio/", - "./skills/md-to-docx/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/project-documenter.md" + ], + "skills": [ + "./skills/drawio/", + "./skills/md-to-docx/" + ] + } + } } diff --git a/plugins/project-planning/.github/plugin/plugin.json b/plugins/project-planning/.github/plugin/plugin.json deleted file mode 100644 index 566e3c1d..00000000 --- a/plugins/project-planning/.github/plugin/plugin.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "project-planning", - "description": "Tools and guidance for software project planning, feature breakdown, epic management, implementation planning, and task organization for development teams.", - "version": "1.0.0", - "author": { - "name": "Awesome Copilot Community" - }, - "repository": "https://github.com/github/awesome-copilot", - "license": "MIT", - "keywords": [ - "planning", - "project-management", - "epic", - "feature", - "implementation", - "task", - "architecture", - "technical-spike" - ], - "agents": [ - "./agents/implementation-plan.md", - "./agents/plan.md", - "./agents/planner.md", - "./agents/prd.md", - "./agents/research-technical-spike.md", - "./agents/task-planner.md", - "./agents/task-researcher.md" - ], - "skills": [ - "./skills/breakdown-epic-arch/", - "./skills/breakdown-epic-pm/", - "./skills/breakdown-feature-implementation/", - "./skills/breakdown-feature-prd/", - "./skills/create-github-issues-feature-from-implementation-plan/", - "./skills/create-implementation-plan/", - "./skills/create-technical-spike/", - "./skills/update-implementation-plan/" - ] -} diff --git a/plugins/project-planning/plugin.json b/plugins/project-planning/plugin.json new file mode 100644 index 00000000..480cc56f --- /dev/null +++ b/plugins/project-planning/plugin.json @@ -0,0 +1,44 @@ +{ + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", + "name": "project-planning", + "description": "Tools and guidance for software project planning, feature breakdown, epic management, implementation planning, and task organization for development teams.", + "version": "1.0.0", + "author": { + "name": "Awesome Copilot Community" + }, + "repository": "https://github.com/github/awesome-copilot", + "license": "MIT", + "keywords": [ + "planning", + "project-management", + "epic", + "feature", + "implementation", + "task", + "architecture", + "technical-spike" + ], + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/implementation-plan.md", + "./agents/plan.md", + "./agents/planner.md", + "./agents/prd.md", + "./agents/research-technical-spike.md", + "./agents/task-planner.md", + "./agents/task-researcher.md" + ], + "skills": [ + "./skills/breakdown-epic-arch/", + "./skills/breakdown-epic-pm/", + "./skills/breakdown-feature-implementation/", + "./skills/breakdown-feature-prd/", + "./skills/create-github-issues-feature-from-implementation-plan/", + "./skills/create-implementation-plan/", + "./skills/create-technical-spike/", + "./skills/update-implementation-plan/" + ] + } + } +} diff --git a/plugins/python-mcp-development/.github/plugin/plugin.json b/plugins/python-mcp-development/plugin.json similarity index 66% rename from plugins/python-mcp-development/.github/plugin/plugin.json rename to plugins/python-mcp-development/plugin.json index 7bea372f..a8b9a9d2 100644 --- a/plugins/python-mcp-development/.github/plugin/plugin.json +++ b/plugins/python-mcp-development/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "python-mcp-development", "description": "Complete toolkit for building Model Context Protocol (MCP) servers in Python using the official SDK with FastMCP. Includes instructions for best practices, a prompt for generating servers, and an expert chat mode for guidance.", "version": "1.0.0", @@ -14,10 +15,14 @@ "fastmcp", "server-development" ], - "agents": [ - "./agents/python-mcp-expert.md" - ], - "skills": [ - "./skills/python-mcp-server-generator/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/python-mcp-expert.md" + ], + "skills": [ + "./skills/python-mcp-server-generator/" + ] + } + } } diff --git a/plugins/react18-upgrade/.github/plugin/plugin.json b/plugins/react18-upgrade/.github/plugin/plugin.json deleted file mode 100644 index f123facb..00000000 --- a/plugins/react18-upgrade/.github/plugin/plugin.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "name": "react18-upgrade", - "description": "Enterprise React 18 migration toolkit with specialized agents and skills for upgrading React 16/17 class-component codebases to React 18.3.1. Includes auditor, dependency surgeon, class component migration specialist, automatic batching fixer, and test guardian.", - "version": "1.0.0", - "keywords": [ - "react18", - "react", - "migration", - "upgrade", - "class-components", - "lifecycle", - "batching" - ], - "author": { - "name": "Awesome Copilot Community" - }, - "repository": "https://github.com/github/awesome-copilot", - "license": "MIT", - "agents": [ - "./agents/react18-auditor.md", - "./agents/react18-batching-fixer.md", - "./agents/react18-class-surgeon.md", - "./agents/react18-commander.md", - "./agents/react18-dep-surgeon.md", - "./agents/react18-test-guardian.md" - ], - "skills": [ - "./skills/react-audit-grep-patterns/", - "./skills/react18-batching-patterns/", - "./skills/react18-dep-compatibility/", - "./skills/react18-enzyme-to-rtl/", - "./skills/react18-legacy-context/", - "./skills/react18-lifecycle-patterns/", - "./skills/react18-string-refs/" - ] -} diff --git a/plugins/react18-upgrade/plugin.json b/plugins/react18-upgrade/plugin.json new file mode 100644 index 00000000..306b3b9a --- /dev/null +++ b/plugins/react18-upgrade/plugin.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", + "name": "react18-upgrade", + "description": "Enterprise React 18 migration toolkit with specialized agents and skills for upgrading React 16/17 class-component codebases to React 18.3.1. Includes auditor, dependency surgeon, class component migration specialist, automatic batching fixer, and test guardian.", + "version": "1.0.0", + "keywords": [ + "react18", + "react", + "migration", + "upgrade", + "class-components", + "lifecycle", + "batching" + ], + "author": { + "name": "Awesome Copilot Community" + }, + "repository": "https://github.com/github/awesome-copilot", + "license": "MIT", + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/react18-auditor.md", + "./agents/react18-batching-fixer.md", + "./agents/react18-class-surgeon.md", + "./agents/react18-commander.md", + "./agents/react18-dep-surgeon.md", + "./agents/react18-test-guardian.md" + ], + "skills": [ + "./skills/react-audit-grep-patterns/", + "./skills/react18-batching-patterns/", + "./skills/react18-dep-compatibility/", + "./skills/react18-enzyme-to-rtl/", + "./skills/react18-legacy-context/", + "./skills/react18-lifecycle-patterns/", + "./skills/react18-string-refs/" + ] + } + } +} diff --git a/plugins/react19-upgrade/.github/plugin/plugin.json b/plugins/react19-upgrade/plugin.json similarity index 54% rename from plugins/react19-upgrade/.github/plugin/plugin.json rename to plugins/react19-upgrade/plugin.json index 8adbe97e..1312038c 100644 --- a/plugins/react19-upgrade/.github/plugin/plugin.json +++ b/plugins/react19-upgrade/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "react19-upgrade", "description": "Enterprise React 19 migration toolkit with specialized agents and skills for upgrading React 18 codebases to React 19. Includes auditor, dependency surgeon, source code migrator, and test guardian. Handles removal of deprecated APIs including ReactDOM.render, forwardRef, defaultProps, legacy context, string refs, and more.", "version": "1.0.0", @@ -15,16 +16,20 @@ }, "repository": "https://github.com/github/awesome-copilot", "license": "MIT", - "agents": [ - "./agents/react19-auditor.md", - "./agents/react19-commander.md", - "./agents/react19-dep-surgeon.md", - "./agents/react19-migrator.md", - "./agents/react19-test-guardian.md" - ], - "skills": [ - "./skills/react19-concurrent-patterns/", - "./skills/react19-source-patterns/", - "./skills/react19-test-patterns/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/react19-auditor.md", + "./agents/react19-commander.md", + "./agents/react19-dep-surgeon.md", + "./agents/react19-migrator.md", + "./agents/react19-test-guardian.md" + ], + "skills": [ + "./skills/react19-concurrent-patterns/", + "./skills/react19-source-patterns/", + "./skills/react19-test-patterns/" + ] + } + } } diff --git a/plugins/release-notes-showcase/README.md b/plugins/release-notes-showcase/README.md new file mode 100644 index 00000000..e587682f --- /dev/null +++ b/plugins/release-notes-showcase/README.md @@ -0,0 +1,17 @@ +# Release Notes Showcase Plugin + +Compose and refine launch-ready release notes with contributor callouts and export-friendly output. + +## Installation + +``bash +copilot plugin install release-notes-showcase@awesome-copilot +`` + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## License + +MIT diff --git a/extensions/release-notes-showcase/.github/plugin/plugin.json b/plugins/release-notes-showcase/plugin.json similarity index 60% rename from extensions/release-notes-showcase/.github/plugin/plugin.json rename to plugins/release-notes-showcase/plugin.json index aa8a7462..79b55e29 100644 --- a/extensions/release-notes-showcase/.github/plugin/plugin.json +++ b/plugins/release-notes-showcase/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "release-notes-showcase", "description": "Compose and refine launch-ready release notes with contributor callouts and export-friendly output.", "version": "1.0.2", @@ -14,6 +15,14 @@ "product-updates", "release-notes" ], - "logo": "assets/preview.png", - "extensions": "." + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/release-notes-showcase" + ] + } + } } diff --git a/plugins/repo-actions-hub/README.md b/plugins/repo-actions-hub/README.md new file mode 100644 index 00000000..ef4a4c26 --- /dev/null +++ b/plugins/repo-actions-hub/README.md @@ -0,0 +1,17 @@ +# Repo Actions Hub Plugin + +Browse repository GitHub Actions workflows, inspect recent runs, and trigger manual workflow_dispatch runs from a Copilot canvas. + +## Installation + +``bash +copilot plugin install repo-actions-hub@awesome-copilot +`` + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## License + +MIT diff --git a/extensions/repo-actions-hub/.github/plugin/plugin.json b/plugins/repo-actions-hub/plugin.json similarity index 61% rename from extensions/repo-actions-hub/.github/plugin/plugin.json rename to plugins/repo-actions-hub/plugin.json index f43e4af1..2ecb30c4 100644 --- a/extensions/repo-actions-hub/.github/plugin/plugin.json +++ b/plugins/repo-actions-hub/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "repo-actions-hub", "description": "Browse repository GitHub Actions workflows, inspect recent runs, and trigger manual workflow_dispatch runs from a Copilot canvas.", "version": "1.0.2", @@ -14,6 +15,14 @@ "recent-runs", "workflow-dispatch" ], - "logo": "assets/preview.png", - "extensions": "." + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/repo-actions-hub" + ] + } + } } diff --git a/plugins/roundup/.github/plugin/plugin.json b/plugins/roundup/plugin.json similarity index 70% rename from plugins/roundup/.github/plugin/plugin.json rename to plugins/roundup/plugin.json index 010bd4c0..76828c93 100644 --- a/plugins/roundup/.github/plugin/plugin.json +++ b/plugins/roundup/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "roundup", "description": "Self-configuring status briefing generator. Learns your communication style from examples, discovers your data sources, and produces draft updates for any audience on demand.", "version": "1.0.0", @@ -17,8 +18,12 @@ "roundup", "copilot-cli" ], - "skills": [ - "./skills/roundup-setup/", - "./skills/roundup/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/roundup-setup/", + "./skills/roundup/" + ] + } + } } diff --git a/plugins/ruby-mcp-development/.github/plugin/plugin.json b/plugins/ruby-mcp-development/plugin.json similarity index 64% rename from plugins/ruby-mcp-development/.github/plugin/plugin.json rename to plugins/ruby-mcp-development/plugin.json index b5683ef6..5a75032f 100644 --- a/plugins/ruby-mcp-development/.github/plugin/plugin.json +++ b/plugins/ruby-mcp-development/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "ruby-mcp-development", "description": "Complete toolkit for building Model Context Protocol servers in Ruby using the official MCP Ruby SDK gem with Rails integration support.", "version": "1.0.0", @@ -16,10 +17,14 @@ "rails", "gem" ], - "agents": [ - "./agents/ruby-mcp-expert.md" - ], - "skills": [ - "./skills/ruby-mcp-server-generator/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/ruby-mcp-expert.md" + ], + "skills": [ + "./skills/ruby-mcp-server-generator/" + ] + } + } } diff --git a/plugins/rug-agentic-workflow/.github/plugin/plugin.json b/plugins/rug-agentic-workflow/plugin.json similarity index 62% rename from plugins/rug-agentic-workflow/.github/plugin/plugin.json rename to plugins/rug-agentic-workflow/plugin.json index c826c446..07a827ad 100644 --- a/plugins/rug-agentic-workflow/.github/plugin/plugin.json +++ b/plugins/rug-agentic-workflow/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "rug-agentic-workflow", "description": "Three-agent workflow for orchestrated software delivery with an orchestrator plus implementation and QA subagents.", "version": "1.0.0", @@ -14,9 +15,13 @@ "software-engineering", "qa" ], - "agents": [ - "./agents/qa-subagent.md", - "./agents/rug-orchestrator.md", - "./agents/swe-subagent.md" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/qa-subagent.md", + "./agents/rug-orchestrator.md", + "./agents/swe-subagent.md" + ] + } + } } diff --git a/plugins/rust-mcp-development/.github/plugin/plugin.json b/plugins/rust-mcp-development/plugin.json similarity index 66% rename from plugins/rust-mcp-development/.github/plugin/plugin.json rename to plugins/rust-mcp-development/plugin.json index 5b05a765..ba36d26b 100644 --- a/plugins/rust-mcp-development/.github/plugin/plugin.json +++ b/plugins/rust-mcp-development/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "rust-mcp-development", "description": "Build high-performance Model Context Protocol servers in Rust using the official rmcp SDK with async/await, procedural macros, and type-safe implementations.", "version": "1.0.0", @@ -18,10 +19,14 @@ "macros", "rmcp" ], - "agents": [ - "./agents/rust-mcp-expert.md" - ], - "skills": [ - "./skills/rust-mcp-server-generator/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/rust-mcp-expert.md" + ], + "skills": [ + "./skills/rust-mcp-server-generator/" + ] + } + } } diff --git a/plugins/salesforce-development/.github/plugin/plugin.json b/plugins/salesforce-development/plugin.json similarity index 50% rename from plugins/salesforce-development/.github/plugin/plugin.json rename to plugins/salesforce-development/plugin.json index 6ba38514..760cfc69 100644 --- a/plugins/salesforce-development/.github/plugin/plugin.json +++ b/plugins/salesforce-development/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "salesforce-development", "description": "Complete Salesforce agentic development environment covering Apex & Triggers, Flow automation, Lightning Web Components, Aura components, and Visualforce pages.", "version": "1.1.0", @@ -18,15 +19,19 @@ "crm", "salesforce-dx" ], - "agents": [ - "./agents/salesforce-apex-triggers.md", - "./agents/salesforce-aura-lwc.md", - "./agents/salesforce-flow.md", - "./agents/salesforce-visualforce.md" - ], - "skills": [ - "./skills/salesforce-apex-quality/", - "./skills/salesforce-component-standards/", - "./skills/salesforce-flow-design/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/salesforce-apex-triggers.md", + "./agents/salesforce-aura-lwc.md", + "./agents/salesforce-flow.md", + "./agents/salesforce-visualforce.md" + ], + "skills": [ + "./skills/salesforce-apex-quality/", + "./skills/salesforce-component-standards/", + "./skills/salesforce-flow-design/" + ] + } + } } diff --git a/plugins/security-best-practices/.github/plugin/plugin.json b/plugins/security-best-practices/plugin.json similarity index 71% rename from plugins/security-best-practices/.github/plugin/plugin.json rename to plugins/security-best-practices/plugin.json index d2930b7e..bb39305c 100644 --- a/plugins/security-best-practices/.github/plugin/plugin.json +++ b/plugins/security-best-practices/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "security-best-practices", "description": "Security frameworks, accessibility guidelines, performance optimization, and code quality best practices for building secure, maintainable, and high-performance applications.", "version": "1.0.0", @@ -17,7 +18,11 @@ "optimization", "best-practices" ], - "skills": [ - "./skills/ai-prompt-engineering-safety-review/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/ai-prompt-engineering-safety-review/" + ] + } + } } diff --git a/plugins/signals-dashboard/README.md b/plugins/signals-dashboard/README.md new file mode 100644 index 00000000..96aed60c --- /dev/null +++ b/plugins/signals-dashboard/README.md @@ -0,0 +1,17 @@ +# Signals Dashboard Plugin + +Real-time Workshop dashboard with agent signals, honesty calibration, and cost-aware repo or connected desk launch profiles. + +## Installation + +``bash +copilot plugin install signals-dashboard@awesome-copilot +`` + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## License + +MIT diff --git a/extensions/signals-dashboard/.github/plugin/plugin.json b/plugins/signals-dashboard/plugin.json similarity index 58% rename from extensions/signals-dashboard/.github/plugin/plugin.json rename to plugins/signals-dashboard/plugin.json index 7e4e6cd4..65db37c0 100644 --- a/extensions/signals-dashboard/.github/plugin/plugin.json +++ b/plugins/signals-dashboard/plugin.json @@ -13,6 +13,15 @@ "coordination", "canvas" ], - "logo": "assets/preview.png", - "extensions": "." + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/signals-dashboard" + ] + } + }, + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json" } diff --git a/plugins/site-studio/README.md b/plugins/site-studio/README.md new file mode 100644 index 00000000..69daad2f --- /dev/null +++ b/plugins/site-studio/README.md @@ -0,0 +1,17 @@ +# Site Studio Plugin + +Plan, draft, and track a personal website section by section — a shared canvas where you and your agent author content, watch progress, and review every change. + +## Installation + +``bash +copilot plugin install site-studio@awesome-copilot +`` + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## License + +MIT diff --git a/extensions/site-studio/.github/plugin/plugin.json b/plugins/site-studio/plugin.json similarity index 63% rename from extensions/site-studio/.github/plugin/plugin.json rename to plugins/site-studio/plugin.json index 2cc5f51d..f87f126d 100644 --- a/extensions/site-studio/.github/plugin/plugin.json +++ b/plugins/site-studio/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "site-studio", "description": "Plan, draft, and track a personal website section by section — a shared canvas where you and your agent author content, watch progress, and review every change.", "version": "1.0.2", @@ -14,6 +15,14 @@ "section-planning", "site-builder" ], - "logo": "assets/preview.png", - "extensions": "." + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/site-studio" + ] + } + } } diff --git a/plugins/skill-image-gen/.github/plugin/plugin.json b/plugins/skill-image-gen/plugin.json similarity index 75% rename from plugins/skill-image-gen/.github/plugin/plugin.json rename to plugins/skill-image-gen/plugin.json index 7e1e2a1e..1127ce0a 100644 --- a/plugins/skill-image-gen/.github/plugin/plugin.json +++ b/plugins/skill-image-gen/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "skill-image-gen", "description": "Generate images using AI directly from your coding workflow. Supports OpenAI (gpt-image-2) and Google Gemini. BYO API key — the skill guides you through setup on first use.", "version": "1.0.0", @@ -19,7 +20,11 @@ "homepage": "https://github.com/adamd9/skill-image-gen", "repository": "https://github.com/github/awesome-copilot", "license": "MIT", - "skills": [ - "./skills/generate-image/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/generate-image/" + ] + } + } } diff --git a/plugins/software-engineering-team/.github/plugin/plugin.json b/plugins/software-engineering-team/plugin.json similarity index 50% rename from plugins/software-engineering-team/.github/plugin/plugin.json rename to plugins/software-engineering-team/plugin.json index b680ade8..34e55361 100644 --- a/plugins/software-engineering-team/.github/plugin/plugin.json +++ b/plugins/software-engineering-team/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "software-engineering-team", "description": "7 specialized agents covering the full software development lifecycle from UX design and architecture to security and DevOps.", "version": "1.0.0", @@ -17,13 +18,17 @@ "product", "ai-ethics" ], - "agents": [ - "./agents/se-gitops-ci-specialist.md", - "./agents/se-product-manager-advisor.md", - "./agents/se-responsible-ai-code.md", - "./agents/se-security-reviewer.md", - "./agents/se-system-architecture-reviewer.md", - "./agents/se-technical-writer.md", - "./agents/se-ux-ui-designer.md" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/se-gitops-ci-specialist.md", + "./agents/se-product-manager-advisor.md", + "./agents/se-responsible-ai-code.md", + "./agents/se-security-reviewer.md", + "./agents/se-system-architecture-reviewer.md", + "./agents/se-technical-writer.md", + "./agents/se-ux-ui-designer.md" + ] + } + } } diff --git a/plugins/structured-autonomy/.github/plugin/plugin.json b/plugins/structured-autonomy/.github/plugin/plugin.json deleted file mode 100644 index 4428d574..00000000 --- a/plugins/structured-autonomy/.github/plugin/plugin.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "structured-autonomy", - "description": "Premium planning, thrifty implementation", - "version": "1.0.0", - "author": { - "name": "Awesome Copilot Community" - }, - "repository": "https://github.com/github/awesome-copilot", - "license": "MIT", - "skills": [ - "./skills/structured-autonomy-generate/", - "./skills/structured-autonomy-implement/", - "./skills/structured-autonomy-plan/" - ] -} diff --git a/plugins/structured-autonomy/plugin.json b/plugins/structured-autonomy/plugin.json new file mode 100644 index 00000000..f9d65224 --- /dev/null +++ b/plugins/structured-autonomy/plugin.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", + "name": "structured-autonomy", + "description": "Premium planning, thrifty implementation", + "version": "1.0.0", + "author": { + "name": "Awesome Copilot Community" + }, + "repository": "https://github.com/github/awesome-copilot", + "license": "MIT", + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/structured-autonomy-generate/", + "./skills/structured-autonomy-implement/", + "./skills/structured-autonomy-plan/" + ] + } + } +} diff --git a/plugins/swift-mcp-development/.github/plugin/plugin.json b/plugins/swift-mcp-development/plugin.json similarity index 66% rename from plugins/swift-mcp-development/.github/plugin/plugin.json rename to plugins/swift-mcp-development/plugin.json index e75803d2..c3beb87e 100644 --- a/plugins/swift-mcp-development/.github/plugin/plugin.json +++ b/plugins/swift-mcp-development/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "swift-mcp-development", "description": "Comprehensive collection for building Model Context Protocol servers in Swift using the official MCP Swift SDK with modern concurrency features.", "version": "1.0.0", @@ -19,10 +20,14 @@ "actor", "async-await" ], - "agents": [ - "./agents/swift-mcp-expert.md" - ], - "skills": [ - "./skills/swift-mcp-server-generator/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/swift-mcp-expert.md" + ], + "skills": [ + "./skills/swift-mcp-server-generator/" + ] + } + } } diff --git a/plugins/technical-spike/.github/plugin/plugin.json b/plugins/technical-spike/plugin.json similarity index 63% rename from plugins/technical-spike/.github/plugin/plugin.json rename to plugins/technical-spike/plugin.json index e706e8da..8a9a57cb 100644 --- a/plugins/technical-spike/.github/plugin/plugin.json +++ b/plugins/technical-spike/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "technical-spike", "description": "Tools for creation, management and research of technical spikes to reduce unknowns and assumptions before proceeding to specification and implementation of solutions.", "version": "1.0.0", @@ -13,10 +14,14 @@ "validation", "research" ], - "agents": [ - "./agents/research-technical-spike.md" - ], - "skills": [ - "./skills/create-technical-spike/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/research-technical-spike.md" + ], + "skills": [ + "./skills/create-technical-spike/" + ] + } + } } diff --git a/plugins/testing-automation/.github/plugin/plugin.json b/plugins/testing-automation/.github/plugin/plugin.json deleted file mode 100644 index d25da6e1..00000000 --- a/plugins/testing-automation/.github/plugin/plugin.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "testing-automation", - "description": "Comprehensive collection for writing tests, test automation, and test-driven development including unit tests, integration tests, and end-to-end testing strategies.", - "version": "1.0.0", - "author": { - "name": "Awesome Copilot Community" - }, - "repository": "https://github.com/github/awesome-copilot", - "license": "MIT", - "keywords": [ - "testing", - "tdd", - "automation", - "unit-tests", - "integration", - "playwright", - "jest", - "nunit" - ], - "agents": [ - "./agents/playwright-tester.md", - "./agents/tdd-green.md", - "./agents/tdd-red.md", - "./agents/tdd-refactor.md" - ], - "skills": [ - "./skills/ai-prompt-engineering-safety-review/", - "./skills/csharp-nunit/", - "./skills/java-junit/", - "./skills/playwright-explore-website/", - "./skills/playwright-generate-test/" - ] -} diff --git a/plugins/testing-automation/plugin.json b/plugins/testing-automation/plugin.json new file mode 100644 index 00000000..153f05aa --- /dev/null +++ b/plugins/testing-automation/plugin.json @@ -0,0 +1,38 @@ +{ + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", + "name": "testing-automation", + "description": "Comprehensive collection for writing tests, test automation, and test-driven development including unit tests, integration tests, and end-to-end testing strategies.", + "version": "1.0.0", + "author": { + "name": "Awesome Copilot Community" + }, + "repository": "https://github.com/github/awesome-copilot", + "license": "MIT", + "keywords": [ + "testing", + "tdd", + "automation", + "unit-tests", + "integration", + "playwright", + "jest", + "nunit" + ], + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/playwright-tester.md", + "./agents/tdd-green.md", + "./agents/tdd-red.md", + "./agents/tdd-refactor.md" + ], + "skills": [ + "./skills/ai-prompt-engineering-safety-review/", + "./skills/csharp-nunit/", + "./skills/java-junit/", + "./skills/playwright-explore-website/", + "./skills/playwright-generate-test/" + ] + } + } +} diff --git a/plugins/the-workshop/.github/plugin/extensions.json b/plugins/the-workshop/.github/plugin/extensions.json new file mode 100644 index 00000000..fc01a6e0 --- /dev/null +++ b/plugins/the-workshop/.github/plugin/extensions.json @@ -0,0 +1,3 @@ +[ + "signals-dashboard" +] diff --git a/plugins/the-workshop/.github/plugin/plugin.json b/plugins/the-workshop/plugin.json similarity index 56% rename from plugins/the-workshop/.github/plugin/plugin.json rename to plugins/the-workshop/plugin.json index fbe149f0..5008b667 100644 --- a/plugins/the-workshop/.github/plugin/plugin.json +++ b/plugins/the-workshop/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "the-workshop", "description": "Stop being the switchboard between your AI agents — direct a team. The Workshop puts long-running AI agents (desks) in the same room, on the same work, each with its own memory and history, sharing one workspace so you direct the work instead of relaying it.", "version": "0.1.0", @@ -15,19 +16,21 @@ "agent-signals", "developer-experience" ], - "agents": [ - "./agents/workshop-ta.md" - ], - "skills": [ - "./skills/bench-read/", - "./skills/desk-journal/", - "./skills/desk-open/", - "./skills/signal-write/", - "./skills/workshop-create/" - ], - "x-awesome-copilot": { - "extensions": [ - "./extensions/signals-dashboard/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/workshop-ta.md" + ], + "skills": [ + "./skills/bench-read/", + "./skills/desk-journal/", + "./skills/desk-open/", + "./skills/signal-write/", + "./skills/workshop-create/" + ], + "extensions": [ + "./extensions/signals-dashboard" + ] + } } } diff --git a/plugins/tiny-tool-town-submitter/README.md b/plugins/tiny-tool-town-submitter/README.md new file mode 100644 index 00000000..a809cceb --- /dev/null +++ b/plugins/tiny-tool-town-submitter/README.md @@ -0,0 +1,17 @@ +# Tiny Tool Town Submitter Plugin + +Inspect a repository, improve Tiny Tool Town readiness, submit its listing issue, and launch remediation work. + +## Installation + +``bash +copilot plugin install tiny-tool-town-submitter@awesome-copilot +`` + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## License + +MIT diff --git a/extensions/tiny-tool-town-submitter/.github/plugin/plugin.json b/plugins/tiny-tool-town-submitter/plugin.json similarity index 61% rename from extensions/tiny-tool-town-submitter/.github/plugin/plugin.json rename to plugins/tiny-tool-town-submitter/plugin.json index 53edf975..4b9964d8 100644 --- a/extensions/tiny-tool-town-submitter/.github/plugin/plugin.json +++ b/plugins/tiny-tool-town-submitter/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "tiny-tool-town-submitter", "description": "Inspect a repository, improve Tiny Tool Town readiness, submit its listing issue, and launch remediation work.", "version": "1.0.2", @@ -14,6 +15,14 @@ "submission-workflow", "tiny-tool-town" ], - "logo": "assets/preview.png", - "extensions": "." + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/tiny-tool-town-submitter" + ] + } + } } diff --git a/plugins/token-pacman/README.md b/plugins/token-pacman/README.md new file mode 100644 index 00000000..150d43e7 --- /dev/null +++ b/plugins/token-pacman/README.md @@ -0,0 +1,17 @@ +# Token Pacman Plugin + +Visualizes live session AI-credit usage as a Pac-Man board with pellets, ghosts, fruit milestones, and game-over limits. + +## Installation + +``bash +copilot plugin install token-pacman@awesome-copilot +`` + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## License + +MIT diff --git a/extensions/token-pacman/.github/plugin/plugin.json b/plugins/token-pacman/plugin.json similarity index 61% rename from extensions/token-pacman/.github/plugin/plugin.json rename to plugins/token-pacman/plugin.json index b63359a8..4df2a5a6 100644 --- a/extensions/token-pacman/.github/plugin/plugin.json +++ b/plugins/token-pacman/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "token-pacman", "description": "Visualizes live session AI-credit usage as a Pac-Man board with pellets, ghosts, fruit milestones, and game-over limits.", "version": "1.0.2", @@ -14,6 +15,14 @@ "quota-tracking", "session-usage" ], - "logo": "assets/preview.png", - "extensions": "." + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/token-pacman" + ] + } + } } diff --git a/plugins/typescript-mcp-development/.github/plugin/plugin.json b/plugins/typescript-mcp-development/plugin.json similarity index 66% rename from plugins/typescript-mcp-development/.github/plugin/plugin.json rename to plugins/typescript-mcp-development/plugin.json index c5c5a523..5711205e 100644 --- a/plugins/typescript-mcp-development/.github/plugin/plugin.json +++ b/plugins/typescript-mcp-development/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "typescript-mcp-development", "description": "Complete toolkit for building Model Context Protocol (MCP) servers in TypeScript/Node.js using the official SDK. Includes instructions for best practices, a prompt for generating servers, and an expert chat mode for guidance.", "version": "1.0.0", @@ -14,10 +15,14 @@ "nodejs", "server-development" ], - "agents": [ - "./agents/typescript-mcp-expert.md" - ], - "skills": [ - "./skills/typescript-mcp-server-generator/" - ] + "extensions": { + "com.github.awesome-copilot": { + "agents": [ + "./agents/typescript-mcp-expert.md" + ], + "skills": [ + "./skills/typescript-mcp-server-generator/" + ] + } + } } diff --git a/plugins/typespec-m365-copilot/.github/plugin/plugin.json b/plugins/typespec-m365-copilot/plugin.json similarity index 64% rename from plugins/typespec-m365-copilot/.github/plugin/plugin.json rename to plugins/typespec-m365-copilot/plugin.json index 670511a3..f1200b08 100644 --- a/plugins/typespec-m365-copilot/.github/plugin/plugin.json +++ b/plugins/typespec-m365-copilot/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "typespec-m365-copilot", "description": "Comprehensive collection of prompts, instructions, and resources for building declarative agents and API plugins using TypeSpec for Microsoft 365 Copilot extensibility.", "version": "1.0.0", @@ -15,9 +16,13 @@ "agent-development", "microsoft-365" ], - "skills": [ - "./skills/typespec-api-operations/", - "./skills/typespec-create-agent/", - "./skills/typespec-create-api-plugin/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/typespec-api-operations/", + "./skills/typespec-create-agent/", + "./skills/typespec-create-api-plugin/" + ] + } + } } diff --git a/plugins/uizze/.github/plugin/plugin.json b/plugins/uizze/plugin.json similarity index 73% rename from plugins/uizze/.github/plugin/plugin.json rename to plugins/uizze/plugin.json index cd5ea735..fc30b55c 100644 --- a/plugins/uizze/.github/plugin/plugin.json +++ b/plugins/uizze/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "uizze", "description": "Stop generic UI from shipping. Ground GitHub Copilot in 800,000+ real web and iOS screens, write a product-specific design contract, and enforce a hard finish gate.", "version": "1.0.0", @@ -18,7 +19,11 @@ "design-review", "quality-gate" ], - "skills": [ - "./skills/anti-ui-slop/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/anti-ui-slop/" + ] + } + } } diff --git a/plugins/visual-pr/.github/plugin/plugin.json b/plugins/visual-pr/plugin.json similarity index 66% rename from plugins/visual-pr/.github/plugin/plugin.json rename to plugins/visual-pr/plugin.json index bf2fc561..32b1c8a2 100644 --- a/plugins/visual-pr/.github/plugin/plugin.json +++ b/plugins/visual-pr/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "visual-pr", "description": "Capture, annotate, and embed screenshots and animated GIF demos in pull request descriptions. Includes Playwright-based UI capture, PIL image annotations, PR embedding workflows for GitHub and Azure DevOps, and screen recording with variable timing.", "version": "1.0.0", @@ -17,10 +18,14 @@ }, "repository": "https://github.com/github/awesome-copilot", "license": "MIT", - "skills": [ - "./skills/image-annotations/", - "./skills/pr-screenshots/", - "./skills/screen-recording/", - "./skills/ui-screenshots/" - ] + "extensions": { + "com.github.awesome-copilot": { + "skills": [ + "./skills/image-annotations/", + "./skills/pr-screenshots/", + "./skills/screen-recording/", + "./skills/ui-screenshots/" + ] + } + } } diff --git a/plugins/where-was-i/README.md b/plugins/where-was-i/README.md new file mode 100644 index 00000000..8d333ec6 --- /dev/null +++ b/plugins/where-was-i/README.md @@ -0,0 +1,17 @@ +# Where Was I Plugin + +Reconstruct your dev context (branch, commits, uncommitted work, PR clues) and trigger a resume prompt to continue quickly. + +## Installation + +``bash +copilot plugin install where-was-i@awesome-copilot +`` + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## License + +MIT diff --git a/extensions/where-was-i/.github/plugin/plugin.json b/plugins/where-was-i/plugin.json similarity index 61% rename from extensions/where-was-i/.github/plugin/plugin.json rename to plugins/where-was-i/plugin.json index 7ef8a679..9685392c 100644 --- a/extensions/where-was-i/.github/plugin/plugin.json +++ b/plugins/where-was-i/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "where-was-i", "description": "Reconstruct your dev context (branch, commits, uncommitted work, PR clues) and trigger a resume prompt to continue quickly.", "version": "1.0.2", @@ -14,6 +15,14 @@ "pull-request-context", "resume-work" ], - "logo": "assets/preview.png", - "extensions": "." + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/where-was-i" + ] + } + } } diff --git a/plugins/work-hub/README.md b/plugins/work-hub/README.md new file mode 100644 index 00000000..71d79481 --- /dev/null +++ b/plugins/work-hub/README.md @@ -0,0 +1,17 @@ +# Work Hub Plugin + +Generic cross-repo command center canvas for GitHub Copilot with onboarding, focus planning, repo health, work signals, and session cleanup. + +## Installation + +``bash +copilot plugin install work-hub@awesome-copilot +`` + +## Source + +This plugin is part of [Awesome Copilot](https://github.com/github/awesome-copilot). + +## License + +MIT diff --git a/extensions/work-hub/.github/plugin/plugin.json b/plugins/work-hub/plugin.json similarity index 63% rename from extensions/work-hub/.github/plugin/plugin.json rename to plugins/work-hub/plugin.json index 8f88dd01..5667cda9 100644 --- a/extensions/work-hub/.github/plugin/plugin.json +++ b/plugins/work-hub/plugin.json @@ -1,4 +1,5 @@ { + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "work-hub", "description": "Generic cross-repo command center canvas for GitHub Copilot with onboarding, focus planning, repo health, work signals, and session cleanup.", "version": "1.0.2", @@ -14,6 +15,14 @@ "work-triage", "workflow-visibility" ], - "logo": "assets/preview.png", - "extensions": "." + "extensions": { + "com.github.copilot": { + "logo": "assets/preview.png" + }, + "com.github.awesome-copilot": { + "extensions": [ + "./extensions/work-hub" + ] + } + } }