from __future__ import annotations from typing import TYPE_CHECKING, Any from yuxi.utils.logging_config import logger if TYPE_CHECKING: from nio import AsyncClient class ACPBinding: def __init__( self, room_id: str, thread_root: str, acp_session_id: str = "", bind_mode: str = "thread", ): self.room_id = room_id self.thread_root = thread_root self.acp_session_id = acp_session_id self.bind_mode = bind_mode self.bound = False async def spawn(self, client: AsyncClient) -> dict[str, Any]: self.bound = True logger.info(f"ACP session spawned: {self.acp_session_id} -> {self.thread_root}") return { "status": "spawned", "room_id": self.room_id, "thread_root": self.thread_root, "acp_session_id": self.acp_session_id, } async def bind(self, client: AsyncClient) -> dict[str, Any]: if self.bound: return {"status": "already_bound", "room_id": self.room_id} self.bound = True logger.info(f"ACP session bound: {self.acp_session_id} -> {self.thread_root}") return {"status": "bound", "room_id": self.room_id, "thread_root": self.thread_root} async def unbind(self) -> dict[str, Any]: self.bound = False return {"status": "unbound", "room_id": self.room_id} def to_dict(self) -> dict[str, Any]: return { "room_id": self.room_id, "thread_root": self.thread_root, "acp_session_id": self.acp_session_id, "bind_mode": self.bind_mode, "bound": self.bound, } class ACPBindingManager: def __init__(self, config: dict[str, Any]): self._config = config self._bindings: dict[str, ACPBinding] = {} def create_binding(self, room_id: str, thread_root: str, session_id: str = "", mode: str = "thread") -> ACPBinding: key = f"{room_id}:{thread_root}" if thread_root else room_id if key in self._bindings: return self._bindings[key] binding = ACPBinding( room_id=room_id, thread_root=thread_root, acp_session_id=session_id, bind_mode=mode, ) self._bindings[key] = binding return binding def get(self, room_id: str, thread_root: str = "") -> ACPBinding | None: key = f"{room_id}:{thread_root}" if thread_root else room_id return self._bindings.get(key) def remove(self, room_id: str, thread_root: str = "") -> bool: key = f"{room_id}:{thread_root}" if thread_root else room_id if key in self._bindings: del self._bindings[key] return True return False def list_bindings(self) -> list[ACPBinding]: return list(self._bindings.values()) @property def binding_count(self) -> int: return len(self._bindings)