diff --git a/Makefile b/Makefile index 2b792d76db5..3181ed1c41d 100644 --- a/Makefile +++ b/Makefile @@ -1040,6 +1040,11 @@ generate-schema-docs: generate-agent-factory: node scripts/generate-agent-factory.js +# Generate llms.txt at repository root from .github/aw/*.md +.PHONY: generate-llms-txt +generate-llms-txt: + node scripts/generate-llms-txt.js + # Build slides with Marp .PHONY: build-slides build-slides: @@ -1217,7 +1222,7 @@ sbom: # Agent should run this task before finishing its turns .PHONY: agent-finish -agent-finish: deps-dev fmt lint build build-wasm test-all validate-otel-contract fix recompile dependabot generate-schema-docs generate-agent-factory security-scan +agent-finish: deps-dev fmt lint build build-wasm test-all validate-otel-contract fix recompile dependabot generate-schema-docs generate-agent-factory generate-llms-txt security-scan @echo "Agent finished tasks successfully." # Fast pre-PR gate — run before every intermediate report_progress call. @@ -1322,6 +1327,7 @@ help: @echo " dependabot - Generate Dependabot manifests for npm dependencies in workflows" @echo " generate-schema-docs - Generate frontmatter full reference documentation from JSON schema" @echo " generate-agent-factory - Generate agent factory documentation page" + @echo " generate-llms-txt - Generate llms.txt at repository root from .github/aw/*.md" @echo " build-slides - Build slides with Marp to docs/public/slides/gh-aw.html" @echo " deps-docs - Install Astro documentation dependencies" @echo " build-docs - Build Astro documentation to docs/dist" diff --git a/scripts/generate-llms-txt.js b/scripts/generate-llms-txt.js new file mode 100644 index 00000000000..55f580bd2f7 --- /dev/null +++ b/scripts/generate-llms-txt.js @@ -0,0 +1,63 @@ +#!/usr/bin/env node + +/** + * llms.txt Generator + * + * Generates llms.txt at the repository root from the agent prompt files in + * .github/aw/*.md. Mirrors the logic in docs/src/pages/llms.txt.ts so that + * https://github.com//gh-aw/llms.txt resolves to the same content that + * the docs site serves at /llms.txt. + * + * Usage: + * node scripts/generate-llms-txt.js + */ + +import fs from "fs"; +import path from "path"; +import { fileURLToPath } from "url"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +const ROOT = path.resolve(__dirname, ".."); +const AW_DIR = path.join(ROOT, ".github", "aw"); +const OUT_FILE = path.join(ROOT, "llms.txt"); +const RAW_BASE = "https://raw.githubusercontent.com/github/gh-aw/main/.github/aw"; + +function parseFrontmatterDescription(content) { + const match = content.match(/^---[\r\n]+([\s\S]*?)[\r\n]+---/); + if (!match) return ""; + const descMatch = match[1].match(/^description:\s*(.+)$/m); + return descMatch ? descMatch[1].trim() : ""; +} + +const files = fs + .readdirSync(AW_DIR) + .filter(f => f.endsWith(".md")) + .sort(); + +const prompts = files.map(file => { + const content = fs.readFileSync(path.join(AW_DIR, file), "utf-8"); + return { + file, + description: parseFrontmatterDescription(content), + rawUrl: `${RAW_BASE}/${file}`, + }; +}); + +const lines = [ + "# GitHub Agentic Workflows", + "", + "> Agent-optimised prompt files for GitHub Agentic Workflows (gh-aw).", + "> These markdown files are designed for AI agents and LLMs, not human readers.", + "", + "## Agent Prompts", + "", + ...prompts.map(({ file, description, rawUrl }) => { + const label = file.replace(/\.md$/, ""); + return description ? `- [${label}](${rawUrl}): ${description}` : `- [${label}](${rawUrl})`; + }), +]; + +fs.writeFileSync(OUT_FILE, lines.join("\n") + "\n", "utf-8"); +console.log(`Written ${OUT_FILE} (${prompts.length} prompts)`);