"""本地 Skills 加载器 - Phase 9.2""" import os import re from typing import Any from app.agents.skills.metadata import SkillMetadata class LocalSkillLoader: """本地 Skills 加载器 从 skills_dir 目录加载 SKILL.md 文件。 """ def __init__(self, skills_dir: str): self.skills_dir = skills_dir def load_all(self) -> list[SkillMetadata]: """加载所有本地 Skills Returns: Skill 元数据列表 """ skills = [] if not os.path.exists(self.skills_dir): return skills for root, dirs, files in os.walk(self.skills_dir): # 跳过隐藏目录 dirs[:] = [d for d in dirs if not d.startswith(".")] if "SKILL.md" in files: skill = self._load_skill_from_dir(root) if skill: skills.append(skill) return skills def _load_skill_from_dir(self, skill_dir: str) -> SkillMetadata | None: """从目录加载 Skill Args: skill_dir: Skill 目录 Returns: Skill 元数据 """ skill_path = os.path.join(skill_dir, "SKILL.md") try: with open(skill_path, "r", encoding="utf-8") as f: content = f.read() # 解析 frontmatter metadata = self._parse_frontmatter(content) # 获取 Skill 名称(目录名) name = os.path.basename(skill_dir) return SkillMetadata( name=metadata.get("name", name), description=metadata.get("description", ""), version=metadata.get("version", "1.0.0"), author=metadata.get("author", ""), tags=metadata.get("tags", []), triggers=metadata.get("triggers", []), content=content, source="local", source_id=skill_dir, ) except Exception: return None def _parse_frontmatter(self, content: str) -> dict[str, Any]: """解析 frontmatter""" metadata = {} # 匹配 --- 包裹的 frontmatter match = re.match(r"^---\n(.*?)\n---", content, re.DOTALL) if match: frontmatter = match.group(1) for line in frontmatter.split("\n"): if ":" in line: key, value = line.split(":", 1) key = key.strip() value = value.strip() # 处理列表 if value.startswith("[") and value.endswith("]"): value = [v.strip().strip('"').strip("'") for v in value[1:-1].split(",")] elif value.lower() in ("true", "false"): value = value.lower() == "true" metadata[key] = value return metadata