registry.py 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. from __future__ import annotations
  2. from pathlib import Path
  3. from supply_agent.skills.loader import SkillLoader
  4. from supply_agent.types import SkillInfo
  5. class SkillRegistry:
  6. """Registry for managing agent skills (specialized instruction sets)."""
  7. def __init__(self, skills_dir: Path | str | None = None) -> None:
  8. self._skills: dict[str, SkillInfo] = {}
  9. if skills_dir:
  10. self.load_from_directory(skills_dir)
  11. def register(self, skill: SkillInfo) -> None:
  12. self._skills[skill.name] = skill
  13. def unregister(self, name: str) -> None:
  14. self._skills.pop(name, None)
  15. def get(self, name: str) -> SkillInfo | None:
  16. return self._skills.get(name)
  17. def list_skills(self) -> list[str]:
  18. return list(self._skills.keys())
  19. def load_from_directory(self, skills_dir: Path | str) -> int:
  20. """Discover and load all skills from a directory. Returns count loaded."""
  21. loader = SkillLoader(skills_dir)
  22. for skill in loader.load_all():
  23. self.register(skill)
  24. return len(self._skills)
  25. def get_catalog(self) -> str:
  26. """Return a catalog of available skills for the system prompt."""
  27. if not self._skills:
  28. return ""
  29. lines = ["## Available Skills", ""]
  30. for skill in self._skills.values():
  31. lines.append(f"- **{skill.name}**: {skill.description or 'No description'}")
  32. lines.append("")
  33. lines.append(
  34. "To use a skill, call the `load_skill` tool with the skill name. "
  35. "The skill instructions will be injected into your context."
  36. )
  37. return "\n".join(lines)
  38. def get_skill_context(self, name: str) -> str | None:
  39. """Get the full skill content for injection into context."""
  40. skill = self._skills.get(name)
  41. if not skill:
  42. return None
  43. return (
  44. f"<skill name=\"{skill.name}\">\n"
  45. f"{skill.content}\n"
  46. f"</skill>"
  47. )
  48. @property
  49. def skills(self) -> list[SkillInfo]:
  50. return list(self._skills.values())
  51. def __len__(self) -> int:
  52. return len(self._skills)
  53. def __contains__(self, name: str) -> bool:
  54. return name in self._skills