# registry.py — Static agent adapter registry and resolution functions (N4 & N5) from typing import Optional, Dict, Any from lib_py.agents.base import BaseAgentAdapter from lib_py.agents.adapters.claude import ClaudeAgentAdapter from lib_py.agents.adapters.agy import AgyAgentAdapter from lib_py.agents.adapters.hermes import HermesAgentAdapter from lib_py.agents.adapters.cline import ClineAgentAdapter _ADAPTERS: Dict[str, BaseAgentAdapter] = { 'claude': ClaudeAgentAdapter(), 'agy': AgyAgentAdapter(), 'hermes': HermesAgentAdapter(), 'cline': ClineAgentAdapter(), } def get_adapter(agent_name: str) -> Optional[BaseAgentAdapter]: if not agent_name: return None return _ADAPTERS.get(agent_name.lower()) def own_key(agent_name: str) -> Optional[str]: adapter = get_adapter(agent_name) return adapter.own_key if adapter else None def agent_of_row(row: Dict[str, Any], session_name: str = "", match_cmd: bool = True) -> Optional[str]: """ Resolves agent for a given registry row or session name using strict priority order (N5): 1. Explicit 'agent' field in row dictionary 2. Session name suffix matching (*-{creator,planner,reviewer}- or *-) 3. pane.cmd exact match (if match_cmd is True, e.g. for non-adoption lookup) 4. None (resolution failure) """ if isinstance(row, dict): explicit = row.get('agent') if explicit and str(explicit).lower() in _ADAPTERS: return str(explicit).lower() if not session_name: session_name = row.get('name', '') name = session_name or (row.get('name', '') if isinstance(row, dict) else '') if name: for agent_name, adapter in _ADAPTERS.items(): if adapter.matches_session_name(name): return agent_name if match_cmd and isinstance(row, dict): pane = row.get('pane') or {} cmd = pane.get('cmd', '') if isinstance(pane, dict) else '' if cmd: for agent_name in _ADAPTERS: if cmd == agent_name or cmd.endswith(f"/{agent_name}"): return agent_name return None