from __future__ import annotations import os import subprocess from pathlib import Path class ToolSandbox: """Applies simple working directory and timeout restrictions.""" def __init__(self, allowed_root: str | Path, timeout_ms: int) -> None: self._allowed_root = Path(allowed_root).resolve() self._timeout_seconds = max(timeout_ms / 1000, 1) def ensure_path_allowed(self, path: str | Path) -> Path: resolved = Path(path).expanduser().resolve() # Permission-first model: path is allowed if it exists # Permission service will handle write/shell restrictions return resolved def run_shell( self, command: str, cwd: str | Path | None = None, stdin_data: str | None = None, ) -> subprocess.CompletedProcess[str]: working_directory = self.ensure_path_allowed(cwd or self._allowed_root) env = {"PATH": os.environ.get("PATH", "")} return subprocess.run( command, shell=True, cwd=str(working_directory), env=env, text=True, capture_output=True, input=stdin_data, timeout=self._timeout_seconds, check=False, )