Implement core Collections feature with YAML parsing and README generation

Co-authored-by: aaronpowell <434140+aaronpowell@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2025-09-09 01:31:17 +00:00
parent c58ae5031e
commit 406b613cf8
8 changed files with 438 additions and 2 deletions

View File

@ -0,0 +1,84 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Collection Manifest",
"description": "Schema for awesome-copilot collection manifest files",
"type": "object",
"required": ["id", "name", "description", "items"],
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the collection",
"pattern": "^[a-z0-9-]+$",
"minLength": 1,
"maxLength": 50
},
"name": {
"type": "string",
"description": "Display name for the collection",
"minLength": 1,
"maxLength": 100
},
"description": {
"type": "string",
"description": "Description of what this collection contains",
"minLength": 1,
"maxLength": 500
},
"tags": {
"type": "array",
"description": "Optional tags for discovery",
"items": {
"type": "string",
"pattern": "^[a-z0-9-]+$",
"minLength": 1,
"maxLength": 30
},
"uniqueItems": true,
"maxItems": 10
},
"items": {
"type": "array",
"description": "List of items in this collection",
"minItems": 1,
"maxItems": 50,
"items": {
"type": "object",
"required": ["path", "kind"],
"additionalProperties": false,
"properties": {
"path": {
"type": "string",
"description": "Relative path from repository root to the item file",
"pattern": "^(prompts|instructions|chatmodes)\/[^\/]+\\.(prompt|instructions|chatmode)\\.md$",
"minLength": 1
},
"kind": {
"type": "string",
"description": "Type of the item",
"enum": ["prompt", "instruction", "chat-mode"]
}
}
},
"uniqueItems": true
},
"display": {
"type": "object",
"description": "Optional display settings for the collection",
"additionalProperties": false,
"properties": {
"ordering": {
"type": "string",
"description": "How to order items in the collection",
"enum": ["manual", "alpha"],
"default": "alpha"
},
"show_badge": {
"type": "boolean",
"description": "Whether to show collection badge on items",
"default": false
}
}
}
}
}

19
README.collections.md Normal file
View File

