Update documentation and prompts for consistency and clarity

- Standardized description formatting in various markdown files to use single quotes.
- Added error handling utility in update-readme.js for safer file operations.
- Improved title extraction logic in update-readme.js to handle frontmatter more robustly.
- Updated chat modes section in README to reflect new emoji and sorted chat mode links.
- Cleaned up various instruction files for better readability and consistency.
- Ensured all markdown files end with a newline for better compatibility with version control.
This commit is contained in:
James Montemagno 2025-07-02 16:35:24 -07:00
parent a0754dd249
commit 17405dfc54
39 changed files with 337 additions and 201 deletions

View File

@ -68,18 +68,15 @@ Ready-to-use prompt templates for specific development scenarios and tasks, defi
> 💡 **Usage**: Use `/prompt-name` in VS Code chat, run `Chat: Run Prompt` command, or hit the run button while you have a prompt open.
## 🧩 Custom Chat Modes
## 🎭 Custom Chat Modes
Custom chat modes define specific behaviors and tools for GitHub Copilot Chat, enabling enhanced context-aware assistance for particular tasks or workflows.
- [4.1 Beast Mode](chatmodes/4.1-beast.chatmode.md) - A custom prompt to get GPT 4.1 to behave like a top-notch coding agent.
- [Database Administrator Chat Mode](chatmodes/postgresql-dba.chatmode.md) - Work with PostgreSQL databases using the PostgreSQL extension.
- [Debug Mode Instructions](chatmodes/debug.chatmode.md) - Debug your application to find and fix a bug
- [Planning mode instructions](chatmodes/planner.chatmode.md) - Generate an implementation plan for new features or refactoring existing code.
- [Refine Requirement or Issue Chat Mode](chatmodes/refine-issue.chatmode.md) - Refine the requirement or issue with Acceptance Criteria, Technical Considerations, Edge Cases, and NFRs
> 💡 **Usage**: Create new chat modes using the command `Chat: Configure Chat Modes...`, then switch your chat mode in the Chat input from _Agent_ or _Ask_ to your own mode.
- [4.1 Beast Mode](chatmodes/4.1-beast.chatmode.md)
- [Debug Mode Instructions](chatmodes/debug.chatmode.md)
- [Planning mode instructions](chatmodes/planner.chatmode.md)
- [Database Administrator Chat Mode](chatmodes/postgresql-dba.chatmode.md)
- [Refine Requirement or Issue Chat Mode](chatmodes/refine-issue.chatmode.md)
## 📚 Additional Resources

View File

@ -1,5 +1,5 @@
---
description: Debug your application to find and fix a bug
description: 'Debug your application to find and fix a bug'
tools: ['codebase', 'readFiles', 'editFiles', 'githubRepo', 'runCommands', 'fetch', 'search', 'usages', 'findTestFiles', 'get_errors', 'test_failure', 'run_in_terminal', 'get_terminal_output']
---

View File

@ -1,5 +1,5 @@
---
description: Generate an implementation plan for new features or refactoring existing code.
description: 'Generate an implementation plan for new features or refactoring existing code.'
tools: ['codebase', 'fetch', 'findTestFiles', 'githubRepo', 'search', 'usages']
---
# Planning mode instructions

View File

@ -1,6 +1,6 @@
---
description: Angular-specific coding standards and best practices
applyTo: "**/*.ts, **/*.html, **/*.scss, **/*.css"
description: 'Angular-specific coding standards and best practices'
applyTo: '**/*.ts, **/*.html, **/*.scss, **/*.css'
---
# Angular Development Instructions

View File

@ -1,6 +1,6 @@
---
description: Guidelines for building REST APIs with ASP.NET
applyTo: "**/*.cs, **/*.json"
description: 'Guidelines for building REST APIs with ASP.NET'
applyTo: '**/*.cs, **/*.json'
---
# ASP.NET REST API Development

View File

@ -1,6 +1,6 @@
---
description: TypeScript patterns for Azure Functions
applyTo: "**/*.ts, **/*.js, **/*.json"
description: 'TypeScript patterns for Azure Functions'
applyTo: '**/*.ts, **/*.js, **/*.json'
---
## Guidance for Code Generation

View File

@ -1,6 +1,6 @@
---
description: Infrastructure as Code with Bicep
applyTo: "**/*.bicep"
description: 'Infrastructure as Code with Bicep'
applyTo: '**/*.bicep'
---
## Naming Conventions

