diff --git a/astrbot/core/sandbox/booters/base.py b/astrbot/core/sandbox/booters/base.py index 5fd793ee7..cee5644db 100644 --- a/astrbot/core/sandbox/booters/base.py +++ b/astrbot/core/sandbox/booters/base.py @@ -21,3 +21,7 @@ class SandboxBooter: Should return a dict with `success` (bool) and `file_path` (str) keys. """ ... + + async def available(self) -> bool: + """Check if the sandbox is available.""" + ... diff --git a/astrbot/core/sandbox/booters/shipyard.py b/astrbot/core/sandbox/booters/shipyard.py index 46aa3fe53..493ad6a9c 100644 --- a/astrbot/core/sandbox/booters/shipyard.py +++ b/astrbot/core/sandbox/booters/shipyard.py @@ -61,3 +61,16 @@ class ShipyardBooter(SandboxBooter): async def upload_file(self, path: str, file_name: str) -> dict: """Upload file to sandbox""" return await self._ship.upload_file(path, file_name) + + async def available(self) -> bool: + """Check if the sandbox is available.""" + try: + ship_id = self._ship.id + data = await self._sandbox_client.client.get_ship(ship_id) + if not data: + return False + health = bool(data.get("status", 0) == 1) + return health + except Exception as e: + logger.error(f"Error checking Shipyard sandbox availability: {e}") + return False diff --git a/astrbot/core/sandbox/sandbox_client.py b/astrbot/core/sandbox/sandbox_client.py index bd6ca5ef4..65838d4df 100644 --- a/astrbot/core/sandbox/sandbox_client.py +++ b/astrbot/core/sandbox/sandbox_client.py @@ -15,6 +15,11 @@ class SandboxClient: session_id: str, booter_type: Literal["shipyard", "boxlite"] = "shipyard", ) -> SandboxBooter: + if session_id in session_booter: + booter = session_booter[session_id] + if not await booter.available(): + # rebuild + session_booter.pop(session_id, None) if session_id not in session_booter: uuid_str = uuid.uuid5(uuid.NAMESPACE_DNS, session_id).hex if booter_type == "shipyard":