Coverage for agentos/tools/code_agent.py: 40%
47 statements
« prev ^ index » next coverage.py v7.14.3, created at 2026-07-07 00:45 +0800
« prev ^ index » next coverage.py v7.14.3, created at 2026-07-07 00:45 +0800
1"""
2CodeAgent 工具 — Agent直接写代码执行,不输出JSON。
3基因来源: Smolagents
4核心洞察: 代码的表达力远超JSON(循环/条件/异常/变量作用域)。
5"""
7from __future__ import annotations
9import subprocess
11from agentos.tools.base import BaseTool, PermissionLevel, ToolResult
14class CodeAgentTool(BaseTool):
15 """代码执行工具 — Agent不输出JSON,直接写Python代码。"""
17 name = "execute_code"
18 description = (
19 "执行Python代码并返回结果。支持任意Python标准库。"
20 "适用场景:数据处理、文件列表、字符串操作、复杂逻辑。"
21 "返回值包含stdout/stderr/exit_code。"
22 )
23 permission_level = PermissionLevel.SENSITIVE
25 @property
26 def parameters(self) -> dict:
27 return {
28 "type": "object",
29 "properties": {
30 "code": {
31 "type": "string",
32 "description": "要执行的Python代码",
33 },
34 },
35 "required": ["code"],
36 }
38 async def execute(self, arguments: dict, sandbox=None) -> ToolResult:
39 code = arguments["code"]
41 # 如果传入了sandbox则在沙箱中执行
42 if sandbox:
43 return await sandbox.execute_code(code, "python")
45 # 默认在当前进程执行(Python环境)
46 try:
47 result = subprocess.run(
48 ["python3", "-c", code],
49 capture_output=True,
50 text=True,
51 timeout=60,
52 )
53 return ToolResult(
54 call_id="",
55 output=result.stdout,
56 error=result.stderr if result.returncode != 0 else None,
57 exit_code=result.returncode,
58 )
59 except subprocess.TimeoutExpired:
60 return ToolResult(call_id="", error="Code execution timed out (60s)")
61 except Exception as e:
62 return ToolResult(call_id="", error=str(e))
64 def is_write_operation(self, arguments: dict) -> bool:
65 code = arguments.get("code", "")
66 write_keywords = ("open(", "write(", "mkdir(", "remove(", "shutil.rmtree")
67 return any(kw in code for kw in write_keywords)
70class ShellTool(BaseTool):
71 """Shell命令执行工具。"""
73 name = "shell"
74 description = "执行Shell命令并返回结果。用于文件操作、系统查询等。"
75 permission_level = PermissionLevel.SENSITIVE
77 @property
78 def parameters(self) -> dict:
79 return {
80 "type": "object",
81 "properties": {
82 "command": {
83 "type": "string",
84 "description": "要执行的Shell命令",
85 },
86 },
87 "required": ["command"],
88 }
90 async def execute(self, arguments: dict, sandbox=None) -> ToolResult:
91 command = arguments["command"]
93 if sandbox:
94 return await sandbox.execute_code(command, "shell")
96 try:
97 result = subprocess.run(
98 command,
99 shell=True,
100 capture_output=True,
101 text=True,
102 timeout=30,
103 )
104 return ToolResult(
105 call_id="",
106 output=result.stdout or result.stderr,
107 error=None if result.returncode == 0 else result.stderr,
108 exit_code=result.returncode,
109 )
110 except subprocess.TimeoutExpired:
111 return ToolResult(call_id="", error="Command timed out (30s)")
112 except Exception as e:
113 return ToolResult(call_id="", error=str(e))
115 def is_write_operation(self, arguments: dict) -> bool:
116 cmd = arguments.get("command", "")
117 write_keywords = ("rm ", "rmdir", "mv ", "cp ", "touch ", "mkdir ", ">")
118 return any(kw in cmd for kw in write_keywords)