Repository URL to install this package:
|
Version:
0.7.15 ▾
|
from pathlib import Path
import yaml
from .errors import ParseError, ValidationError
from .models import SkillProperties
def find_skill_md(skill_dir: Path) -> Path | None:
for name in ("SKILL.md", "skill.md"):
path = skill_dir / name
if path.exists():
return path
return None
def parse_frontmatter(content: str) -> tuple[dict, str]:
if not content.startswith("---"):
raise ParseError("SKILL.md must start with YAML frontmatter (---)")
parts = content.split("---", 2)
if len(parts) < 3:
raise ParseError("SKILL.md frontmatter not properly closed with ---")
frontmatter_str = parts[1]
body = parts[2].strip()
try:
metadata = yaml.safe_load(frontmatter_str)
except yaml.YAMLError as exc:
raise ParseError(f"Invalid YAML in frontmatter: {exc}") from exc
if not isinstance(metadata, dict):
raise ParseError("SKILL.md frontmatter must be a YAML mapping")
if "metadata" in metadata and isinstance(metadata["metadata"], dict):
metadata["metadata"] = {
str(key): str(value) for key, value in metadata["metadata"].items()
}
return metadata, body
def read_properties(skill_dir: Path) -> SkillProperties:
skill_dir = Path(skill_dir)
skill_md = find_skill_md(skill_dir)
if skill_md is None:
raise ParseError(f"SKILL.md not found in {skill_dir}")
content = skill_md.read_text(encoding="utf-8")
metadata, _ = parse_frontmatter(content)
if "name" not in metadata:
raise ValidationError("Missing required field in frontmatter: name")
if "description" not in metadata:
raise ValidationError("Missing required field in frontmatter: description")
name = metadata["name"]
description = metadata["description"]
if not isinstance(name, str) or not name.strip():
raise ValidationError("Field 'name' must be a non-empty string")
if not isinstance(description, str) or not description.strip():
raise ValidationError("Field 'description' must be a non-empty string")
return SkillProperties(
name=name.strip(),
description=description.strip(),
license=metadata.get("license"),
compatibility=metadata.get("compatibility"),
allowed_tools=metadata.get("allowed-tools"),
metadata=metadata.get("metadata"),
)