from __future__ import annotations import re from dataclasses import dataclass from pathlib import Path PROFILE_ID_RE = re.compile(r"^[a-z0-9][a-z0-9_-]{0,63}$") @dataclass(frozen=True) class AgentProfile: id: str name: str class InvalidAgentId(ValueError): pass class UnknownAgent(ValueError): pass class ProfileDiscovery: def __init__(self, profiles_dir: str | Path = "Hermes/profiles") -> None: self.profiles_dir = Path(profiles_dir) def list_agents(self) -> list[AgentProfile]: if not self.profiles_dir.exists(): return [] agents: list[AgentProfile] = [] for child in sorted(self.profiles_dir.iterdir(), key=lambda item: item.name): if child.is_dir() and PROFILE_ID_RE.fullmatch(child.name): agents.append(AgentProfile(id=child.name, name=child.name)) return agents def validate_agent_id(self, agent_id: str) -> str: if not PROFILE_ID_RE.fullmatch(agent_id): raise InvalidAgentId("Invalid agent_id.") path = (self.profiles_dir / agent_id).resolve() root = self.profiles_dir.resolve() if path.parent != root or not path.is_dir(): raise UnknownAgent("Unknown agent_id.") return agent_id