auto-coder 0.1.389__py3-none-any.whl → 0.1.391__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of auto-coder might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: auto-coder
3
- Version: 0.1.389
3
+ Version: 0.1.391
4
4
  Summary: AutoCoder: AutoCoder
5
5
  Author: allwefantasy
6
6
  Classifier: Programming Language :: Python :: 3.10
@@ -28,7 +28,7 @@ Requires-Dist: prompt-toolkit
28
28
  Requires-Dist: tokenizers
29
29
  Requires-Dist: aiofiles
30
30
  Requires-Dist: readerwriterlock
31
- Requires-Dist: byzerllm[saas] >=0.1.187
31
+ Requires-Dist: byzerllm[saas] >=0.1.188
32
32
  Requires-Dist: patch
33
33
  Requires-Dist: diff-match-patch
34
34
  Requires-Dist: GitPython
@@ -1,17 +1,17 @@
1
1
  autocoder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  autocoder/auto_coder.py,sha256=7602L3tG0JErNxh8vkLAmGUgv2c-DGPzPCkmWIQt9bs,69757
3
- autocoder/auto_coder_rag.py,sha256=tRAKfo3jIhcaQKN_3g7DZRKtDJSZXJxMRdT6Zz8W9nw,41173
4
- autocoder/auto_coder_runner.py,sha256=NhT1fVdV4NnV2SwpXl7G-tTKgduA0D-0lK_p2R6DWew,115569
3
+ autocoder/auto_coder_rag.py,sha256=9PeW7m1bdZx9Q4yw6ULeBKuJQ2EZyO2MepTofl9RxA4,41376
4
+ autocoder/auto_coder_runner.py,sha256=3kjlxvCgnOd-_P7VqPVcBYU_xqTdW515c-XFwuXUgdI,115789
5
5
  autocoder/auto_coder_server.py,sha256=bLORGEclcVdbBVfM140JCI8WtdrU0jbgqdJIVVupiEU,20578
6
6
  autocoder/benchmark.py,sha256=Ypomkdzd1T3GE6dRICY3Hj547dZ6_inqJbBJIp5QMco,4423
7
- autocoder/chat_auto_coder.py,sha256=vNQwbYkdqeMl07Vx8z6x-kSPkHKn9AT3sSkYMTJiWtc,26655
7
+ autocoder/chat_auto_coder.py,sha256=atlHr3kh9jiVoMt5Wa69_shxRxLjLMrFyz-Iw605g1E,26772
8
8
  autocoder/chat_auto_coder_lang.py,sha256=ylLr1GskchU6kIUJY2TiznrBg-ckc1o-8fDsKZZ0iQU,29337
9
9
  autocoder/command_args.py,sha256=HxflngkYtTrV17Vfgk6lyUyiG68jP2ftSc7FYr9AXwY,30585
10
10
  autocoder/command_parser.py,sha256=fx1g9E6GaM273lGTcJqaFQ-hoksS_Ik2glBMnVltPCE,10013
11
11
  autocoder/lang.py,sha256=PFtATuOhHRnfpqHQkXr6p4C893JvpsgwTMif3l-GEi0,14321
12
12
  autocoder/models.py,sha256=pD5u6gcMKRwWaLxeVin18g25k-ERyeHOFsRpOgO_Ae0,13788
13
13
  autocoder/run_context.py,sha256=IUfSO6_gp2Wt1blFWAmOpN0b0nDrTTk4LmtCYUBIoro,1643
14
- autocoder/version.py,sha256=_eG6Vyzk-NJSxEJd-HpLZRgj5aU8TeLxkg-hboV3wU4,25
14
+ autocoder/version.py,sha256=ziiG-zaOKRVuQuJK5CBB3DggynIuAtpa-vKHfvrrY94,25
15
15
  autocoder/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  autocoder/agent/agentic_filter.py,sha256=zlInIRhawKIYTJjCiJBWqPCOV5UtMbh5VnvszfTy2vo,39824
17
17
  autocoder/agent/auto_demand_organizer.py,sha256=URAq0gSEiHeV_W4zwhOI_83kHz0Ryfj1gcfh5jwCv_w,6501
