re-uploading work
This commit is contained in:
228
scripts/generate_agents_md_index.py
Executable file
228
scripts/generate_agents_md_index.py
Executable file
@@ -0,0 +1,228 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate AGENTS.md index file in minified format.
|
||||
|
||||
This script scans the docs, scripts, and work-summary directories
|
||||
and generates a minified index file that helps AI agents quickly
|
||||
understand the project structure and available documentation.
|
||||
|
||||
The script uses AGENTS.md.template as a base and injects the generated
|
||||
index at the {{DOCUMENTATION_INDEX}} placeholder.
|
||||
|
||||
Usage:
|
||||
python scripts/generate_agents_md_index.py
|
||||
"""
|
||||
|
||||
import os
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Set
|
||||
|
||||
|
||||
def get_project_root() -> Path:
|
||||
"""Get the project root directory (parent of scripts/)."""
|
||||
script_dir = Path(__file__).parent
|
||||
return script_dir.parent
|
||||
|
||||
|
||||
def scan_directory(
|
||||
base_path: Path, extensions: Set[str] = None
|
||||
) -> Dict[str, List[str]]:
|
||||
"""
|
||||
Scan a directory and organize files by subdirectory.
|
||||
|
||||
Args:
|
||||
base_path: Directory to scan
|
||||
extensions: Set of file extensions to include (e.g., {'.md', '.py'}). None means all files.
|
||||
|
||||
Returns:
|
||||
Dictionary mapping relative directory paths to lists of filenames
|
||||
"""
|
||||
if not base_path.exists():
|
||||
return {}
|
||||
|
||||
structure = defaultdict(list)
|
||||
|
||||
for item in sorted(base_path.rglob("*")):
|
||||
if item.is_file():
|
||||
# Filter by extension if specified
|
||||
if extensions and item.suffix not in extensions:
|
||||
continue
|
||||
|
||||
# Get relative path from base_path
|
||||
rel_path = item.relative_to(base_path)
|
||||
parent_dir = str(rel_path.parent) if rel_path.parent != Path(".") else ""
|
||||
|
||||
structure[parent_dir].append(item.name)
|
||||
|
||||
return structure
|
||||
|
||||
|
||||
def format_directory_entry(
|
||||
dir_path: str, files: List[str], max_files: int = None
|
||||
) -> str:
|
||||
"""
|
||||
Format a directory entry in minified format.
|
||||
|
||||
Args:
|
||||
dir_path: Directory path (empty string for root)
|
||||
files: List of filenames in the directory
|
||||
max_files: Maximum number of files to list before truncating
|
||||
|
||||
Returns:
|
||||
Formatted string like "path:{file1,file2,...}"
|
||||
"""
|
||||
if not files:
|
||||
return ""
|
||||
|
||||
# Sort files for consistency
|
||||
sorted_files = sorted(files)
|
||||
|
||||
# Truncate if needed
|
||||
if max_files and len(sorted_files) > max_files:
|
||||
file_list = sorted_files[:max_files] + ["..."]
|
||||
else:
|
||||
file_list = sorted_files
|
||||
|
||||
files_str = ",".join(file_list)
|
||||
|
||||
if dir_path:
|
||||
return f"{dir_path}:{{{files_str}}}"
|
||||
else:
|
||||
return f"root:{{{files_str}}}"
|
||||
|
||||
|
||||
def generate_index_content(root_dirs: Dict[str, Dict[str, any]]) -> str:
|
||||
"""
|
||||
Generate the documentation index content.
|
||||
|
||||
Args:
|
||||
root_dirs: Dictionary mapping directory names to their scan configs
|
||||
|
||||
Returns:
|
||||
Formatted index content as a string
|
||||
"""
|
||||
lines = []
|
||||
|
||||
lines.append("[Attune Project Documentation Index]")
|
||||
lines.append("|root: ./")
|
||||
lines.append(
|
||||
"|IMPORTANT: Prefer retrieval-led reasoning over pre-training-led reasoning"
|
||||
)
|
||||
lines.append(
|
||||
"|IMPORTANT: This index provides a quick overview - use grep/read_file for details"
|
||||
)
|
||||
lines.append("|")
|
||||
lines.append("| Format: path/to/dir:{file1,file2,...}")
|
||||
lines.append(
|
||||
"| '...' indicates truncated file list - use grep/list_directory for full contents"
|
||||
)
|
||||
lines.append("|")
|
||||
lines.append("| To regenerate this index: make generate-agents-index")
|
||||
lines.append("|")
|
||||
|
||||
# Process each root directory
|
||||
for dir_name, config in root_dirs.items():
|
||||
base_path = config["path"]
|
||||
extensions = config.get("extensions")
|
||||
max_files = config.get("max_files", 10)
|
||||
|
||||
structure = scan_directory(base_path, extensions)
|
||||
|
||||
if not structure:
|
||||
lines.append(f"|{dir_name}: (empty)")
|
||||
continue
|
||||
|
||||
# Sort directories for consistent output
|
||||
sorted_dirs = sorted(structure.keys())
|
||||
|
||||
for dir_path in sorted_dirs:
|
||||
files = structure[dir_path]
|
||||
|
||||
# Build the full path relative to project root
|
||||
if dir_path:
|
||||
full_path = f"{dir_name}/{dir_path}"
|
||||
else:
|
||||
full_path = dir_name
|
||||
|
||||
entry = format_directory_entry(full_path, files, max_files)
|
||||
if entry:
|
||||
lines.append(f"|{entry}")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def generate_agents_md(
|
||||
template_path: Path, output_path: Path, root_dirs: Dict[str, Dict[str, any]]
|
||||
) -> None:
|
||||
"""
|
||||
Generate the AGENTS.md file using template.
|
||||
|
||||
Args:
|
||||
template_path: Path to AGENTS.md.template file
|
||||
output_path: Path where AGENTS.md should be written
|
||||
root_dirs: Dictionary mapping directory names to their scan configs
|
||||
"""
|
||||
# Generate the index content
|
||||
index_content = generate_index_content(root_dirs)
|
||||
|
||||
# Read the template
|
||||
if not template_path.exists():
|
||||
print(f"⚠️ Template not found at {template_path}")
|
||||
print(f" Creating AGENTS.md without template...")
|
||||
content = index_content + "\n"
|
||||
else:
|
||||
template = template_path.read_text()
|
||||
# Inject the index into the template
|
||||
content = template.replace("{{DOCUMENTATION_INDEX}}", index_content)
|
||||
|
||||
# Write to file
|
||||
output_path.write_text(content)
|
||||
print(f"✓ Generated {output_path}")
|
||||
index_lines = index_content.count("\n") + 1
|
||||
total_lines = content.count("\n") + 1
|
||||
print(f" Index lines: {index_lines}")
|
||||
print(f" Total lines: {total_lines}")
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entry point."""
|
||||
project_root = get_project_root()
|
||||
|
||||
# Configuration for directories to scan
|
||||
root_dirs = {
|
||||
"docs": {
|
||||
"path": project_root / "docs",
|
||||
"extensions": {".md", ".txt", ".yaml", ".yml", ".json", ".sh"},
|
||||
"max_files": 15,
|
||||
},
|
||||
"scripts": {
|
||||
"path": project_root / "scripts",
|
||||
"extensions": {".sh", ".py", ".sql", ".js", ".html"},
|
||||
"max_files": 20,
|
||||
},
|
||||
"work-summary": {
|
||||
"path": project_root / "work-summary",
|
||||
"extensions": {".md", ".txt"},
|
||||
"max_files": 20,
|
||||
},
|
||||
}
|
||||
|
||||
template_path = project_root / "AGENTS.md.template"
|
||||
output_path = project_root / "AGENTS.md"
|
||||
|
||||
print("Generating AGENTS.md index...")
|
||||
print(f"Project root: {project_root}")
|
||||
print(f"Template: {template_path}")
|
||||
print()
|
||||
|
||||
# Generate the index
|
||||
generate_agents_md(template_path, output_path, root_dirs)
|
||||
|
||||
print()
|
||||
print("Index generation complete!")
|
||||
print(f"Review the generated file at: {output_path}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user