Rohan03 commited on
Commit
c63c002
·
verified ·
1 Parent(s): fb16a26

Sprint 4D: AGENTS.md parser

Browse files
purpose_agent/protocols/agents_md.py ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ agents_md.py — Parser for repo-local AGENTS.md instruction files.
3
+
4
+ Precedence: system_policy > developer_config > AGENTS.md > team_purpose > skill_cards > user_task
5
+ """
6
+ from __future__ import annotations
7
+ import logging
8
+ from dataclasses import dataclass, field
9
+ from pathlib import Path
10
+ from typing import Any
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+ @dataclass
15
+ class AgentsConfig:
16
+ instructions: list[str] = field(default_factory=list)
17
+ capabilities: dict[str, str] = field(default_factory=dict)
18
+ constraints: list[str] = field(default_factory=list)
19
+ metadata: dict[str, Any] = field(default_factory=dict)
20
+ source_path: str = ""
21
+ def to_prompt_section(self) -> str:
22
+ parts = []
23
+ if self.instructions:
24
+ parts.append("## Repository Instructions (AGENTS.md)")
25
+ for i in self.instructions: parts.append(f"- {i}")
26
+ if self.constraints:
27
+ parts.append("\n## Constraints")
28
+ for c in self.constraints: parts.append(f"- {c}")
29
+ return "\n".join(parts)
30
+ @property
31
+ def has_content(self) -> bool:
32
+ return bool(self.instructions or self.capabilities or self.constraints)
33
+
34
+ def parse_agents_md(content: str, source_path: str = "") -> AgentsConfig:
35
+ config = AgentsConfig(source_path=source_path)
36
+ if content.startswith("---"):
37
+ end = content.find("---", 3)
38
+ if end > 0: content = content[end+3:]
39
+ current = None
40
+ for line in content.split("\n"):
41
+ line = line.strip()
42
+ if line.startswith("## ") or line.startswith("# "):
43
+ h = line.lstrip("#").strip().lower()
44
+ if "instruction" in h: current = "instructions"
45
+ elif "capabilit" in h: current = "capabilities"
46
+ elif "constraint" in h: current = "constraints"
47
+ else: current = None
48
+ continue
49
+ if not line or line.startswith("<!--"): continue
50
+ item = line.lstrip("- ").lstrip("* ").strip()
51
+ if not item: continue
52
+ if current == "instructions": config.instructions.append(item)
53
+ elif current == "capabilities":
54
+ if ":" in item:
55
+ n, d = item.split(":", 1); config.capabilities[n.strip()] = d.strip()
56
+ else: config.capabilities[item] = ""
57
+ elif current == "constraints": config.constraints.append(item)
58
+ return config
59
+
60
+ def load_agents_md(path: str = "AGENTS.md") -> AgentsConfig | None:
61
+ for p in [Path(path), Path(".github/AGENTS.md"), Path("docs/AGENTS.md")]:
62
+ if p.exists():
63
+ try:
64
+ config = parse_agents_md(p.read_text(), str(p))
65
+ if config.has_content: return config
66
+ except: pass
67
+ return None