@@ -60,7 +60,7 @@ autocoder/commands/auto_web.py,sha256=K0Gv7lil5UqmExr_sAJNOcwNxw_q1vhvre1jjQ7tA3
60
60
  autocoder/commands/tools.py,sha256=IX_zx5mWAvQDED7wUHTqNtrCmLNo9ztFV1aZ6AflY4o,34292
61
61
  autocoder/common/JupyterClient.py,sha256=O-wi6pXeAEYhAY24kDa0BINrLYvKS6rKyWe98pDClS0,2816
62
62
  autocoder/common/ShellClient.py,sha256=fM1q8t_XMSbLBl2zkCNC2J9xuyKN3eXzGm6hHhqL2WY,2286
63
- autocoder/common/__init__.py,sha256=qZWLTeEjimIGDUvbAq_QV1o5jgMiD1k4TQcoU0-wOo8,14887
63
+ autocoder/common/__init__.py,sha256=OzjUaZBO1p8cb1f3K-3RylcDn7PAEbtm2cqr3Qz6Y6k,15010
64
64
  autocoder/common/action_yml_file_manager.py,sha256=DdF5P1R_B_chCnnqoA2IgogakWLZk_nItiJZUfX0_Wo,17857
65
65
  autocoder/common/anything2images.py,sha256=0ILBbWzY02M-CiWB-vzuomb_J1hVdxRcenAfIrAXq9M,25283
66
66
  autocoder/common/anything2img.py,sha256=iZQmg8srXlD7N5uGl5b_ONKJMBjYoW8kPmokkG6ISF0,10118
@@ -182,7 +182,8 @@ autocoder/common/v2/agent/agentic_edit_tools/__init__.py,sha256=RbPZZcZg_VnGssL5
182
182
  autocoder/common/v2/agent/agentic_edit_tools/ask_followup_question_tool_resolver.py,sha256=-HFXo3RR6CH8xXjDaE2mYV4XasTLAmvXe6WutL7qbwA,3208
183
183
  autocoder/common/v2/agent/agentic_edit_tools/attempt_completion_tool_resolver.py,sha256=82ZGKeRBSDKeead_XVBW4FxpiE-5dS7tBOk_3RZ6B5s,1511
184
184
  autocoder/common/v2/agent/agentic_edit_tools/base_tool_resolver.py,sha256=Zid2m1uZd-2wVFGc_n_KAViXZyNjbdLSpI5n7ut1RUQ,1036
185
- autocoder/common/v2/agent/agentic_edit_tools/execute_command_tool_resolver.py,sha256=8dCjSvpo09QG4Jj-kh5iOTQtikp87W0Z6q_6XyezQDo,5439
185
+ autocoder/common/v2/agent/agentic_edit_tools/dangerous_command_checker.py,sha256=XeFKuZrxbmSNk04GrL2U_PzIjRbqWYlGvGLhcYv-Jeg,7831
186
+ autocoder/common/v2/agent/agentic_edit_tools/execute_command_tool_resolver.py,sha256=KvwXFrdCsWlAsU15a6mvOnTxrcgysTIViZE2o0TGItM,6139
186
187
  autocoder/common/v2/agent/agentic_edit_tools/list_code_definition_names_tool_resolver.py,sha256=8QoMsADUDWliqiDt_dpguz31403syB8eeW0Pcw-qfb8,3842
187
188
  autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py,sha256=1tJX9RYRU0zRjKZMzFlZzKm-4R32CzRnZ0UQJj4pxAk,8074
188
189
  autocoder/common/v2/agent/agentic_edit_tools/list_package_info_tool_resolver.py,sha256=dIdV12VuczHpHuHgx2B1j_3BZYc9PL0jfHCuBk9ryk8,2005
@@ -248,9 +249,13 @@ autocoder/linters/test_python_linter.py,sha256=zYPliyjm1s0IJmlIadyWQedsLNOGbaz7Q
248
249
  autocoder/linters/test_reactjs_linter.py,sha256=72VnejikldyEH5PdvJzrgtcxhnlGkVZTe3hWRGnw4mA,7099
249
250
  autocoder/linters/test_vue_linter.py,sha256=m031brPZdK66Yi-hvlPvL0RYyQxvY43lHu_ATVxrvQs,7592