@ -0,0 +1,19 @@
# 📦 Collections
Curated collections of related prompts, instructions, and chat modes organized around specific themes, workflows, or use cases.
### How to Use Collections
**Browse Collections:**
- Explore themed collections that group related customizations
- Each collection includes prompts, instructions, and chat modes for specific workflows
- Collections make it easy to adopt comprehensive toolkits for particular scenarios
**Install Items:**
- Click install buttons for individual items within collections
- Or browse to the individual files to copy content manually
- Collections help you discover related customizations you might have missed
| Name | Description | Items | Tags |
| ---- | ----------- | ----- | ---- |
| [C# .NET Development](collections/csharp-dotnet-development.md) | Essential prompts, instructions, and chat modes for C# and .NET development including testing, documentation, and best practices. | 7 items | csharp, dotnet, aspnet, testing |
| [DevOps On-Call](collections/devops-oncall.md) | A focused set of prompts, instructions, and a chat mode to help triage incidents and respond quickly with DevOps tools and Azure resources. | 5 items | devops, incident-response, oncall, azure |

View File

@ -14,6 +14,7 @@ This repository provides a comprehensive toolkit for enhancing GitHub Copilot wi
- **[![Awesome Prompts](https://img.shields.io/badge/Awesome-Prompts-blue?logo=githubcopilot)](README.prompts.md)** - Focused, task-specific prompts for generating code, documentation, and solving specific problems - **[![Awesome Prompts](https://img.shields.io/badge/Awesome-Prompts-blue?logo=githubcopilot)](README.prompts.md)** - Focused, task-specific prompts for generating code, documentation, and solving specific problems
- **[![Awesome Instructions](https://img.shields.io/badge/Awesome-Instructions-blue?logo=githubcopilot)](README.instructions.md)** - Comprehensive coding standards and best practices that apply to specific file patterns or entire projects - **[![Awesome Instructions](https://img.shields.io/badge/Awesome-Instructions-blue?logo=githubcopilot)](README.instructions.md)** - Comprehensive coding standards and best practices that apply to specific file patterns or entire projects
- **[![Awesome Chat Modes](https://img.shields.io/badge/Awesome-Chat_Modes-blue?logo=githubcopilot)](README.chatmodes.md)** - Specialized AI personas and conversation modes for different roles and contexts - **[![Awesome Chat Modes](https://img.shields.io/badge/Awesome-Chat_Modes-blue?logo=githubcopilot)](README.chatmodes.md)** - Specialized AI personas and conversation modes for different roles and contexts
- **[![Awesome Collections](https://img.shields.io/badge/Awesome-Collections-blue?logo=githubcopilot)](README.collections.md)** - Curated collections of related prompts, instructions, and chat modes organized around specific themes and workflows
## MCP Server ## MCP Server
@ -76,12 +77,13 @@ We welcome contributions! Please see our [Contributing Guidelines](CONTRIBUTING.
├── prompts/ # Task-specific prompts (.prompt.md) ├── prompts/ # Task-specific prompts (.prompt.md)
├── instructions/ # Coding standards and best practices (.instructions.md) ├── instructions/ # Coding standards and best practices (.instructions.md)
├── chatmodes/ # AI personas and specialized modes (.chatmode.md) ├── chatmodes/ # AI personas and specialized modes (.chatmode.md)
├── collections/ # Curated collections of related items (.collection.yml)
└── scripts/ # Utility scripts for maintenance └── scripts/ # Utility scripts for maintenance
``` ```
## 🌟 Getting Started ## 🌟 Getting Started
1. **Browse the Collections**: Check out our comprehensive lists of [prompts](README.prompts.md), [instructions](README.instructions.md), and [chat modes](README.chatmodes.md). 1. **Browse the Collections**: Check out our comprehensive lists of [collections](README.collections.md), [prompts](README.prompts.md), [instructions](README.instructions.md), and [chat modes](README.chatmodes.md).
2. **Add to your editor**: Click the "Install" button to install to VS Code, or copy the file contents for other editors. 2. **Add to your editor**: Click the "Install" button to install to VS Code, or copy the file contents for other editors.
3. **Start Using**: Copy prompts to use with `/` commands, let instructions enhance your coding experience, or activate chat modes for specialized assistance. 3. **Start Using**: Copy prompts to use with `/` commands, let instructions enhance your coding experience, or activate chat modes for specialized assistance.

View File

@ -0,0 +1,22 @@
id: csharp-dotnet-development
name: C# .NET Development
description: Essential prompts, instructions, and chat modes for C# and .NET development including testing, documentation, and best practices.
tags: [csharp, dotnet, aspnet, testing]
items:
- path: prompts/csharp-async.prompt.md
kind: prompt
- path: prompts/aspnet-minimal-api-openapi.prompt.md
kind: prompt
- path: instructions/csharp.instructions.md
kind: instruction
- path: instructions/dotnet-architecture-good-practices.instructions.md
kind: instruction
- path: chatmodes/expert-dotnet-software-engineer.chatmode.md
kind: chat-mode
- path: prompts/csharp-xunit.prompt.md
kind: prompt
- path: prompts/dotnet-best-practices.prompt.md
kind: prompt
display:
ordering: alpha
show_badge: false

View File

@ -0,0 +1,17 @@
# C# .NET Development
Essential prompts, instructions, and chat modes for C# and .NET development including testing, documentation, and best practices.
**Tags:** csharp, dotnet, aspnet, testing
## Items in this Collection
| Title | Type | Description |
| ----- | ---- | ----------- |
| [.NET/C# Best Practices](../prompts/dotnet-best-practices.prompt.md)<br />[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/prompt?url=vscode%3Achat-prompt%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fprompts%2Fdotnet-best-practices.prompt.md)<br />[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/prompt?url=vscode-insiders%3Achat-prompt%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fprompts%2Fdotnet-best-practices.prompt.md) | Prompt | Ensure .NET/C# code meets best practices for the solution/project. |
| [ASP.NET Minimal API with OpenAPI](../prompts/aspnet-minimal-api-openapi.prompt.md)<br />[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/prompt?url=vscode%3Achat-prompt%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fprompts%2Faspnet-minimal-api-openapi.prompt.md)<br />[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/prompt?url=vscode-insiders%3Achat-prompt%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fprompts%2Faspnet-minimal-api-openapi.prompt.md) | Prompt | Create ASP.NET Minimal API endpoints with proper OpenAPI documentation |
| [C# Async Programming Best Practices](../prompts/csharp-async.prompt.md)<br />[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/prompt?url=vscode%3Achat-prompt%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fprompts%2Fcsharp-async.prompt.md)<br />[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/prompt?url=vscode-insiders%3Achat-prompt%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fprompts%2Fcsharp-async.prompt.md) | Prompt | Get best practices for C# async programming |
| [C# Development](../instructions/csharp.instructions.md)<br />[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fcsharp.instructions.md)<br />[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fcsharp.instructions.md) | Instruction | Guidelines for building C# applications |
| [DDD Systems & .NET Guidelines](../instructions/dotnet-architecture-good-practices.instructions.md)<br />[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fdotnet-architecture-good-practices.instructions.md)<br />[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fdotnet-architecture-good-practices.instructions.md) | Instruction | DDD and .NET architecture guidelines |
| [Expert .NET software engineer mode instructions](../chatmodes/expert-dotnet-software-engineer.chatmode.md)<br />[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/chatmode?url=vscode%3Achat-mode%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fchatmodes%2Fexpert-dotnet-software-engineer.chatmode.md)<br />[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/chatmode?url=vscode-insiders%3Achat-mode%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fchatmodes%2Fexpert-dotnet-software-engineer.chatmode.md) | Chat Mode | Provide expert .NET software engineering guidance using modern software design patterns. |
| [XUnit Best Practices](../prompts/csharp-xunit.prompt.md)<br />[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/prompt?url=vscode%3Achat-prompt%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fprompts%2Fcsharp-xunit.prompt.md)<br />[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/prompt?url=vscode-insiders%3Achat-prompt%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fprompts%2Fcsharp-xunit.prompt.md) | Prompt | Get best practices for XUnit unit testing, including data-driven tests |

View File

@ -0,0 +1,18 @@
id: devops-oncall
name: DevOps On-Call
description: A focused set of prompts, instructions, and a chat mode to help triage incidents and respond quickly with DevOps tools and Azure resources.
tags: [devops, incident-response, oncall, azure]
items:
- path: prompts/azure-resource-health-diagnose.prompt.md
kind: prompt
- path: instructions/devops-core-principles.instructions.md
kind: instruction
- path: instructions/containerization-docker-best-practices.instructions.md
kind: instruction
- path: chatmodes/azure-principal-architect.chatmode.md
kind: chat-mode
- path: prompts/multi-stage-dockerfile.prompt.md
kind: prompt
display:
ordering: manual
show_badge: true

View File

@ -0,0 +1,18 @@
# DevOps On-Call
A focused set of prompts, instructions, and a chat mode to help triage incidents and respond quickly with DevOps tools and Azure resources.
**Tags:** devops, incident-response, oncall, azure
## Items in this Collection
| Title | Type | Description |
| ----- | ---- | ----------- |
| [Azure Resource Health & Issue Diagnosis](../prompts/azure-resource-health-diagnose.prompt.md)<br />[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/prompt?url=vscode%3Achat-prompt%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fprompts%2Fazure-resource-health-diagnose.prompt.md)<br />[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/prompt?url=vscode-insiders%3Achat-prompt%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fprompts%2Fazure-resource-health-diagnose.prompt.md) | Prompt | Analyze Azure resource health, diagnose issues from logs and telemetry, and create a remediation plan for identified problems. |
| [DevOps Core Principles](../instructions/devops-core-principles.instructions.md)<br />[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fdevops-core-principles.instructions.md)<br />[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fdevops-core-principles.instructions.md) | Instruction | Foundational instructions covering core DevOps principles, culture (CALMS), and key metrics (DORA) to guide GitHub Copilot in understanding and promoting effective software delivery. |
| [Containerization & Docker Best Practices](../instructions/containerization-docker-best-practices.instructions.md)<br />[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fcontainerization-docker-best-practices.instructions.md)<br />[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/instructions?url=vscode-insiders%3Achat-instructions%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Finstructions%2Fcontainerization-docker-best-practices.instructions.md) | Instruction | Comprehensive best practices for creating optimized, secure, and efficient Docker images and managing containers. Covers multi-stage builds, image layer optimization, security scanning, and runtime best practices. |
| [Azure Principal Architect mode instructions](../chatmodes/azure-principal-architect.chatmode.md)<br />[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/chatmode?url=vscode%3Achat-mode%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fchatmodes%2Fazure-principal-architect.chatmode.md)<br />[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/chatmode?url=vscode-insiders%3Achat-mode%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fchatmodes%2Fazure-principal-architect.chatmode.md) | Chat Mode | Provide expert Azure Principal Architect guidance using Azure Well-Architected Framework principles and Microsoft best practices. |
| [Multi Stage Dockerfile](../prompts/multi-stage-dockerfile.prompt.md)<br />[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/prompt?url=vscode%3Achat-prompt%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fprompts%2Fmulti-stage-dockerfile.prompt.md)<br />[![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://aka.ms/awesome-copilot/install/prompt?url=vscode-insiders%3Achat-prompt%2Finstall%3Furl%3Dhttps%3A%2F%2Fraw.githubusercontent.com%2Fgithub%2Fawesome-copilot%2Fmain%2Fprompts%2Fmulti-stage-dockerfile.prompt.md) | Prompt | Create optimized multi-stage Dockerfiles for any language or framework |
---
*This collection includes 5 curated items for devops on-call.*

View File

@ -49,6 +49,22 @@ Custom chat modes define specific behaviors and tools for GitHub Copilot Chat, e
- Import the chat mode configuration into your VS Code settings - Import the chat mode configuration into your VS Code settings
- Access the installed chat modes through the VS Code Chat interface - Access the installed chat modes through the VS Code Chat interface
- Select the desired chat mode from the available options in VS Code Chat`, - Select the desired chat mode from the available options in VS Code Chat`,
collectionsSection: `## 📦 Collections
Curated collections of related prompts, instructions, and chat modes organized around specific themes, workflows, or use cases.`,
collectionsUsage: `### How to Use Collections
**Browse Collections:**
- Explore themed collections that group related customizations
- Each collection includes prompts, instructions, and chat modes for specific workflows
- Collections make it easy to adopt comprehensive toolkits for particular scenarios
**Install Items:**
- Click install buttons for individual items within collections
- Or browse to the individual files to copy content manually
- Collections help you discover related customizations you might have missed`,
}; };
// Add error handling utility // Add error handling utility
@ -61,6 +77,110 @@ function safeFileOperation(operation, filePath, defaultValue = null) {
} }
} }
/**
* Simple YAML parser for collection manifests
* Handles our specific YAML structure without external dependencies
*/
function parseCollectionYaml(filePath) {
return safeFileOperation(
() => {
const content = fs.readFileSync(filePath, "utf8");
const lines = content.split("\n");
const result = {};
let currentKey = null;
let currentArray = null;
let currentObject = null;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith("#")) continue;
const leadingSpaces = line.length - line.trimLeft().length;
// Handle array items starting with -
if (trimmed.startsWith("- ")) {
if (currentKey === "items") {
if (!currentArray) {
currentArray = [];
result[currentKey] = currentArray;
}
// Parse item object
const item = {};
currentArray.push(item);
currentObject = item;
// Handle inline properties on same line as -
const restOfLine = trimmed.substring(2).trim();
if (restOfLine) {
const colonIndex = restOfLine.indexOf(":");
if (colonIndex > -1) {
const key = restOfLine.substring(0, colonIndex).trim();
const value = restOfLine.substring(colonIndex + 1).trim();
item[key] = value;
}
}
} else if (currentKey === "tags") {
if (!currentArray) {
currentArray = [];
result[currentKey] = currentArray;
}
const value = trimmed.substring(2).trim();
currentArray.push(value);
}
}
// Handle key-value pairs
else if (trimmed.includes(":")) {
const colonIndex = trimmed.indexOf(":");
const key = trimmed.substring(0, colonIndex).trim();
let value = trimmed.substring(colonIndex + 1).trim();
if (leadingSpaces === 0) {
// Top-level property
currentKey = key;
currentArray = null;
currentObject = null;
if (value) {
// Handle array format [item1, item2, item3]
if (value.startsWith("[") && value.endsWith("]")) {
const arrayContent = value.slice(1, -1);
if (arrayContent.trim()) {
result[key] = arrayContent.split(",").map(item => item.trim());
} else {
result[key] = [];
}
currentKey = null; // Reset since we handled the array
} else {
result[key] = value;
}
} else if (key === "items" || key === "tags") {
// Will be populated by array items
result[key] = [];
currentArray = result[key];
} else if (key === "display") {
result[key] = {};
currentObject = result[key];
}
} else if (currentObject && leadingSpaces > 0) {
// Property of current object (e.g., display properties)
currentObject[key] = value === "true" ? true : value === "false" ? false : value;
} else if (currentArray && currentObject && leadingSpaces > leadingSpaces) {
// Property of array item object
currentObject[key] = value;
}
}
}
return result;
},
filePath,
null
);
}
function extractTitle(filePath) { function extractTitle(filePath) {
return safeFileOperation( return safeFileOperation(
() => { () => {
@ -409,6 +529,110 @@ function generateChatModesSection(chatmodesDir) {
return `${TEMPLATES.chatmodesSection}\n${TEMPLATES.chatmodesUsage}\n\n${chatmodesContent}`; return `${TEMPLATES.chatmodesSection}\n${TEMPLATES.chatmodesUsage}\n\n${chatmodesContent}`;
} }
/**
* Generate the collections section with a table of all collections
*/
function generateCollectionsSection(collectionsDir) {
// Check if collections directory exists
if (!fs.existsSync(collectionsDir)) {
console.log("Collections directory does not exist");
return "";
}
// Get all collection files
const collectionFiles = fs
.readdirSync(collectionsDir)
.filter((file) => file.endsWith(".collection.yml"))
.sort();
console.log(`Found ${collectionFiles.length} collection files`);
// If no collections, return empty string
if (collectionFiles.length === 0) {
return "";
}
// Create table header
let collectionsContent =
"| Name | Description | Items | Tags |\n| ---- | ----------- | ----- | ---- |\n";
// Generate table rows for each collection file
for (const file of collectionFiles) {
const filePath = path.join(collectionsDir, file);
const collection = parseCollectionYaml(filePath);
if (!collection) {
console.warn(`Failed to parse collection: ${file}`);
continue;
}
const collectionId = collection.id || path.basename(file, ".collection.yml");
const name = collection.name || collectionId;
const description = collection.description || "No description";
const itemCount = collection.items ? collection.items.length : 0;
const tags = collection.tags ? collection.tags.join(", ") : "";
const link = `collections/${collectionId}.md`;
collectionsContent += `| [${name}](${link}) | ${description} | ${itemCount} items | ${tags} |\n`;
}
return `${TEMPLATES.collectionsSection}\n${TEMPLATES.collectionsUsage}\n\n${collectionsContent}`;
}
/**
* Generate individual collection README file
*/
function generateCollectionReadme(collection, collectionId) {
if (!collection || !collection.items) {
return `# ${collectionId}\n\nCollection not found or invalid.`;
}
const name = collection.name || collectionId;
const description = collection.description || "No description provided.";
const tags = collection.tags ? collection.tags.join(", ") : "None";
let content = `# ${name}\n\n${description}\n\n`;
if (collection.tags && collection.tags.length > 0) {
content += `**Tags:** ${tags}\n\n`;
}
content += `## Items in this Collection\n\n`;
content += `| Title | Type | Description |\n| ----- | ---- | ----------- |\n`;
// Sort items based on display.ordering setting
const items = [...collection.items];
if (collection.display?.ordering === "alpha") {
items.sort((a, b) => {
const titleA = extractTitle(path.join(__dirname, a.path));
const titleB = extractTitle(path.join(__dirname, b.path));
return titleA.localeCompare(titleB);
});
}
for (const item of items) {
const filePath = path.join(__dirname, item.path);
const title = extractTitle(filePath);
const description = extractDescription(filePath) || "No description";
const typeDisplay = item.kind === "chat-mode" ? "Chat Mode" :
item.kind === "instruction" ? "Instruction" : "Prompt";
const link = `../${item.path}`;
// Create install badges for each item
const badges = makeBadges(item.path, item.kind === "instruction" ? "instructions" :
item.kind === "chat-mode" ? "mode" : "prompt");
content += `| [${title}](${link})<br />${badges} | ${typeDisplay} | ${description} |\n`;
}
if (collection.display?.show_badge) {
content += `\n---\n*This collection includes ${items.length} curated items for ${name.toLowerCase()}.*`;
}
return content;
}
// Utility: write file only if content changed // Utility: write file only if content changed
function writeFileIfChanged(filePath, content) { function writeFileIfChanged(filePath, content) {
const exists = fs.existsSync(filePath); const exists = fs.existsSync(filePath);
@ -441,11 +665,13 @@ try {
const instructionsDir = path.join(__dirname, "instructions"); const instructionsDir = path.join(__dirname, "instructions");
const promptsDir = path.join(__dirname, "prompts"); const promptsDir = path.join(__dirname, "prompts");
const chatmodesDir = path.join(__dirname, "chatmodes"); const chatmodesDir = path.join(__dirname, "chatmodes");
const collectionsDir = path.join(__dirname, "collections");
// Compose headers for standalone files by converting section headers to H1 // Compose headers for standalone files by converting section headers to H1
const instructionsHeader = TEMPLATES.instructionsSection.replace(/^##\s/m, "# "); const instructionsHeader = TEMPLATES.instructionsSection.replace(/^##\s/m, "# ");
const promptsHeader = TEMPLATES.promptsSection.replace(/^##\s/m, "# "); const promptsHeader = TEMPLATES.promptsSection.replace(/^##\s/m, "# ");
const chatmodesHeader = TEMPLATES.chatmodesSection.replace(/^##\s/m, "# "); const chatmodesHeader = TEMPLATES.chatmodesSection.replace(/^##\s/m, "# ");
const collectionsHeader = TEMPLATES.collectionsSection.replace(/^##\s/m, "# ");
const instructionsReadme = buildCategoryReadme( const instructionsReadme = buildCategoryReadme(
generateInstructionsSection, generateInstructionsSection,
@ -465,11 +691,41 @@ try {
chatmodesHeader, chatmodesHeader,
TEMPLATES.chatmodesUsage TEMPLATES.chatmodesUsage
); );
// Generate collections README
const collectionsReadme = buildCategoryReadme(
generateCollectionsSection,
collectionsDir,
collectionsHeader,
TEMPLATES.collectionsUsage
);
// Write outputs // Write category outputs
writeFileIfChanged(path.join(__dirname, "README.instructions.md"), instructionsReadme); writeFileIfChanged(path.join(__dirname, "README.instructions.md"), instructionsReadme);
writeFileIfChanged(path.join(__dirname, "README.prompts.md"), promptsReadme); writeFileIfChanged(path.join(__dirname, "README.prompts.md"), promptsReadme);
writeFileIfChanged(path.join(__dirname, "README.chatmodes.md"), chatmodesReadme); writeFileIfChanged(path.join(__dirname, "README.chatmodes.md"), chatmodesReadme);
writeFileIfChanged(path.join(__dirname, "README.collections.md"), collectionsReadme);
// Generate individual collection README files
if (fs.existsSync(collectionsDir)) {
console.log("Generating individual collection README files...");
const collectionFiles = fs
.readdirSync(collectionsDir)
.filter((file) => file.endsWith(".collection.yml"));
for (const file of collectionFiles) {
const filePath = path.join(collectionsDir, file);
const collection = parseCollectionYaml(filePath);
if (collection) {
const collectionId = collection.id || path.basename(file, ".collection.yml");
const readmeContent = generateCollectionReadme(collection, collectionId);
const readmeFile = path.join(collectionsDir, `${collectionId}.md`);
writeFileIfChanged(readmeFile, readmeContent);
}
}
}
} catch (error) { } catch (error) {
console.error(`Error generating category README files: ${error.message}`); console.error(`Error generating category README files: ${error.message}`);
process.exit(1); process.exit(1);