from __future__ import annotations from pathlib import Path from supply_agent.skills.loader import SkillLoader from supply_agent.types import SkillInfo class SkillRegistry: """Registry for managing agent skills (specialized instruction sets).""" def __init__(self, skills_dir: Path | str | None = None) -> None: self._skills: dict[str, SkillInfo] = {} if skills_dir: self.load_from_directory(skills_dir) def register(self, skill: SkillInfo) -> None: self._skills[skill.name] = skill def unregister(self, name: str) -> None: self._skills.pop(name, None) def get(self, name: str) -> SkillInfo | None: return self._skills.get(name) def list_skills(self) -> list[str]: return list(self._skills.keys()) def load_from_directory(self, skills_dir: Path | str) -> int: """Discover and load all skills from a directory. Returns count loaded.""" loader = SkillLoader(skills_dir) for skill in loader.load_all(): self.register(skill) return len(self._skills) def get_catalog(self) -> str: """Return a catalog of available skills for the system prompt.""" if not self._skills: return "" lines = ["## Available Skills", ""] for skill in self._skills.values(): lines.append(f"- **{skill.name}**: {skill.description or 'No description'}") lines.append("") lines.append( "To use a skill, call the `load_skill` tool with the skill name. " "The skill instructions will be injected into your context." ) return "\n".join(lines) def get_skill_context(self, name: str) -> str | None: """Get the full skill content for injection into context.""" skill = self._skills.get(name) if not skill: return None return ( f"\n" f"{skill.content}\n" f"" ) @property def skills(self) -> list[SkillInfo]: return list(self._skills.values()) def __len__(self) -> int: return len(self._skills) def __contains__(self, name: str) -> bool: return name in self._skills