머니페니 76e3220e77
All checks were successful
Deploy to Production / deploy (push) Successful in 3m10s
feat: 에이전트 기능 추가 (LLM 서비스, 에이전트 API, 테스트)
2026-05-06 20:56:45 +09:00

53 lines
1.7 KiB
Python

from __future__ import annotations
from pathlib import Path
from app.agents.skills.loader import SkillLoader
from app.agents.skills.types import Skill, SkillMetadata
class SkillRegistry:
"""builtin 스킬 탐색 및 캐싱."""
BUILTIN_DIR: Path = Path(__file__).parent / "builtin"
_cache: dict[str, SkillMetadata] = {}
@classmethod
def discover(cls) -> list[SkillMetadata]:
"""BUILTIN_DIR 하위의 */SKILL.md 패턴을 스캔하여 메타데이터 캐싱."""
cls._cache.clear()
for skill_file in sorted(cls.BUILTIN_DIR.glob("*/SKILL.md")):
meta = SkillLoader.extract_metadata(skill_file, "builtin")
if meta.name:
cls._cache[meta.name] = meta
return list(cls._cache.values())
@classmethod
def get(cls, name: str) -> Skill | None:
"""캐시에서 이름으로 조회 후 전체 Skill(instructions 포함) 로드."""
if not cls._cache:
cls.discover()
meta = cls._cache.get(name)
if meta is None:
return None
return SkillLoader.load_from_path(meta.path, meta.source)
@classmethod
def list_skills(cls) -> list[SkillMetadata]:
return list(cls._cache.values())
@classmethod
def build_skills_section(cls) -> str:
"""시스템 프롬프트에 삽입할 스킬 목록 텍스트 생성."""
skills = cls.list_skills()
if not skills:
return ""
lines = ["## 사용 가능한 스킬\n"]
for s in skills:
lines.append(f"- **{s.name}**: {s.description}")
return "\n".join(lines)
@classmethod
def clear_cache(cls) -> None:
cls._cache.clear()