"""Shell 执行: subprocess 跑命令,有黑名单拦明显危险操作。""" from __future__ import annotations import subprocess from .base import Tool class ShellTool(Tool): name = "shell" description = ( "Execute a shell command and return stdout/stderr/exit_code. " "Default 60s timeout. Working directory is the agent's base dir." ) parameters = { "type": "object", "properties": { "command": {"type": "string"}, "timeout": {"type": "integer", "default": 60, "description": "Seconds before kill"}, }, "required": ["command"], } BLOCKED_PATTERNS = ( "rm -rf /", "rm -rf ~", "rm -rf $HOME", ":(){ :|:& };:", "mkfs", "dd if=/dev/zero", "> /dev/sda", "format c:", ) def execute(self, command: str, timeout: int = 60) -> str: normalized = command.lower() for pat in self.BLOCKED_PATTERNS: if pat in normalized: return f"[Error] blocked dangerous command pattern: {pat!r}" try: result = subprocess.run( command, shell=True, cwd=str(self.base_dir), capture_output=True, timeout=timeout, text=True, encoding="utf-8", errors="replace", ) except subprocess.TimeoutExpired: return f"[Error] command timed out after {timeout}s" except FileNotFoundError as e: return f"[Error] {e}" parts = [] if result.stdout: parts.append(f"[stdout]\n{result.stdout.rstrip()}") if result.stderr: parts.append(f"[stderr]\n{result.stderr.rstrip()}") parts.append(f"[exit {result.returncode}]") return "\n".join(parts)