250
251
  autocoder/linters/vue_linter.py,sha256=MjF-SgSbgOucyv0hnp2r56CIfe8hqDibs0NKnvUUvLw,21225
251
- autocoder/memory/__init__.py,sha256=5FeGvsesRViYL4BkFiHw9SdlyHeWlqALpTyqOpfnBRw,179
252
+ autocoder/memory/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
253
+ autocoder/memory/active_changes.py,sha256=I2CWMdw-rUqEOcJX-8apk5in4y2gomWhaufytkqQOsY,9492
252
254
  autocoder/memory/active_context_manager.py,sha256=nqWD4lBLNcskXDRERhPpqnmn_i1V7_CTfQSN3xAX6b8,32297
253
- autocoder/memory/active_package.py,sha256=NHLLnncFSfFcOFLWILwJLuEVd4nOoL0mqzFev6QHgzU,25480
255
+ autocoder/memory/active_diagrams.py,sha256=4_JRyzLZeXvLyopWY35oHI9omnXWhRZITmpazltn7NA,11055
256
+ autocoder/memory/active_documents.py,sha256=QEfssXWPWvl4pWeZuv7ZEUx0Ynm-VRPRrFJIwmP4wAA,10060
257
+ autocoder/memory/active_header.py,sha256=_6ZXe0uixqc24SUXmnsVzIZYHU6Y3fV5hIU56zFlWko,3092
258
+ autocoder/memory/active_package.py,sha256=LMRAeI4--tURHbGn2Xb4rdeTTFyRcnruAL7utHpfTtI,16183
254
259
  autocoder/memory/async_processor.py,sha256=htHzLGupw9IHQAEdLe2AEaALZSItPi3AltDt8FMTRHk,4643
255
260
  autocoder/memory/directory_mapper.py,sha256=BXHblOdRpeZb7URDECALp9uN5oi91KmkW9g_UaWFuZY,2513
256
261
  autocoder/plugins/__init__.py,sha256=T71wGXBP24NhFyf9BntKDXWPIvKp5hWhq_-xK7C-ptE,43722
@@ -336,9 +341,9 @@ autocoder/utils/types.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
336
341
  autocoder/utils/auto_coder_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
337
342
  autocoder/utils/auto_coder_utils/chat_stream_out.py,sha256=t902pKxQ5xM7zgIHiAOsTPLwxhE6VuvXAqPy751S7fg,14096
338
343
  autocoder/utils/chat_auto_coder_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
339
- auto_coder-0.1.389.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
340
- auto_coder-0.1.389.dist-info/METADATA,sha256=vmgcu_JB1Mf3kCDXkyJ0NZzjh_ItUfwdIV2bKKNanGU,2796
341
- auto_coder-0.1.389.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
342
- auto_coder-0.1.389.dist-info/entry_points.txt,sha256=0nzHtHH4pNcM7xq4EBA2toS28Qelrvcbrr59GqD_0Ak,350
343
- auto_coder-0.1.389.dist-info/top_level.txt,sha256=Jqc0_uJSw2GwoFQAa9iJxYns-2mWla-9ok_Y3Gcznjk,10
344
- auto_coder-0.1.389.dist-info/RECORD,,
344
+ auto_coder-0.1.391.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
345
+ auto_coder-0.1.391.dist-info/METADATA,sha256=sR4t9Ydv7vshE7YwjlIm_2lqRu3xT6Vd34irhHfWfTk,2796
346
+ auto_coder-0.1.391.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
347
+ auto_coder-0.1.391.dist-info/entry_points.txt,sha256=0nzHtHH4pNcM7xq4EBA2toS28Qelrvcbrr59GqD_0Ak,350
348
+ auto_coder-0.1.391.dist-info/top_level.txt,sha256=Jqc0_uJSw2GwoFQAa9iJxYns-2mWla-9ok_Y3Gcznjk,10
349
+ auto_coder-0.1.391.dist-info/RECORD,,
@@ -936,6 +936,11 @@ def main(input_args: Optional[List[str]] = None):
936
936
  logger.error(
937
937
  "The document retriever does not support hybrid index building"
938
938
  )
