| import os |
| import uuid |
| from dataclasses import dataclass, field |
| from threading import Lock |
|
|
| from dotenv import load_dotenv |
|
|
| load_dotenv() |
|
|
| from biomni_agent import BiomniWebAgent |
|
|
| DEFAULT_LLM_PROVIDER = os.getenv("BIOMNI_LLM_PROVIDER", "deepseek").strip().lower() |
|
|
|
|
| @dataclass |
| class SessionState: |
| agent: BiomniWebAgent | None = None |
| uploaded_files: list[str] = field(default_factory=list) |
| metabolomics_enabled: bool = False |
| metabolomics_tools: list[str] = field(default_factory=list) |
| paper_repro_enabled: bool = False |
| paper_profile: str = "foxj1" |
| stop_requested: bool = False |
| llm_provider: str = field(default_factory=lambda: DEFAULT_LLM_PROVIDER) |
|
|
|
|
| def _create_agent( |
| session_id: str, |
| expected_files: list[str] | None = None, |
| llm_provider: str = DEFAULT_LLM_PROVIDER, |
| ) -> BiomniWebAgent: |
| return BiomniWebAgent( |
| session_id=session_id, |
| expected_data_lake_files=expected_files or [], |
| llm_provider=llm_provider, |
| ) |
|
|
|
|
| class SessionManager: |
| def __init__(self): |
| self._sessions: dict[str, SessionState] = {} |
| self._lock = Lock() |
|
|
| def create_session(self, llm_provider: str = DEFAULT_LLM_PROVIDER) -> str: |
| sid = str(uuid.uuid4()) |
| with self._lock: |
| |
| self._sessions[sid] = SessionState( |
| llm_provider=(llm_provider or DEFAULT_LLM_PROVIDER).strip().lower() |
| ) |
| return sid |
|
|
| def has_session(self, sid: str) -> bool: |
| return sid in self._sessions |
|
|
| def get_agent(self, sid: str) -> BiomniWebAgent: |
| |
| with self._lock: |
| state = self._sessions[sid] |
| if state.agent is not None: |
| return state.agent |
| expected_files = list(state.uploaded_files) |
| llm_provider = state.llm_provider |
|
|
| |
| new_agent = _create_agent(sid, expected_files=expected_files, llm_provider=llm_provider) |
| if expected_files: |
| new_agent.set_uploaded_files(expected_files) |
| new_agent.set_metabolomics_settings(state.metabolomics_enabled, state.metabolomics_tools) |
| new_agent.set_paper_reproduction_settings(state.paper_repro_enabled, state.paper_profile) |
|
|
| |
| with self._lock: |
| state = self._sessions.get(sid) |
| if state is None: |
| raise KeyError(f"Session not found: {sid}") |
| if state.agent is None: |
| state.agent = new_agent |
| return state.agent |
|
|
| def add_uploaded_file(self, sid: str, relative_path: str): |
| with self._lock: |
| state = self._sessions[sid] |
| if relative_path not in state.uploaded_files: |
| state.uploaded_files.append(relative_path) |
| if state.agent is not None: |
| state.agent.set_uploaded_files(state.uploaded_files) |
|
|
| def set_metabolomics_settings(self, sid: str, enabled: bool, tools: list[str]): |
| with self._lock: |
| state = self._sessions[sid] |
| state.metabolomics_enabled = bool(enabled) |
| state.metabolomics_tools = sorted(set(tools)) |
| if state.agent is not None: |
| state.agent.set_metabolomics_settings(state.metabolomics_enabled, state.metabolomics_tools) |
|
|
| def set_llm_provider(self, sid: str, llm_provider: str): |
| normalized = (llm_provider or DEFAULT_LLM_PROVIDER).strip().lower() |
| with self._lock: |
| state = self._sessions[sid] |
| if state.llm_provider == normalized: |
| return |
| state.llm_provider = normalized |
| |
| state.agent = None |
|
|
| def request_stop(self, sid: str) -> None: |
| with self._lock: |
| state = self._sessions[sid] |
| state.stop_requested = True |
| if state.agent is not None: |
| state.agent.request_cancel() |
|
|
| def clear_stop(self, sid: str) -> None: |
| with self._lock: |
| state = self._sessions[sid] |
| state.stop_requested = False |
| if state.agent is not None: |
| state.agent.clear_cancel_request() |
|
|
| def is_stop_requested(self, sid: str) -> bool: |
| with self._lock: |
| state = self._sessions[sid] |
| return bool(state.stop_requested) |
|
|
| def set_paper_reproduction_settings(self, sid: str, enabled: bool, profile: str = "foxj1"): |
| normalized_profile = (profile or "foxj1").strip().lower() |
| with self._lock: |
| state = self._sessions[sid] |
| state.paper_repro_enabled = bool(enabled) |
| state.paper_profile = normalized_profile |
| if state.agent is not None: |
| state.agent.set_paper_reproduction_settings(state.paper_repro_enabled, state.paper_profile) |
|
|
| def get_uploaded_files(self, sid: str) -> list[str]: |
| with self._lock: |
| return list(self._sessions[sid].uploaded_files) |
|
|
| def delete_session(self, sid: str): |
| with self._lock: |
| self._sessions.pop(sid, None) |
|
|
| def cleanup_all(self): |
| with self._lock: |
| self._sessions.clear() |
|
|