View File

@ -1,6 +1,6 @@
---
description: Blazor component and application patterns
applyTo: "**/*.razor, **/*.razor.cs, **/*.razor.css"
description: 'Blazor component and application patterns'
applyTo: '**/*.razor, **/*.razor.cs, **/*.razor.css'
---
## Blazor Code Style and Structure

View File

@ -1,6 +1,6 @@
---
description: C++ project configuration and package management
applyTo: "**/*.cmake, **/CMakeLists.txt, **/*.cpp, **/*.h, **/*.hpp"
description: 'C++ project configuration and package management'
applyTo: '**/*.cmake, **/CMakeLists.txt, **/*.cpp, **/*.h, **/*.hpp'
---
This project uses vcpkg in manifest mode. Please keep this in mind when giving vcpkg suggestions. Do not provide suggestions like vcpkg install library, as they will not work as expected.

View File

@ -1,6 +1,6 @@
---
description: Guidelines for building C# applications
applyTo: "**/*.cs"
description: 'Guidelines for building C# applications'
applyTo: '**/*.cs'
---
# C# Development

View File

@ -1,8 +1,10 @@
---
description: .NET MAUI component and application patterns
applyTo: "**/*.xaml, **/*.cs"
description: '.NET MAUI component and application patterns'
applyTo: '**/*.xaml, **/*.cs'
---
# .NET MAUI
## .NET MAUI Code Style and Structure
- Write idiomatic and efficient .NET MAUI and C# code.

View File

@ -1,6 +1,6 @@
---
description: AI-powered script generation guidelines
applyTo: "**/*.genai.*"
description: 'AI-powered script generation guidelines'
applyTo: '**/*.genai.*'
---
## Role

View File

@ -1,6 +1,6 @@
---
description: Guidelines for generating modern Terraform code for Azure
applyTo: "**/*.tf"
description: 'Guidelines for generating modern Terraform code for Azure'
applyTo: '**/*.tf'
---
## 1. Use Latest Terraform and Providers

View File

@ -1,6 +1,6 @@
---
description: Guidelines for localizing markdown documents
applyTo: "**/*.md"
description: 'Guidelines for localizing markdown documents'
applyTo: '**/*.md'
---
# Guidance for Localization

View File

@ -1,6 +1,6 @@
---
description: Documentation and content creation standards
applyTo: "**/*.md"
description: 'Documentation and content creation standards'
applyTo: '**/*.md'
---
## Markdown Content Rules

View File

@ -1,6 +1,6 @@
---
description: Next.js + Tailwind development standards and instructions
applyTo: "**/*.tsx, **/*.ts, **/*.jsx, **/*.js, **/*.css"
description: 'Next.js + Tailwind development standards and instructions'
applyTo: '**/*.tsx, **/*.ts, **/*.jsx, **/*.js, **/*.css'
---
# Next.js + Tailwind Development Instructions

View File

@ -1,6 +1,6 @@
---
description: Python coding conventions and guidelines
applyTo: "**/*.py"
description: 'Python coding conventions and guidelines'
applyTo: '**/*.py'
---
# Python Coding Conventions

View File

@ -1,7 +1,7 @@
---
mode: "agent"
tools: ["changes", "codebase", "editFiles", "problems"]
description: "Create ASP.NET Minimal API endpoints with proper OpenAPI documentation"
mode: 'agent'
tools: ['changes', 'codebase', 'editFiles', 'problems']
description: 'Create ASP.NET Minimal API endpoints with proper OpenAPI documentation'
---
Your goal is to help me create well-structured ASP.NET Minimal API endpoints with correct types and comprehensive OpenAPI/Swagger documentation.

View File

@ -1,6 +1,6 @@
---
mode: agent
description: Analyze Azure resources used in the app (IaC files and/or resources in a target rg) and optimize costs - creating GitHub issues for identified optimizations.
mode: 'agent'
description: 'Analyze Azure resources used in the app (IaC files and/or resources in a target rg) and optimize costs - creating GitHub issues for identified optimizations.'
---
## Overview

View File

@ -1,7 +1,7 @@
---
mode: "agent"
tools: ["changes", "codebase", "editFiles", "problems"]
description: "Get best practices for C# async programming"
mode: 'agent'
tools: ['changes', 'codebase', 'editFiles', 'problems']
description: 'Get best practices for C# async programming'
---
# C# Async Programming Best Practices

View File