939
+ try:
940
+ monitor = FileMonitor(args.doc_dir)
941
+ monitor.stop()
942
+ except Exception as e:
943
+ logger.warning(f"Failed to stop file monitor: {e}")
939
944
 
940
945
  elif args.command == "tools":
941
946
  if args.tool == "count":
@@ -258,6 +258,7 @@ def configure_logger():
258
258
  ]
259
259
  )
260
260
 
261
+
261
262
  def init_singleton_instances():
262
263
  # 初始化文件监控系统
263
264
  try:
@@ -275,9 +276,17 @@ def init_singleton_instances():
275
276
  _ = IgnoreFileManager(project_root=project_root)
276
277
 
277
278
 
278
- if os.environ.get('autocoder_auto_init',"true") in ["true","True","True",True]:
279
- configure_logger()
280
- init_singleton_instances()
279
+ def start():
280
+ if os.environ.get('autocoder_auto_init',"true") in ["true","True","True",True]:
281
+ configure_logger()
282
+ init_singleton_instances()
283
+
284
+ def stop():
285
+ try:
286
+ FileMonitor(project_root).stop()
287
+ except Exception as e:
288
+ global_logger.error(f"Failed to stop file monitor: {e}")
289
+ global_logger.exception(e)
281
290
 
282
291
  def initialize_system(args:InitializeSystemRequest):
283
292
  from autocoder.utils.model_provider_selector import ModelProviderSelector
@@ -52,7 +52,9 @@ from autocoder.auto_coder_runner import (
52
52
  summon,
53
53
  get_memory,
54
54
  active_context,
55
- rules
55
+ rules,
56
+ start as start_engine,
57
+ stop as stop_engine
56
58
  )
57
59
  # Ensure the correct import is present
58
60
  from autocoder.chat.conf_command import handle_conf_command
@@ -269,6 +271,7 @@ ARGS = None
269
271
 
270
272
  def main():
271
273
  load_tokenizer()
274
+ start_engine()
272
275
 
273
276
  ARGS = parse_arguments()
274
277
 
@@ -668,13 +671,14 @@ def main():
668
671
  except EOFError:
669
672
  try:
670
673
  # Shutdown all plugins before exiting
671
- plugin_manager.shutdown_all()
674
+ plugin_manager.shutdown_all()
672
675
  # save_memory()
673
676
  try:
674
677
  if get_mcp_server():
675
678
  get_mcp_server().stop()
676
679
  except Exception as e:
677
680
  pass
681
+ stop_engine()
678
682
  except Exception as e:
