from __future__ import annotations from pathlib import Path import frontmatter # type: ignore[import-untyped] import yaml from pydantic import BaseModel, ConfigDict class ParsedSkill(BaseModel): model_config = ConfigDict(frozen=True) frontmatter: dict[str, object] body: str mtime: float class ParseError(Exception): """Raised when a SKILL.md cannot be parsed.""" def parse_skill(path: Path) -> ParsedSkill: """Parse a SKILL.md file: extract YAML frontmatter and markdown body.""" try: raw = path.read_text(encoding="utf-8") except OSError as e: raise ParseError(f"unreadable: {path}: {e}") from e try: post = frontmatter.loads(raw) except yaml.YAMLError as e: raise ParseError(f"malformed yaml in {path}: {e}") from e mtime = path.stat().st_mtime return ParsedSkill(frontmatter=dict(post.metadata), body=post.content, mtime=mtime)