@ -1,7 +1,7 @@
---
mode: "agent"
tools: ["changes", "codebase", "editFiles", "problems"]
description: "Ensure that C# types are documented with XML comments and follow best practices for documentation."
mode: 'agent'
tools: ['changes', 'codebase', 'editFiles', 'problems']
description: 'Ensure that C# types are documented with XML comments and follow best practices for documentation.'
---
# C# Documentation Best Practices

View File

@ -1,7 +1,7 @@
---
mode: "agent"
tools: ["changes", "codebase", "editFiles", "problems", "search"]
description: "Get best practices for MSTest unit testing, including data-driven tests"
mode: 'agent'
tools: ['changes', 'codebase', 'editFiles', 'problems', 'search']
description: 'Get best practices for MSTest unit testing, including data-driven tests'
---
# MSTest Best Practices

View File

@ -1,7 +1,7 @@
---
mode: "agent"
tools: ["changes", "codebase", "editFiles", "problems", "search"]
description: "Get best practices for NUnit unit testing, including data-driven tests"
mode: 'agent'
tools: ['changes', 'codebase', 'editFiles', 'problems', 'search']
description: 'Get best practices for NUnit unit testing, including data-driven tests'
---
# NUnit Best Practices

View File

@ -1,7 +1,7 @@
---
mode: "agent"
tools: ["changes", "codebase", "editFiles", "problems", "search"]
description: "Get best practices for XUnit unit testing, including data-driven tests"
mode: 'agent'
tools: ['changes', 'codebase', 'editFiles', 'problems', 'search']
description: 'Get best practices for XUnit unit testing, including data-driven tests'
---
# XUnit Best Practices

View File

@ -1,7 +1,7 @@
---
mode: "agent"
tools: ["changes", "codebase", "editFiles", "problems", "runCommands"]
description: "Get best practices for Entity Framework Core"
mode: 'agent'
tools: ['changes', 'codebase', 'editFiles', 'problems', 'runCommands']
description: 'Get best practices for Entity Framework Core'
---
# Entity Framework Core Best Practices

View File

@ -1,5 +1,5 @@
---
description: "Best practices for writing JavaScript/TypeScript tests using Jest, including mocking strategies, test structure, and common patterns."
description: 'Best practices for writing JavaScript/TypeScript tests using Jest, including mocking strategies, test structure, and common patterns.'
---
### Test Structure

View File

@ -1,7 +1,7 @@
---
mode: "agent"
tools: ["codebase"]
description: "Create optimized multi-stage Dockerfiles for any language or framework"
mode: 'agent'
tools: ['codebase']
description: 'Create optimized multi-stage Dockerfiles for any language or framework'
---
Your goal is to help me create efficient multi-stage Dockerfiles that follow best practices, resulting in smaller, more secure container images.

View File