679
683
  print(
680
684
  f"\033[91mAn error occurred while saving memory:\033[0m \033[93m{type(e).__name__}\033[0m - {str(e)}"
@@ -275,6 +275,8 @@ class AutoCoderArgs(pydantic.BaseModel):
275
275
 
276
276
  enable_agentic_filter: Optional[bool] = False
277
277
  enable_agentic_edit: Optional[bool] = True
278
+ enable_agentic_auto_approve: Optional[bool] = False
279
+ enable_agentic_dangerous_command_check: Optional[bool] = False
278
280
 
279
281
 
280
282
  index_filter_level: Optional[int] = 0
@@ -0,0 +1,191 @@
1
+ import re
2
+ from typing import List, Tuple, Optional
3
+ from loguru import logger
4
+
5
+
6
+ class DangerousCommandChecker:
7
+ """危险命令检查器,用于检测和防止执行潜在危险的系统命令"""
8
+
9
+ def __init__(self):
10
+ # 危险命令模式列表
11
+ self.dangerous_patterns = [
12
+ # 文件删除相关
13
+ (r'\brm\s+.*-[rf]', "删除文件命令"),
14
+ (r'\brm\s+-[rf]', "删除文件命令"),
15
+ (r'\bunlink\b', "删除文件命令"),
16
+
17
+ # 系统格式化和分区操作
18
+ (r'\bmkfs\b', "格式化文件系统命令"),
19
+ (r'\bfdisk\b', "磁盘分区命令"),
20
+ (r'\bparted\b', "磁盘分区命令"),
21
+ (r'\bdd\s+.*if=.*of=', "数据复制命令,可能覆盖系统文件"),
22
+
23
+ # 权限修改
24
+ (r'\bchmod\s+777\b', "危险权限修改"),
25
+ (r'\bchmod\s+\d*7\d*7\b', "危险权限修改"),
26
+ (r'\bchown\s+.*root\b', "更改文件所有者为root"),
27
+
28
+ # 提权相关
29
+ (r'\bsudo\s+.*rm\b', "使用sudo执行删除命令"),
30
+ (r'\bsu\s+-\b', "切换到root用户"),
31
+ (r'\bsu\s+root\b', "切换到root用户"),
32
+
33
+ # 系统服务相关
34
+ (r'\bsystemctl\s+stop\b', "停止系统服务"),
35
+ (r'\bsystemctl\s+disable\b', "禁用系统服务"),
36
+ (r'\bservice\s+.*stop\b', "停止系统服务"),
37
+
38
+ # 进程操作
39
+ (r'\bkill\s+-9\s+1\b', "强制终止init进程"),
40
+ (r'\bkillall\s+-9\b', "强制终止所有进程"),
41
+ (r'\bpkill\s+-9\b', "强制终止进程"),
42
+
43
+ # 系统关机重启
44
+ (r'\bshutdown\b', "系统关机命令"),
45
+ (r'\breboot\b', "系统重启命令"),
46
+ (r'\bhalt\b', "系统停机命令"),
47
+ (r'\bpoweroff\b', "系统断电命令"),
48
+
49
+ # 环境变量和系统配置
50
+ (r'\bexport\s+PATH=', "修改PATH环境变量"),
51
+ (r'\bunset\s+PATH\b', "删除PATH环境变量"),
52
+ (r'>\s*/etc/', "重定向写入系统配置文件"),
53
+ (r'\becho\s+.*>\s*/etc/', "写入系统配置文件"),
54
+
55
+ # 系统文件编辑
56
+ (r'\bvi\s+/etc/', "编辑系统配置文件"),
57
+ (r'\bnano\s+/etc/', "编辑系统配置文件"),
58
+ (r'\bemacs\s+/etc/', "编辑系统配置文件"),
59
+
60
+ # 历史和日志清理
61
+ (r'\bhistory\s+-c\b', "清空命令历史"),
62
+ (r'>\s*/dev/null\s+2>&1', "重定向所有输出到null"),
63
+ (r'\brm\s+.*\.log\b', "删除日志文件"),
64
+
65
+ # 安装和包管理(可能安装恶意软件)
66
+ (r'\bapt\s+install\s+.*--force\b', "强制安装软件包"),
67
+ (r'\byum\s+install\s+.*--assumeyes\b', "自动确认安装软件包"),
68
+ (r'\bpip\s+install\s+.*--force\b', "强制安装Python包"),
69
+ ]
70
+
71
+ # 危险字符模式
72
+ self.dangerous_chars = [
73
+ (r';', "命令分隔符,可能执行多个命令"),
74
+ (r'`.*`', "命令替换,可能执行隐藏命令"),
75
+ (r'\$\(.*\)', "命令替换,可能执行隐藏命令"),
76
+ (r'\|(?!\s*head\b|\s*tail\b|\s*grep\b|\s*sort\b|\s*uniq\b|\s*wc\b|\s*cat\b)', "管道符,可能传递敏感数据"),
77
+ (r'&&(?!\s*echo\b)', "逻辑与操作符,可能链式执行命令"),
78
+ (r'\|\|', "逻辑或操作符,可能条件执行命令"),
79
+ (r'<\(', "进程替换"),
80
+ (r'>\(', "进程替换"),
81
+ ]
82
+
83
+ # 允许的安全命令前缀(白名单)
84
+ self.safe_command_prefixes = [
85
+ 'ls', 'pwd', 'whoami', 'date', 'echo', 'cat', 'head', 'tail',
86
+ 'grep', 'find', 'which', 'man', 'help', 'cd', 'mkdir', 'touch',
87
+ 'cp', 'mv', 'wc', 'sort', 'uniq', 'diff', 'tree', 'file',
88
+ 'stat', 'du', 'df', 'ps', 'top', 'history', 'env', 'printenv'
89
+ ]
90
+
91
+ def is_command_dangerous(self, command: str) -> Tuple[bool, Optional[str]]:
92
+ """
93
+ 检查命令是否危险
94
+
95
+ Args:
96
+ command: 要检查的命令字符串
97
+
98
+ Returns:
99
+ Tuple[bool, Optional[str]]: (是否危险, 危险原因)
100
+ """
101
+ command = command.strip()
102
+
103
+ # 空命令不危险
104
+ if not command:
105
+ return False, None
106
+
107
+ # 检查危险命令模式
108
+ for pattern, reason in self.dangerous_patterns:
109
+ if re.search(pattern, command, re.IGNORECASE):
110
+ logger.warning(f"检测到危险命令模式: {pattern} in command: {command}")
111
+ return True, f"危险命令: {reason}"
112
+
113
+ # 检查危险字符
114
+ for pattern, reason in self.dangerous_chars:
115
+ if re.search(pattern, command):
116
+ # 对于 && 的特殊处理,允许 cd 命令链
117
+ if pattern == r'&&(?!\s*echo\b)' and command.strip().startswith('cd '):
118
+ continue
119
+ logger.warning(f"检测到危险字符: {pattern} in command: {command}")
120
+ return True, f"包含危险字符: {reason}"
121
+
122
+ return False, None
123
+
124
+ def is_command_in_whitelist(self, command: str) -> bool:
125
+ """
126
+ 检查命令是否在安全白名单中
127
+
128
+ Args:
129
+ command: 要检查的命令字符串
130
+
131
+ Returns:
132
+ bool: 是否在白名单中
133
+ """
134
+ command = command.strip()
135
+ if not command:
136
+ return False
137
+
138
+ # 获取命令的第一个词(命令名)
139
+ first_word = command.split()[0]
140
+
141
+ return first_word.lower() in self.safe_command_prefixes
142
+
143
+ def check_command_safety(self, command: str, allow_whitelist_bypass: bool = True) -> Tuple[bool, Optional[str]]:
144
+ """
145
+ 综合检查命令安全性
146
+
147
+ Args:
148
+ command: 要检查的命令字符串
149
+ allow_whitelist_bypass: 是否允许白名单命令绕过危险检查
150
+
151
+ Returns:
152
+ Tuple[bool, Optional[str]]: (是否安全, 不安全的原因)
153
+ """
154
+ # 首先检查是否危险
155
+ is_dangerous, danger_reason = self.is_command_dangerous(command)
156
+
157
+ if not is_dangerous:
158
+ return True, None
159
+
160
+ # 如果允许白名单绕过,且命令在白名单中,则认为安全
161
+ if allow_whitelist_bypass and self.is_command_in_whitelist(command):
162
+ logger.info(f"命令在白名单中,允许执行: {command}")
163
+ return True, None
164
+
165
+ return False, danger_reason
166
+
167
+ def get_safety_recommendations(self, command: str) -> List[str]:
168
+ """
169
+ 为不安全的命令提供安全建议
170
+
171
+ Args:
172
+ command: 要检查的命令字符串
173
+
174
+ Returns:
175
+ List[str]: 安全建议列表
176
+ """
177
+ recommendations = []
178
+
179
+ if 'rm' in command:
180
+ recommendations.append("使用 'rm -i' 进行交互式删除")
181
+ recommendations.append("在删除前使用 'ls' 确认要删除的文件")
182
+
183
+ if 'chmod 777' in command:
184
+ recommendations.append("避免使用 '777' 权限,考虑更安全的权限设置")
185
+ recommendations.append("使用 'chmod 755' 或 'chmod 644' 等更安全的权限")
186
+
187
+ if 'sudo' in command:
188
+ recommendations.append("确认您真的需要root权限")
189
+ recommendations.append("考虑使用更具体的权限而不是sudo")
190
+
191
+ return recommendations
@@ -4,6 +4,7 @@ from typing import Dict, Any, Optional
4
4
  from autocoder.common.run_cmd import run_cmd_subprocess
5
5
  from autocoder.common.v2.agent.agentic_edit_tools.base_tool_resolver import BaseToolResolver
6
6
  from autocoder.common.v2.agent.agentic_edit_types import ExecuteCommandTool, ToolResult # Import ToolResult from types
7
+ from autocoder.common.v2.agent.agentic_edit_tools.dangerous_command_checker import DangerousCommandChecker
7
8
  from autocoder.common import shells
8
9
  from autocoder.common.printer import Printer
9
10
  from loguru import logger
@@ -26,6 +27,8 @@ class ExecuteCommandToolResolver(BaseToolResolver):
26
27
  args=self.args,
27
28
  llm=self.agent.context_prune_llm
28
29
  )
