File size: 2,682 Bytes
c63c002
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
"""
agents_md.py — Parser for repo-local AGENTS.md instruction files.

Precedence: system_policy > developer_config > AGENTS.md > team_purpose > skill_cards > user_task
"""
from __future__ import annotations
import logging
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any

logger = logging.getLogger(__name__)

@dataclass
class AgentsConfig:
    instructions: list[str] = field(default_factory=list)
    capabilities: dict[str, str] = field(default_factory=dict)
    constraints: list[str] = field(default_factory=list)
    metadata: dict[str, Any] = field(default_factory=dict)
    source_path: str = ""
    def to_prompt_section(self) -> str:
        parts = []
        if self.instructions:
            parts.append("## Repository Instructions (AGENTS.md)")
            for i in self.instructions: parts.append(f"- {i}")
        if self.constraints:
            parts.append("\n## Constraints")
            for c in self.constraints: parts.append(f"- {c}")
        return "\n".join(parts)
    @property
    def has_content(self) -> bool:
        return bool(self.instructions or self.capabilities or self.constraints)

def parse_agents_md(content: str, source_path: str = "") -> AgentsConfig:
    config = AgentsConfig(source_path=source_path)
    if content.startswith("---"):
        end = content.find("---", 3)
        if end > 0: content = content[end+3:]
    current = None
    for line in content.split("\n"):
        line = line.strip()
        if line.startswith("## ") or line.startswith("# "):
            h = line.lstrip("#").strip().lower()
            if "instruction" in h: current = "instructions"
            elif "capabilit" in h: current = "capabilities"
            elif "constraint" in h: current = "constraints"
            else: current = None
            continue
        if not line or line.startswith("<!--"): continue
        item = line.lstrip("- ").lstrip("* ").strip()
        if not item: continue
        if current == "instructions": config.instructions.append(item)
        elif current == "capabilities":
            if ":" in item:
                n, d = item.split(":", 1); config.capabilities[n.strip()] = d.strip()
            else: config.capabilities[item] = ""
        elif current == "constraints": config.constraints.append(item)
    return config

def load_agents_md(path: str = "AGENTS.md") -> AgentsConfig | None:
    for p in [Path(path), Path(".github/AGENTS.md"), Path("docs/AGENTS.md")]:
        if p.exists():
            try:
                config = parse_agents_md(p.read_text(), str(p))
                if config.has_content: return config
            except: pass
    return None