feat: Separate timeouts for code exec and output (#739)
The Master committed
Sep 25, 2025 at 14:11 UTC
bc980a21a119b69be5528eac0bee04dd03b6f58d
1 file changed
+27
-3
python/tools/code_execution_tool.py
+27
-3
@@ -13,6 +13,22 @@ from python.helpers.messages import truncate_text as truncate_text_agent
13
import re
14
15
16
+# Timeouts for python, nodejs, and terminal runtimes.
17
+CODE_EXEC_TIMEOUTS: dict[str, int] = {
18
+ "first_output_timeout": 30,
19
+ "between_output_timeout": 15,
20
+ "max_exec_timeout": 180,
21
+ "dialog_timeout": 5,
22
+}
23
+
24
+# Timeouts for output runtime.
25
+OUTPUT_TIMEOUTS: dict[str, int] = {
26
+ "first_output_timeout": 90,
27
+ "between_output_timeout": 45,
28
+ "max_exec_timeout": 300,
29
+ "dialog_timeout": 5,
30
+}
31
+
32
@dataclass
33
class State:
34
ssh_enabled: bool
@@ -42,7 +58,7 @@ class CodeExecution(Tool):
58
)
59
elif runtime == "output":
60
response = await self.get_terminal_output(
45
- session=session, first_output_timeout=60, between_output_timeout=5
61
+ session=session, timeouts=OUTPUT_TIMEOUTS
62
)
63
elif runtime == "reset":
64
response = await self.reset_terminal(session=session)
@@ -139,7 +155,7 @@ class CodeExecution(Tool):
155
return await self.terminal_session(session, command, reset, prefix)
156
157
async def terminal_session(
142
- self, session: int, command: str, reset: bool = False, prefix: str = ""
158
+ self, session: int, command: str, reset: bool = False, prefix: str = "", timeouts: dict | None = None
159
):
160
161
self.state = await self.prepare_state(reset=reset, session=session)
@@ -164,7 +180,7 @@ class CodeExecution(Tool):
180
PrintStyle(
181
background_color="white", font_color="#1B4F72", bold=True
182
).print(f"{self.agent.agent_name} code execution output{locl}")
167
- return await self.get_terminal_output(session=session, prefix=prefix)
183
+ return await self.get_terminal_output(session=session, prefix=prefix, timeouts=(timeouts or CODE_EXEC_TIMEOUTS))
184
185
except Exception as e:
186
if i == 1:
@@ -196,11 +212,19 @@ class CodeExecution(Tool):
212
max_exec_timeout=180, # hard cap on total runtime
213
sleep_time=0.1,
214
prefix="",
215
+ timeouts: dict | None = None,
216
):
217
218
# if not self.state:
219
self.state = await self.prepare_state(session=session)
220
221
+ # Override timeouts if a dict is provided
222
+ if timeouts:
223
+ first_output_timeout = timeouts.get("first_output_timeout", first_output_timeout)
224
+ between_output_timeout = timeouts.get("between_output_timeout", between_output_timeout)
225
+ dialog_timeout = timeouts.get("dialog_timeout", dialog_timeout)
226
+ max_exec_timeout = timeouts.get("max_exec_timeout", max_exec_timeout)
227
+
228
# Common shell prompt regex patterns (add more as needed)
229
prompt_patterns = [
230
re.compile(r"\(venv\).+[$#] ?$"), # (venv) ...$ or (venv) ...#