@ -1,7 +1,7 @@
---
mode: agent
mode: 'agent'
tools: ['githubRepo', 'github', 'get_issue', 'get_issue_comments', 'get_me', 'list_issues']
description: "List my issues in the current repository"
description: 'List my issues in the current repository'
---
Search the current repo (using #githubRepo for the repo info) and list any issues you find (using #list_issues) that are assigned to me.

View File

@ -1,7 +1,7 @@
---
mode: agent
mode: 'agent'
tools: ['githubRepo', 'github', 'get_me', 'get_pull_request', 'get_pull_request_comments', 'get_pull_request_diff', 'get_pull_request_files', 'get_pull_request_reviews', 'get_pull_request_status', 'list_pull_requests', 'request_copilot_review']
description: "List my pull requests in the current repository"
description: 'List my pull requests in the current repository'
---
Search the current repo (using #githubRepo for the repo info) and list any pull requests you find (using #list_pull_requests) that are assigned to me.

121
standardize-frontmatter.js Normal file
View File

@ -0,0 +1,121 @@
#!/usr/bin/env node
const fs = require("fs");
const path = require("path");
function standardizeFrontmatter(content) {
const lines = content.split('\n');
const result = [];
let inFrontmatter = false;
let frontmatterEnded = false;
for (const line of lines) {
if (line.trim() === '---') {
if (!inFrontmatter) {
inFrontmatter = true;
result.push(line);
} else if (!frontmatterEnded) {
frontmatterEnded = true;
result.push(line);
} else {
result.push(line);
}
continue;
}
if (inFrontmatter && !frontmatterEnded) {
// Convert frontmatter fields to use single quotes
let modifiedLine = line;
// Handle fields that should use single quotes for strings
const fieldsToStandardize = ['mode', 'description', 'applyTo', 'title'];
for (const field of fieldsToStandardize) {
// Pattern 1: Convert double quotes to single quotes
const doubleQuotePattern = new RegExp(`^(${field}:\\s*)"([^"]*)"(\\s*)$`);
const doubleQuoteMatch = modifiedLine.match(doubleQuotePattern);
if (doubleQuoteMatch) {
modifiedLine = `${doubleQuoteMatch[1]}'${doubleQuoteMatch[2]}'${doubleQuoteMatch[3]}`;
continue; // Skip to next field if we found a match
}
// Pattern 2: Fix double single quotes (''text'') to single quotes
const doubleSingleQuotePattern = new RegExp(`^(${field}:\\s*)''([^']*?)''(\\s*)$`);
const doubleSingleQuoteMatch = modifiedLine.match(doubleSingleQuotePattern);
if (doubleSingleQuoteMatch) {
modifiedLine = `${doubleSingleQuoteMatch[1]}'${doubleSingleQuoteMatch[2]}'${doubleSingleQuoteMatch[3]}`;
continue;
}
// Pattern 3: Fix missing space after colon (field:value -> field: value)
const noSpacePattern = new RegExp(`^(${field}:)([^\\s])`);
const noSpaceMatch = modifiedLine.match(noSpacePattern);
if (noSpaceMatch) {
modifiedLine = modifiedLine.replace(noSpacePattern, `${noSpaceMatch[1]} ${noSpaceMatch[2]}`);
}
// Pattern 4: Add single quotes to unquoted values (but not arrays or objects)
const unquotedPattern = new RegExp(`^(${field}:\\s*)([^'\"\\[\\{][^\\n]*?)(\\s*)$`);
const unquotedMatch = modifiedLine.match(unquotedPattern);
if (unquotedMatch) {
const value = unquotedMatch[2].trim();
// Only quote if it's not already quoted and not empty
if (value && !value.startsWith('[') && !value.startsWith('{')) {
modifiedLine = `${unquotedMatch[1]}'${value}'${unquotedMatch[3]}`;
}
}
}
// Handle tools array - convert double quotes to single quotes within the array
if (modifiedLine.includes('tools:')) {
modifiedLine = modifiedLine.replace(/"/g, "'");
}
result.push(modifiedLine);
} else {
result.push(line);
}
}
return result.join('\n');
}
function processFiles() {
const directories = ['prompts', 'instructions', 'chatmodes'];
let filesProcessed = 0;
for (const dir of directories) {
const dirPath = path.join(__dirname, dir);
if (!fs.existsSync(dirPath)) {
console.log(`Directory ${dir} does not exist, skipping...`);
continue;
}
const files = fs.readdirSync(dirPath);
for (const file of files) {
if (file.endsWith('.md')) {
const filePath = path.join(dirPath, file);
try {
const content = fs.readFileSync(filePath, 'utf8');
const standardizedContent = standardizeFrontmatter(content);
// Only write if content has changed
if (content !== standardizedContent) {
fs.writeFileSync(filePath, standardizedContent);
console.log(`Standardized frontmatter in: ${filePath}`);
filesProcessed++;
}
} catch (error) {
console.error(`Error processing ${filePath}: ${error.message}`);
}
}
}
}
console.log(`\nProcessed ${filesProcessed} files.`);
}
processFiles();

View File

@ -3,153 +3,168 @@
const fs = require("fs");
const path = require("path");
function extractTitle(filePath) {
// Add error handling utility
function safeFileOperation(operation, filePath, defaultValue = null) {
try {
const content = fs.readFileSync(filePath, "utf8");
const lines = content.split("\n");
return operation();
} catch (error) {
console.error(`Error processing file ${filePath}: ${error.message}`);
return defaultValue;
}
}
// Step 1: Look for title in frontmatter for all file types
let inFrontmatter = false;
let frontmatterEnded = false;
function extractTitle(filePath) {
return safeFileOperation(
() => {
const content = fs.readFileSync(filePath, "utf8");
const lines = content.split("\n");
for (const line of lines) {
if (line.trim() === "---") {
if (!inFrontmatter) {
inFrontmatter = true;
} else if (!frontmatterEnded) {
frontmatterEnded = true;
}
continue;
}
// Step 1: Look for title in frontmatter for all file types
let inFrontmatter = false;
let frontmatterEnded = false;
if (inFrontmatter && !frontmatterEnded) {
// Look for title field in frontmatter
const titleMatch = line.match(/^title:\s*['"]?(.+?)['"]?$/);
if (titleMatch) {
return titleMatch[1].trim();
}
}
}
// Reset for second pass
inFrontmatter = false;
frontmatterEnded = false;
// Step 2: For prompt/chatmode files, look for heading after frontmatter
if (filePath.includes(".prompt.md") || filePath.includes(".chatmode.md")) {
for (const line of lines) {
if (line.trim() === "---") {
if (!inFrontmatter) {
inFrontmatter = true;
} else if (inFrontmatter && !frontmatterEnded) {
} else if (!frontmatterEnded) {
frontmatterEnded = true;
}
continue;
}
if (frontmatterEnded && line.startsWith("# ")) {
if (inFrontmatter && !frontmatterEnded) {
// Look for title field in frontmatter
if (line.includes('title:')) {
// Extract everything after 'title:'
const afterTitle = line.substring(line.indexOf('title:') + 6).trim();
// Remove quotes if present
const cleanTitle = afterTitle.replace(/^['"]|['"]$/g, '');
return cleanTitle;
}
}
}
// Reset for second pass
inFrontmatter = false;
frontmatterEnded = false;
// Step 2: For prompt/chatmode files, look for heading after frontmatter
if (filePath.includes(".prompt.md") || filePath.includes(".chatmode.md")) {
for (const line of lines) {
if (line.trim() === "---") {
if (!inFrontmatter) {
inFrontmatter = true;
} else if (inFrontmatter && !frontmatterEnded) {
frontmatterEnded = true;
}
continue;
}
if (frontmatterEnded && line.startsWith("# ")) {
return line.substring(2).trim();
}
}
// Step 3: Format filename for prompt/chatmode files if no heading found
const basename = path.basename(
filePath,
filePath.includes(".prompt.md") ? ".prompt.md" : ".chatmode.md"
);
return basename
.replace(/[-_]/g, " ")
.replace(/\b\w/g, (l) => l.toUpperCase());
}
// Step 4: For instruction files, look for the first heading
for (const line of lines) {
if (line.startsWith("# ")) {
return line.substring(2).trim();
}
}
// Step 3: Format filename for prompt/chatmode files if no heading found
const basename = path.basename(
filePath,
filePath.includes(".prompt.md") ? ".prompt.md" : ".chatmode.md"
);
// Step 5: Fallback to filename
const basename = path.basename(filePath, path.extname(filePath));
return basename
.replace(/[-_]/g, " ")
.replace(/\b\w/g, (l) => l.toUpperCase());
}
// Step 4: For instruction files, look for the first heading
for (const line of lines) {
if (line.startsWith("# ")) {
return line.substring(2).trim();
}
}
// Step 5: Fallback to filename
const basename = path.basename(filePath, path.extname(filePath));
return basename
},
filePath,
path.basename(filePath, path.extname(filePath))
.replace(/[-_]/g, " ")
.replace(/\b\w/g, (l) => l.toUpperCase());
} catch (error) {
// Fallback to filename
const basename = path.basename(filePath, path.extname(filePath));
return basename
.replace(/[-_]/g, " ")
.replace(/\b\w/g, (l) => l.toUpperCase());
}
.replace(/\b\w/g, (l) => l.toUpperCase())
);
}
function extractDescription(filePath) {
try {
const content = fs.readFileSync(filePath, "utf8");
return safeFileOperation(
() => {
const content = fs.readFileSync(filePath, "utf8");
// Parse frontmatter for description (for both prompts and instructions)
const lines = content.split("\n");
let inFrontmatter = false;
let frontmatterEnded = false;
// Parse frontmatter for description (for both prompts and instructions)
const lines = content.split("\n");
let inFrontmatter = false;
let frontmatterEnded = false;
// For multi-line descriptions
let isMultilineDescription = false;
let multilineDescription = [];
// For multi-line descriptions
let isMultilineDescription = false;
let multilineDescription = [];
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (line.trim() === "---") {
if (!inFrontmatter) {
inFrontmatter = true;
} else if (inFrontmatter && !frontmatterEnded) {
frontmatterEnded = true;
break;
}
continue;
}
if (inFrontmatter && !frontmatterEnded) {
// Check for multi-line description with pipe syntax (|)
const multilineMatch = line.match(/^description:\s*\|(\s*)$/);
if (multilineMatch) {
isMultilineDescription = true;
// Continue to next line to start collecting the multi-line content
if (line.trim() === "---") {
if (!inFrontmatter) {
inFrontmatter = true;
} else if (inFrontmatter && !frontmatterEnded) {
frontmatterEnded = true;
break;
}
continue;
}
// If we're collecting a multi-line description
if (isMultilineDescription) {
// If the line has no indentation or has another frontmatter key, stop collecting
if (!line.startsWith(" ") || line.match(/^[a-zA-Z0-9_-]+:/)) {
isMultilineDescription = false;
// Join the collected lines and return
return multilineDescription.join(" ").trim();
if (inFrontmatter && !frontmatterEnded) {
// Check for multi-line description with pipe syntax (|)
const multilineMatch = line.match(/^description:\s*\|(\s*)$/);
if (multilineMatch) {
isMultilineDescription = true;
// Continue to next line to start collecting the multi-line content
continue;
}
// Add the line to our multi-line collection (removing the 2-space indentation)
multilineDescription.push(line.substring(2));
} else {
// Look for single-line description field in frontmatter
const descriptionMatch = line.match(
/^description:\s*['"]?(.+?)['"]?$/
);
if (descriptionMatch) {
return descriptionMatch[1];
// If we're collecting a multi-line description
if (isMultilineDescription) {
// If the line has no indentation or has another frontmatter key, stop collecting
if (!line.startsWith(" ") || line.match(/^[a-zA-Z0-9_-]+:/)) {
isMultilineDescription = false;
// Join the collected lines and return
return multilineDescription.join(" ").trim();
}
// Add the line to our multi-line collection (removing the 2-space indentation)
multilineDescription.push(line.substring(2));
} else {
// Look for single-line description field in frontmatter
const descriptionMatch = line.match(
/^description:\s*['"]?(.+?)['"]?$/
);
if (descriptionMatch) {
return descriptionMatch[1];
}
}
}
}
}
// If we've collected multi-line description but the frontmatter ended
if (multilineDescription.length > 0) {
return multilineDescription.join(" ").trim();
}
// If we've collected multi-line description but the frontmatter ended
if (multilineDescription.length > 0) {
return multilineDescription.join(" ").trim();
}
return null;
} catch (error) {
return null;
}
return null;
},
filePath,
null
);
}
function updateInstructionsSection(
@ -391,15 +406,15 @@ function updateChatModesSection(currentReadme, chatmodeFiles, chatmodesDir) {
console.log(`Found ${newChatModeFiles.length} new chat modes to add.`);
}
const chatmodesSection = currentReadme.match(
/## 🧩 Custom Chat Modes\n\nCustom chat modes define.+?(?=\n\n>)/s
);
// Look for ANY existing chat modes section (with any emoji)
const chatmodesSectionRegex = /## [🧩🎭].*Custom Chat Modes[\s\S]*?(?=\n## |\n\n## |$)/;
const chatmodesSection = currentReadme.match(chatmodesSectionRegex);
if (chatmodesSection) {
let chatmodesListContent = "\n\n";
// Generate list of chat mode links
for (const file of chatmodeFiles) {
// Generate list of chat mode links (sorted alphabetically)
for (const file of chatmodeFiles.sort()) {
const filePath = path.join(chatmodesDir, file);
const title = extractTitle(filePath);
const link = encodeURI(`chatmodes/${file}`);
@ -418,7 +433,7 @@ function updateChatModesSection(currentReadme, chatmodeFiles, chatmodesDir) {
// Replace the current chat modes section with the updated one
const newChatmodesSection =
"## 🧩 Custom Chat Modes\n\nCustom chat modes define specific behaviors and tools for GitHub Copilot Chat, enabling enhanced context-aware assistance for particular tasks or workflows." +
"## 🎭 Custom Chat Modes\n\nCustom chat modes define specific behaviors and tools for GitHub Copilot Chat, enabling enhanced context-aware assistance for particular tasks or workflows." +
chatmodesListContent;
return currentReadme.replace(chatmodesSection[0], newChatmodesSection);
@ -429,6 +444,7 @@ function updateChatModesSection(currentReadme, chatmodeFiles, chatmodesDir) {
);
const chatmodesListContent = chatmodeFiles
.sort()
.map((file) => {
const filePath = path.join(chatmodesDir, file);
const title = extractTitle(filePath);