不允许操作文件权限的终端组件
代码
import subprocess
from typing import Dict, Any
from lfx.custom.custom_component.component import Component
from lfx.inputs.inputs import MessageTextInput
from lfx.io import Output
from lfx.schema.data import Data
ALLOWED_COMMANDS = ["ls", "dir", "echo", "ping"]
def is_allowed(command: str) -> bool:
# 禁止危险符号
forbidden = ["&&", "||", ";", "|", "rm", "del"]
if any(f in command for f in forbidden):
return False
return any(command.strip().startswith(cmd) for cmd in ALLOWED_COMMANDS)
class TerminalTool(Component):
display_name = "Terminal Tool"
description = "Execute safe shell commands. Only supports basic commands like ls, dir, echo, ping."
icon = "terminal"
inputs = [
MessageTextInput(
name="command",
display_name="Command",
info="Command to execute (e.g., 'ls', 'echo hello')",
tool_mode=True, # ✅ 允许 Agent 调用
),
]
outputs = [
Output(
display_name="Result",
name="result",
method="run_tool",
),
]
def run_tool(self) -> Data:
command = self.command.strip()
if not is_allowed(command):
return Data(data={
"success": False,
"error": "Command not allowed",
"command": command
})
try:
result = subprocess.run(
command,
shell=True,
capture_output=True,
text=True,
timeout=10
)
return Data(data={
"success": True,
"stdout": result.stdout.strip(),
"stderr": result.stderr.strip(),
"code": result.returncode,
"command": command
})
except subprocess.TimeoutExpired:
return Data(data={
"success": False,
"error": "Timeout",
"command": command
})
except Exception as e:
return Data(data={
"success": False,
"error": str(e),
"command": command
})
# ✅ 关键:定义 Tool Schema(让 Agent 知道怎么用)
def build(self):
return {
"name": "terminal_execute",
"description": "Execute a safe shell command on the system",
"parameters": {
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "Shell command to execute (e.g., 'ls', 'echo hello')"
}
},
"required": ["command"]
},
"function": self.run_tool
}
进阶版详解。
锁定langflow当前工作目录操作文件和系统权限,终端组件
import subprocess
import os
from lfx.custom.custom_component.component import Component
from lfx.inputs.inputs import MessageTextInput
from lfx.io import Output
from lfx.schema.data import Data
# ✅ 使用 Langflow 后端当前工作目录
SAFE_ROOT = os.getcwd()
def is_safe_path(path: str) -> bool:
try:
full_path = os.path.abspath(path)
return full_path.startswith(SAFE_ROOT)
except:
return False
class TerminalTool(Component):
display_name = "Terminal Tool (Backend CWD)"
description = "Execute shell commands in backend working directory"
icon = "terminal"
inputs = [
MessageTextInput(
name="command",
display_name="Command",
info="Command to execute",
tool_mode=True,
),
]
outputs = [
Output(
display_name="Result",
name="result",
method="run_tool",
),
]
def run_tool(self) -> Data:
command = self.command.strip()
# ❌ 基础危险拦截
forbidden = ["rm -rf /", "del C:\\Windows", "shutdown", "reboot"]
if any(f in command for f in forbidden):
return Data(data={
"success": False,
"error": "Dangerous command blocked",
"command": command
})
try:
result = subprocess.run(
command,
shell=True,
cwd=SAFE_ROOT, # ✅ 后端真实目录
capture_output=True,
text=True,
timeout=10
)
return Data(data={
"success": result.returncode == 0,
"stdout": result.stdout.strip(),
"stderr": result.stderr.strip(),
"code": result.returncode,
"command": command,
"cwd": SAFE_ROOT # 👈 方便你调试
})
except subprocess.TimeoutExpired:
return Data(data={
"success": False,
"error": "Timeout",
"command": command
})
except Exception as e:
return Data(data={
"success": False,
"error": str(e),
"command": command
})
def build(self):
return {
"name": "terminal_execute",
"description": "Execute shell commands in backend working directory",
"parameters": {
"type": "object",
"properties": {
"command": {"type": "string"}
},
"required": ["command"]
},
"function": self.run_tool
}