import asyncio import base64 import logging from pathlib import Path from typing import Any from app.bots.assistant import AssistantRuntime from app.config import Settings from app.storage.hf_dataset import HFDataStore class SessionManager: def __init__(self, settings: Settings, store: HFDataStore) -> None: self.settings = settings self.store = store self.base_dir = Path("sessions") self.base_dir.mkdir(exist_ok=True) self._assistants: dict[str, AssistantRuntime] = {} def running_ids(self) -> list[str]: return list(self._assistants.keys()) def get_runtime(self, assistant_id: str) -> AssistantRuntime | None: return self._assistants.get(assistant_id) async def start_assistant(self, assistant_id: str, assistant_data: dict[str, Any]) -> None: if assistant_id in self._assistants: return session_b64 = assistant_data.get("session_b64", "") session_path = self.base_dir / f"{assistant_id}.session" if session_b64: try: session_path.write_bytes(base64.b64decode(session_b64.encode("utf-8"))) except Exception as exc: raise ValueError(f"Corrupted session data for assistant {assistant_id}") from exc runtime = AssistantRuntime(self.settings, self.store, assistant_id, str(session_path)) await runtime.start() self._assistants[assistant_id] = runtime async def stop_assistant(self, assistant_id: str) -> None: runtime = self._assistants.pop(assistant_id, None) if runtime: await runtime.stop() (self.base_dir / f"{assistant_id}.session").unlink(missing_ok=True) async def load_all(self) -> None: assistants = self.store.get_data().get("assistants", {}) for assistant_id, data in assistants.items(): try: await self.start_assistant(assistant_id, data) except Exception: logging.exception("Failed to start assistant %s", assistant_id) async def shutdown(self) -> None: for assistant_id in list(self._assistants.keys()): await self.stop_assistant(assistant_id)