78 lines
2.3 KiB
Python
78 lines
2.3 KiB
Python
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
|