30
+ # 初始化危险命令检查器
31
+ self.danger_checker = DangerousCommandChecker()
29
32
 
30
33
  def _prune_file_content(self, content: str, file_path: str) -> str:
31
34
  """对文件内容进行剪枝处理"""
@@ -60,33 +63,39 @@ class ExecuteCommandToolResolver(BaseToolResolver):
60
63
  command = self.tool.command
61
64
  requires_approval = self.tool.requires_approval
62
65
  source_dir = self.args.source_dir or "."
63
-
64
- # Basic security check (can be expanded)
65
- if ";" in command or "&&" in command or "|" in command or "`" in command:
66
- # Allow && for cd chaining, but be cautious
67
- if not command.strip().startswith("cd ") and " && " in command:
68
- pass # Allow cd chaining like 'cd subdir && command'
69
- else:
70
- return ToolResult(success=False, message=f"Command '{command}' contains potentially unsafe characters.")
66
+
67
+ if self.args.enable_agentic_dangerous_command_check:
68
+ # 使用新的危险命令检查器进行安全检查
69
+ is_safe, danger_reason = self.danger_checker.check_command_safety(command, allow_whitelist_bypass=True)
70
+
71
+ if not is_safe:
72
+ # 获取安全建议
73
+ recommendations = self.danger_checker.get_safety_recommendations(command)
74
+
75
+ error_message = f"检测到危险命令: {danger_reason}"
76
+ if recommendations:
77
+ error_message += f"\n安全建议:\n" + "\n".join(f"- {rec}" for rec in recommendations)
78
+
79
+ logger.warning(f"阻止执行危险命令: {command}, 原因: {danger_reason}")
80
+ return ToolResult(success=False, message=error_message)
71
81
 
