Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,24 +489,30 @@ function readAgentsFile(filePath: string): string | null {
*/
function parseAgentsContent(
content: string,
): Record<string, { title: string; content: string }> {
const sections: Record<string, { title: string; content: string }> = {};
): Record<string, { title: string; content: string; level: number }> {
const sections: Record<
string,
{ title: string; content: string; level: number }
> = {};
const lines = content.split('\n');
let currentKey = '';
let currentTitle = '';
let currentLevel = 0;
let currentContent: string[] = [];

for (const line of lines) {
const sectionMatch = line.match(/^##\s+(.+)$/);
const sectionMatch = line.match(/^(#{1,2})\s+(.+)$/);
if (sectionMatch) {
if (currentKey) {
sections[currentKey] = {
title: currentTitle,
level: currentLevel,
content: currentContent.join('\n').trim(),
};
}
currentTitle = sectionMatch[1];
currentKey = sectionMatch[1].toLowerCase();
currentLevel = sectionMatch[1].length;
currentTitle = sectionMatch[2].trim();
currentKey = `${currentLevel}-${currentTitle.toLowerCase()}`;
currentContent = [];
} else if (currentKey) {
currentContent.push(line);
Expand All @@ -516,6 +522,7 @@ function parseAgentsContent(
if (currentKey) {
sections[currentKey] = {
title: currentTitle,
level: currentLevel,
content: currentContent.join('\n').trim(),
};
}
Expand All @@ -527,15 +534,22 @@ function parseAgentsContent(
* Merge AGENTS.md files from multiple sources
*/
function mergeAgentsFiles(agentsFiles: string[]): string {
const allSections: Record<string, { title: string; contents: string[] }> = {};
const allSections: Record<
string,
{ title: string; level: number; contents: string[] }
> = {};

for (const fileContent of agentsFiles) {
if (!fileContent) continue;
const sections = parseAgentsContent(fileContent);

for (const [key, section] of Object.entries(sections)) {
if (!allSections[key]) {
allSections[key] = { title: section.title, contents: [] };
allSections[key] = {
title: section.title,
level: section.level,
contents: [],
};
}
if (
section.content &&
Expand All @@ -549,7 +563,7 @@ function mergeAgentsFiles(agentsFiles: string[]): string {
const result: string[] = [];

for (const [, section] of Object.entries(allSections)) {
result.push(`## ${section.title}`);
result.push(`${'#'.repeat(section.level)} ${section.title}`);
result.push('');
for (const content of section.contents) {
result.push(content);
Expand Down
24 changes: 24 additions & 0 deletions test/agents.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,27 @@ test('should generate AGENTS.md with eslint tool and template mapping', async ()
assert.match(content, /## Tools/);
assert.match(content, /### ESLint/); // from template-eslint/AGENTS.md
});

test('should merge top-level sections from AGENTS.md files', async () => {
const projectDir = path.join(testDir, 'h1-support');
process.argv = ['node', 'test', '--dir', projectDir, '--template', 'vanilla'];

await create({
name: 'test',
root: fixturesDir,
templates: ['vanilla'],
getTemplateName: async () => 'vanilla',
mapESLintTemplate: () => null,
});

const agentsPath = path.join(projectDir, 'AGENTS.md');
assert.strictEqual(fs.existsSync(agentsPath), true);

const content = fs.readFileSync(agentsPath, 'utf-8');
const h1Matches = content.match(/^# Project Overview$/gm) ?? [];
assert.strictEqual(h1Matches.length, 1);
assert.match(
content,
/This section provides common guidance for all templates./,
);
});
6 changes: 5 additions & 1 deletion test/fixtures/agents-md/template-common/AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Project Overview

This section provides common guidance for all templates.

## Development

### Common Development
Expand All @@ -7,4 +11,4 @@
## Tools

### Common Tools
- Tools that apply to all templates
- Tools that apply to all templates