Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion packages/js-sdk/src/sandbox/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,11 @@ export class Commands {
cmd: string,
opts?: CommandStartOpts & { background?: boolean }
): Promise<CommandHandle | CommandResult> {
const proc = await this.start(cmd, opts)
const startOpts =
opts?.background && opts?.timeoutMs === undefined
? { ...opts, timeoutMs: 0 }
: opts
const proc = await this.start(cmd, startOpts)

return opts?.background ? proc : proc.wait()
}
Expand Down
20 changes: 14 additions & 6 deletions packages/python-sdk/e2b/sandbox_async/commands/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ async def run(
on_stdout: Optional[OutputHandler[Stdout]] = None,
on_stderr: Optional[OutputHandler[Stderr]] = None,
stdin: Optional[bool] = None,
timeout: Optional[float] = 60,
timeout: Optional[float] = None,
request_timeout: Optional[float] = None,
) -> CommandResult:
"""
Expand All @@ -158,7 +158,7 @@ async def run(
:param on_stdout: Callback for command stdout output
:param on_stderr: Callback for command stderr output
:param stdin: If `True`, the command will have a stdin stream that you can send data to using `sandbox.commands.send_stdin()`
:param timeout: Timeout for the command connection in **seconds**. Using `0` will not limit the command connection time
:param timeout: Timeout for the command connection in **seconds**. Using `0` will not limit the command connection time. Default is `60` seconds for foreground commands, `0` (no limit) for background commands
:param request_timeout: Timeout for the request in **seconds**

:return: `CommandResult` result of the command execution
Expand All @@ -176,7 +176,7 @@ async def run(
on_stdout: Optional[OutputHandler[Stdout]] = None,
on_stderr: Optional[OutputHandler[Stderr]] = None,
stdin: Optional[bool] = None,
timeout: Optional[float] = 60,
timeout: Optional[float] = None,
request_timeout: Optional[float] = None,
) -> AsyncCommandHandle:
"""
Expand All @@ -190,7 +190,7 @@ async def run(
:param on_stdout: Callback for command stdout output
:param on_stderr: Callback for command stderr output
:param stdin: If `True`, the command will have a stdin stream that you can send data to using `sandbox.commands.send_stdin()`
:param timeout: Timeout for the command connection in **seconds**. Using `0` will not limit the command connection time
:param timeout: Timeout for the command connection in **seconds**. Using `0` will not limit the command connection time. Default is `0` (no limit) for background commands
:param request_timeout: Timeout for the request in **seconds**

:return: `AsyncCommandHandle` handle to interact with the running command
Expand All @@ -207,7 +207,7 @@ async def run(
on_stdout: Optional[OutputHandler[Stdout]] = None,
on_stderr: Optional[OutputHandler[Stderr]] = None,
stdin: Optional[bool] = None,
timeout: Optional[float] = 60,
timeout: Optional[float] = None,
request_timeout: Optional[float] = None,
):
# Check version for stdin support
Expand All @@ -220,12 +220,20 @@ async def run(
# Default to `False`
stdin = stdin or False

# When timeout is not explicitly provided, default to 60s for foreground
# commands, or 0 (unlimited) for background commands so the process
# remains reachable for connect(pid)
if timeout is None:
effective_timeout = 0 if background else 60
else:
effective_timeout = timeout

proc = await self._start(
cmd,
envs,
user,
cwd,
timeout,
effective_timeout,
request_timeout,
stdin,
on_stdout=on_stdout,
Expand Down
20 changes: 14 additions & 6 deletions packages/python-sdk/e2b/sandbox_sync/commands/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def run(
on_stdout: Optional[Callable[[str], None]] = None,
on_stderr: Optional[Callable[[str], None]] = None,
stdin: Optional[bool] = None,
timeout: Optional[float] = 60,
timeout: Optional[float] = None,
request_timeout: Optional[float] = None,
) -> CommandResult:
"""
Expand All @@ -157,7 +157,7 @@ def run(
:param on_stdout: Callback for command stdout output
:param on_stderr: Callback for command stderr output
:param stdin: If `True`, the command will have a stdin stream that you can send data to using `sandbox.commands.send_stdin()`
:param timeout: Timeout for the command connection in **seconds**. Using `0` will not limit the command connection time
:param timeout: Timeout for the command connection in **seconds**. Using `0` will not limit the command connection time. Default is `60` seconds for foreground commands, `0` (no limit) for background commands
:param request_timeout: Timeout for the request in **seconds**

:return: `CommandResult` result of the command execution
Expand All @@ -175,7 +175,7 @@ def run(
on_stdout: None = None,
on_stderr: None = None,
stdin: Optional[bool] = None,
timeout: Optional[float] = 60,
timeout: Optional[float] = None,
request_timeout: Optional[float] = None,
) -> CommandHandle:
"""
Expand All @@ -187,7 +187,7 @@ def run(
:param user: User to run the command as
:param cwd: Working directory to run the command
:param stdin: If `True`, the command will have a stdin stream that you can send data to using `sandbox.commands.send_stdin()`
:param timeout: Timeout for the command connection in **seconds**. Using `0` will not limit the command connection time
:param timeout: Timeout for the command connection in **seconds**. Using `0` will not limit the command connection time. Default is `0` (no limit) for background commands
:param request_timeout: Timeout for the request in **seconds**

:return: `CommandHandle` handle to interact with the running command
Expand All @@ -204,7 +204,7 @@ def run(
on_stdout: Optional[Callable[[str], None]] = None,
on_stderr: Optional[Callable[[str], None]] = None,
stdin: Optional[bool] = None,
timeout: Optional[float] = 60,
timeout: Optional[float] = None,
request_timeout: Optional[float] = None,
):
# Check version for stdin support
Expand All @@ -217,13 +217,21 @@ def run(
# Default to `False`
stdin = stdin or False

# When timeout is not explicitly provided, default to 60s for foreground
# commands, or 0 (unlimited) for background commands so the process
# remains reachable for connect(pid)
if timeout is None:
effective_timeout = 0 if background else 60
Comment on lines +223 to +224
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve explicit timeout=None for Python foreground runs

This branch now rewrites every timeout=None call to 60 when background is false, so commands.run(..., timeout=None) no longer disables the command-stream deadline. That is a public API regression, and it also changes existing internal callers such as packages/python-sdk/e2b/sandbox_sync/git.py:_run_git and packages/python-sdk/e2b/sandbox_async/git.py:_run_git, which default timeout to None and forward it directly. Slow git clone/fetch/push operations that previously had no command timeout will now start failing with TimeoutException after 60 seconds. If the goal is only to special-case omitted timeouts for background commands, this needs a separate sentinel instead of treating explicit None as “use default”.

Useful? React with 👍 / 👎.

else:
effective_timeout = timeout

proc = self._start(
cmd,
envs,
user,
cwd,
stdin,
timeout,
effective_timeout,
request_timeout,
)

Expand Down