72
82
  # Approval mechanism (simplified)
73
- if requires_approval:
74
- # In a real scenario, this would involve user interaction
75
- logger.info(f"Command requires approval: {command}")
76
- # For now, let's assume approval is granted in non-interactive mode or handled elsewhere
77
- pass
78
-
79
- logger.info(f"Executing command: {command} in {os.path.abspath(source_dir)}")
80
- try:
81
- # 使用封装的run_cmd方法执行命令
82
- if get_run_context().is_web():
83
- answer = get_event_manager(
84
- self.args.event_file).ask_user(prompt=f"Allow to execute the `{command}`?",options=["yes","no"])
85
- if answer == "yes":
86
- pass
87
- else:
88
- return ToolResult(success=False, message=f"Command '{command}' execution denied by user.")
89
-
83
+ if not self.args.enable_agentic_auto_approve and requires_approval:
84
+ logger.info(f"Executing command: {command} in {os.path.abspath(source_dir)}")
85
+ try:
86
+ # 使用封装的run_cmd方法执行命令
87
+ if get_run_context().is_web():
88
+ answer = get_event_manager(
89
+ self.args.event_file).ask_user(prompt=f"Allow to execute the `{command}`?",options=["yes","no"])
90
+ if answer == "yes":
91
+ pass
92
+ else:
93
+ return ToolResult(success=False, message=f"Command '{command}' execution denied by user.")
94
+ except Exception as e:
95
+ logger.error(f"Error when ask the user to approve the command '{command}': {str(e)}")
96
+ return ToolResult(success=False, message=f"An unexpected error occurred while asking the user to approve the command: {str(e)}")
97
+
98
+ try:
90
99
  exit_code, output = run_cmd_subprocess(command, verbose=True, cwd=source_dir)
91
100
 
92
101
  logger.info(f"Command executed: {command}")
@@ -1,7 +0,0 @@
1
- """
2
- 记忆子系统 - 用于跟踪和记录代码变更上下文
3
- """
4
-
5
- from autocoder.memory.active_context_manager import ActiveContextManager
6
-
7
- __all__ = ["ActiveContextManager"]