fix: use shell fallback instead of hardcoded /bin/zsh in LocalSandbox (#939)

* fix: use shell fallback instead of hardcoded /bin/zsh in LocalSandbox

Replace hardcoded /bin/zsh executable with dynamic shell detection
that falls back through /bin/zsh → /bin/bash → /bin/sh. This fixes
skill execution failures in Docker containers (python:3.12-slim)
where zsh is not available.

Closes #935

* Update backend/src/sandbox/local/local_sandbox.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: atian8179 <atian8179@users.noreply.github.com>
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
atian8179
2026-03-01 22:08:07 +08:00
committed by GitHub
parent 8c6dd9e264
commit d728bb26d5

View File

@@ -1,4 +1,5 @@
import os
import shutil
import subprocess
from pathlib import Path
@@ -132,13 +133,32 @@ class LocalSandbox(Sandbox):
return pattern.sub(replace_match, command)
@staticmethod
def _get_shell() -> str:
"""Detect available shell executable with fallback.
Returns the first available shell in order of preference:
/bin/zsh → /bin/bash → /bin/sh → first `sh` found on PATH.
Raises a RuntimeError if no suitable shell is found.
"""
for shell in ("/bin/zsh", "/bin/bash", "/bin/sh"):
if os.path.isfile(shell) and os.access(shell, os.X_OK):
return shell
shell_from_path = shutil.which("sh")
if shell_from_path is not None:
return shell_from_path
raise RuntimeError(
"No suitable shell executable found. Tried /bin/zsh, /bin/bash, "
"/bin/sh, and `sh` on PATH."
)
def execute_command(self, command: str) -> str:
# Resolve container paths in command before execution
resolved_command = self._resolve_paths_in_command(command)
result = subprocess.run(
resolved_command,
executable="/bin/zsh",
executable=self._get_shell(),
shell=True,
capture_output=True,
text=True,