Skip to content

Commit f8ada9a

Browse files
refactor: remove init parameter from class ToolExecutor.
1 parent b034737 commit f8ada9a

File tree

7 files changed

+33
-37
lines changed

7 files changed

+33
-37
lines changed

apps/application/chat_pipeline/step/chat_step/impl/base_chat_step.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ def _handle_mcp_request(self, mcp_enable, tool_enable, mcp_source, mcp_servers,
253253
tool = QuerySet(Tool).filter(id=tool_id).first()
254254
if tool is None or tool.is_active is False:
255255
continue
256-
executor = ToolExecutor(CONFIG.get('SANDBOX'))
256+
executor = ToolExecutor()
257257
if tool.init_params is not None:
258258
params = json.loads(rsa_long_decrypt(tool.init_params))
259259
else:

apps/application/flow/step_node/ai_chat_step_node/impl/base_chat_node.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ def _handle_mcp_request(self, mcp_enable, tool_enable, mcp_source, mcp_servers,
237237
tool = QuerySet(Tool).filter(id=tool_id).first()
238238
if not tool.is_active:
239239
continue
240-
executor = ToolExecutor(CONFIG.get('SANDBOX'))
240+
executor = ToolExecutor()
241241
if tool.init_params is not None:
242242
params = json.loads(rsa_long_decrypt(tool.init_params))
243243
else:

apps/application/flow/step_node/tool_lib_node/impl/base_tool_lib_node.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from maxkb.const import CONFIG
2323
from tools.models import Tool
2424

25-
function_executor = ToolExecutor(CONFIG.get('SANDBOX'))
25+
function_executor = ToolExecutor()
2626

2727

2828
def write_context(step_variable: Dict, global_variable: Dict, node, workflow):

apps/application/flow/step_node/tool_node/impl/base_tool_node.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from common.utils.tool_code import ToolExecutor
1818
from maxkb.const import CONFIG
1919

20-
function_executor = ToolExecutor(CONFIG.get('SANDBOX'))
20+
function_executor = ToolExecutor()
2121

2222

2323
def write_context(step_variable: Dict, global_variable: Dict, node, workflow):

apps/common/utils/tool_code.py

Lines changed: 27 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,21 @@
1919
from maxkb.const import PROJECT_DIR
2020
from textwrap import dedent
2121

22-
class ToolExecutor:
22+
_enable_sandbox = bool(CONFIG.get('SANDBOX', 0))
23+
_run_user = 'sandbox' if _enable_sandbox else getpass.getuser()
24+
_sandbox_path = CONFIG.get("SANDBOX_HOME", '/opt/maxkb-app/sandbox') if _enable_sandbox else os.path.join(PROJECT_DIR, 'data', 'sandbox')
25+
_process_limit_timeout_seconds = int(CONFIG.get("SANDBOX_PYTHON_PROCESS_LIMIT_TIMEOUT_SECONDS", '3600'))
26+
_process_limit_cpu_cores = min(max(int(CONFIG.get("SANDBOX_PYTHON_PROCESS_LIMIT_CPU_CORES", '1')), 1), len(os.sched_getaffinity(0))) if sys.platform.startswith("linux") else os.cpu_count() # 只支持linux,window和mac不支持
27+
_process_limit_mem_mb = int(CONFIG.get("SANDBOX_PYTHON_PROCESS_LIMIT_MEM_MB", '256'))
2328

24-
enable_sandbox = bool(CONFIG.get('SANDBOX', 0))
25-
sandbox_path = CONFIG.get("SANDBOX_HOME", '/opt/maxkb-app/sandbox') if enable_sandbox else os.path.join(PROJECT_DIR, 'data', 'sandbox')
26-
process_timeout_seconds = int(CONFIG.get("SANDBOX_PYTHON_PROCESS_TIMEOUT_SECONDS", '3600'))
27-
process_limit_mem_mb = int(CONFIG.get("SANDBOX_PYTHON_PROCESS_LIMIT_MEM_MB", '256'))
28-
process_limit_cpu_cores = min(max(int(CONFIG.get("SANDBOX_PYTHON_PROCESS_LIMIT_CPU_CORES", '1')), 1), len(os.sched_getaffinity(0))) if sys.platform.startswith("linux") else os.cpu_count() # 只支持linux,window和mac不支持
29+
class ToolExecutor:
2930

30-
def __init__(self, sandbox=False):
31-
self.sandbox = sandbox
32-
if sandbox:
33-
self.user = 'sandbox'
34-
else:
35-
self.user = getpass.getuser()
31+
def __init__(self):
32+
pass
3633

3734
@staticmethod
3835
def init_sandbox_dir():
39-
if not ToolExecutor.enable_sandbox:
36+
if not _enable_sandbox:
4037
# 不启用sandbox就不初始化目录
4138
return
4239
try:
@@ -57,7 +54,7 @@ def init_sandbox_dir():
5754
if CONFIG.get("SANDBOX_TMP_DIR_ENABLED", '0') == "1":
5855
os.system("chmod g+rwx /tmp")
5956
# 初始化sandbox配置文件
60-
sandbox_lib_path = os.path.dirname(f'{ToolExecutor.sandbox_path}/lib/sandbox.so')
57+
sandbox_lib_path = os.path.dirname(f'{_sandbox_path}/lib/sandbox.so')
6158
sandbox_conf_file_path = f'{sandbox_lib_path}/.sandbox.conf'
6259
if os.path.exists(sandbox_conf_file_path):
6360
os.remove(sandbox_conf_file_path)
@@ -70,16 +67,20 @@ def init_sandbox_dir():
7067
with open(sandbox_conf_file_path, "w") as f:
7168
f.write(f"SANDBOX_PYTHON_BANNED_HOSTS={banned_hosts}\n")
7269
f.write(f"SANDBOX_PYTHON_ALLOW_SUBPROCESS={allow_subprocess}\n")
73-
os.system(f"chmod -R 550 {ToolExecutor.sandbox_path}")
70+
os.system(f"chmod -R 550 {_sandbox_path}")
7471

72+
try:
73+
init_sandbox_dir()
74+
except Exception as e:
75+
maxkb_logger.error(f'Exception: {e}', exc_info=True)
7576

7677
def exec_code(self, code_str, keywords, function_name=None):
7778
_id = str(uuid.uuid7())
7879
success = '{"code":200,"msg":"成功","data":exec_result}'
7980
err = '{"code":500,"msg":str(e),"data":None}'
8081
action_function = f'({function_name !a}, locals_v.get({function_name !a}))' if function_name else 'locals_v.popitem()'
8182
python_paths = CONFIG.get_sandbox_python_package_paths().split(',')
82-
set_run_user = f'os.setgid({pwd.getpwnam(self.user).pw_gid});os.setuid({pwd.getpwnam(self.user).pw_uid});' if self.sandbox else ''
83+
set_run_user = f'os.setgid({pwd.getpwnam(_run_user).pw_gid});os.setuid({pwd.getpwnam(_run_user).pw_uid});' if _enable_sandbox else ''
8384
_exec_code = f"""
8485
try:
8586
import os, sys, json, base64, builtins
@@ -98,7 +99,7 @@ def exec_code(self, code_str, keywords, function_name=None):
9899
exec_result=f(**keywords)
99100
builtins.print("\\n{_id}:"+base64.b64encode(json.dumps({success}, default=str).encode()).decode(), flush=True)
100101
except Exception as e:
101-
if isinstance(e, MemoryError): e = Exception("Cannot allocate more memory: exceeded the limit of {ToolExecutor.process_limit_mem_mb} MB.")
102+
if isinstance(e, MemoryError): e = Exception("Cannot allocate more memory: exceeded the limit of {_process_limit_mem_mb} MB.")
102103
builtins.print("\\n{_id}:"+base64.b64encode(json.dumps({err}, default=str).encode()).decode(), flush=True)
103104
"""
104105
maxkb_logger.debug(f"Sandbox execute code: {_exec_code}")
@@ -184,7 +185,7 @@ def _generate_mcp_server_code(self, _code, params):
184185
def generate_mcp_server_code(self, code_str, params):
185186
python_paths = CONFIG.get_sandbox_python_package_paths().split(',')
186187
code = self._generate_mcp_server_code(code_str, params)
187-
set_run_user = f'os.setgid({pwd.getpwnam(self.user).pw_gid});os.setuid({pwd.getpwnam(self.user).pw_uid});' if self.sandbox else ''
188+
set_run_user = f'os.setgid({pwd.getpwnam(_run_user).pw_gid});os.setuid({pwd.getpwnam(_run_user).pw_uid});' if _enable_sandbox else ''
188189
return f"""
189190
import os, sys, logging
190191
logging.basicConfig(level=logging.WARNING)
@@ -208,41 +209,36 @@ def get_tool_mcp_config(self, code, params):
208209
'-c',
209210
f'import base64,gzip; exec(gzip.decompress(base64.b64decode(\'{compressed_and_base64_encoded_code_str}\')).decode())',
210211
],
211-
'cwd': ToolExecutor.sandbox_path,
212+
'cwd': _sandbox_path,
212213
'env': {
213-
'LD_PRELOAD': f'{ToolExecutor.sandbox_path}/lib/sandbox.so',
214+
'LD_PRELOAD': f'{_sandbox_path}/lib/sandbox.so',
214215
},
215216
'transport': 'stdio',
216217
}
217218
return tool_config
218219

219220
def _exec(self, execute_file):
220221
kwargs = {'cwd': BASE_DIR, 'env': {
221-
'LD_PRELOAD': f'{ToolExecutor.sandbox_path}/lib/sandbox.so',
222+
'LD_PRELOAD': f'{_sandbox_path}/lib/sandbox.so',
222223
}}
223224
try:
224225
subprocess_result = subprocess.run(
225226
[sys.executable, execute_file],
226-
timeout=ToolExecutor.process_timeout_seconds,
227+
timeout=_process_limit_timeout_seconds,
227228
text=True,
228229
capture_output=True,
229230
**kwargs,
230-
preexec_fn=(lambda: None if (not self.sandbox or not sys.platform.startswith("linux")) else (
231-
resource.setrlimit(resource.RLIMIT_AS, (ToolExecutor.process_limit_mem_mb * 1024 * 1024,) * 2),
232-
os.sched_setaffinity(0, set(random.sample(list(os.sched_getaffinity(0)), ToolExecutor.process_limit_cpu_cores)))
231+
preexec_fn=(lambda: None if (not _enable_sandbox or not sys.platform.startswith("linux")) else (
232+
resource.setrlimit(resource.RLIMIT_AS, (_process_limit_mem_mb * 1024 * 1024,) * 2),
233+
os.sched_setaffinity(0, set(random.sample(list(os.sched_getaffinity(0)), _process_limit_cpu_cores)))
233234
))
234235
)
235236
return subprocess_result
236237
except subprocess.TimeoutExpired:
237-
raise Exception(_(f"Process execution timed out after {ToolExecutor.process_timeout_seconds} seconds."))
238+
raise Exception(_(f"Process execution timed out after {_process_limit_timeout_seconds} seconds."))
238239

239240
def validate_mcp_transport(self, code_str):
240241
servers = json.loads(code_str)
241242
for server, config in servers.items():
242243
if config.get('transport') not in ['sse', 'streamable_http']:
243244
raise Exception(_('Only support transport=sse or transport=streamable_http'))
244-
245-
try:
246-
ToolExecutor.init_sandbox_dir()
247-
except Exception as e:
248-
maxkb_logger.error(f'Exception: {e}', exc_info=True)

apps/knowledge/serializers/knowledge_workflow.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
from tools.models import Tool
2929
from users.models import User
3030

31-
tool_executor = ToolExecutor(CONFIG.get('SANDBOX'))
31+
tool_executor = ToolExecutor()
3232

3333

3434
class KnowledgeWorkflowModelSerializer(serializers.ModelSerializer):

apps/tools/serializers/tool.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
from tools.models import Tool, ToolScope, ToolFolder, ToolType
3939
from users.serializers.user import is_workspace_manage
4040

41-
tool_executor = ToolExecutor(CONFIG.get('SANDBOX'))
41+
tool_executor = ToolExecutor()
4242

4343

4444
class ToolInstance:

0 commit comments

Comments
 (0)