@@ -82,14 +82,31 @@ async def initialize(self):
8282 )
8383
8484 # Setting the directory
85- resp = await self ._send_instruction_post (
86- command = CommandsInterpreter .SET_DIRECTORY ,
87- key = "directory" ,
88- data = self .directory ,
85+ # NOTE: the sandbox HTTP server may not be ready immediately after the
86+ # process starts, so we add a small retry loop here to avoid transient
87+ # "connection refused" errors that surface as tool failures like:
88+ # "Error executing tool: CommandsInterpreter.SET_DIRECTORY".
89+ last_exc : Exception | None = None
90+ for attempt in range (5 ):
91+ try :
92+ resp = await self ._send_instruction_post (
93+ command = CommandsInterpreter .SET_DIRECTORY ,
94+ key = "directory" ,
95+ data = self .directory ,
96+ )
97+ print (resp )
98+ return resp
99+ except aiohttp .ClientError as exc : # type: ignore[attr-defined]
100+ last_exc = exc
101+ # Back off slightly between attempts to give the server time to boot
102+ await asyncio .sleep (0.2 * (attempt + 1 ))
103+
104+ # If we got here, all attempts failed – raise a clear, high-level error
105+ raise RuntimeError (
106+ f"Failed to reach Python sandbox at { str (CommandsInterpreter .SET_DIRECTORY )} "
107+ f"after 5 attempts. Last error: { last_exc !r} "
89108 )
90109
91- return resp
92-
93110 async def load_packages (self , packages : list [str ]):
94111 """Request package installation inside the sandbox.
95112
@@ -132,7 +149,7 @@ async def run_code(self, code: str):
132149 """Execute inline Python code in the sandbox (not implemented)."""
133150 raise NotImplementedError
134151
135- async def _send_instruction_post (self , command : str , key : str , data : Any ):
152+ async def _send_instruction_post (self , command : str | CommandsInterpreter , key : str , data : Any ):
136153 """Send a JSON POST request to the sandbox.
137154
138155 Args:
@@ -143,8 +160,15 @@ async def _send_instruction_post(self, command: str, key: str, data: Any):
143160 Returns:
144161 Any: Parsed JSON response.
145162 """
163+ # Explicitly convert Enum to string for aiohttp compatibility
164+ # Using .value for Enums ensures we get the actual string value
165+ # This is necessary for Python 3.10 compatibility (StrEnum is 3.11+)
166+ if isinstance (command , Enum ):
167+ url = command .value
168+ else :
169+ url = str (command )
146170 async with aiohttp .ClientSession () as session :
147- async with session .post (url = command , json = {key : data }) as resp :
171+ async with session .post (url = url , json = {key : data }) as resp :
148172 return await resp .json ()
149173
150174 async def shutdown (self , timeout : float = 5.0 ):
0 commit comments