from __future__ import annotations import re from dataclasses import dataclass from pathlib import Path @dataclass(frozen=True) class Skill: slug: str name: str description: str use_when: str content: str path: Path | None INDEX_ROW_RE = re.compile( r"^\|\s*\[([^\]]+)\]\(([^)]+)\)\s*\|\s*([^|]+?)\s*\|\s*([^|]+?)\s*\|" ) FRONT_MATTER_RE = re.compile(r"^---\n(.*?)\n---\n", re.DOTALL) def _front_matter_value(content: str, key: str) -> str | None: match = FRONT_MATTER_RE.match(content) if not match: return None for line in match.group(1).splitlines(): if line.startswith(f"{key}:"): return line.split(":", 1)[1].strip() return None def load_skill_catalog(root: Path | str = Path("skills") / "GJB438C-2021_prd_skills") -> list[Skill]: root_path = Path(root) index_path = root_path / "index.md" skills: list[Skill] = [] seen: set[str] = set() if index_path.exists(): for line in index_path.read_text(encoding="utf-8").splitlines(): match = INDEX_ROW_RE.match(line) if not match: continue slug, relative_path, description, use_when = [part.strip() for part in match.groups()] skill_path = root_path / relative_path content = skill_path.read_text(encoding="utf-8") if skill_path.exists() else "" name = _front_matter_value(content, "name") or slug skills.append( Skill( slug=slug, name=name, description=description, use_when=use_when, content=content, path=skill_path, ) ) seen.add(slug) for skill_path in sorted(root_path.glob("*/SKILL.md")): slug = skill_path.parent.name if slug in seen: continue content = skill_path.read_text(encoding="utf-8") skills.append( Skill( slug=slug, name=_front_matter_value(content, "name") or slug, description=_front_matter_value(content, "description") or "", use_when="", content=content, path=skill_path, ) ) return skills