auto-coder 0.1.362__py3-none-any.whl → 0.1.363__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.

Files changed (46) hide show
  1. {auto_coder-0.1.362.dist-info → auto_coder-0.1.363.dist-info}/METADATA +1 -1
  2. {auto_coder-0.1.362.dist-info → auto_coder-0.1.363.dist-info}/RECORD +46 -18
  3. autocoder/agent/base_agentic/__init__.py +0 -0
  4. autocoder/agent/base_agentic/agent_hub.py +169 -0
  5. autocoder/agent/base_agentic/agentic_lang.py +112 -0
  6. autocoder/agent/base_agentic/agentic_tool_display.py +180 -0
  7. autocoder/agent/base_agentic/base_agent.py +1582 -0
  8. autocoder/agent/base_agentic/default_tools.py +683 -0
  9. autocoder/agent/base_agentic/test_base_agent.py +82 -0
  10. autocoder/agent/base_agentic/tool_registry.py +425 -0
  11. autocoder/agent/base_agentic/tools/__init__.py +12 -0
  12. autocoder/agent/base_agentic/tools/ask_followup_question_tool_resolver.py +72 -0
  13. autocoder/agent/base_agentic/tools/attempt_completion_tool_resolver.py +37 -0
  14. autocoder/agent/base_agentic/tools/base_tool_resolver.py +35 -0
  15. autocoder/agent/base_agentic/tools/example_tool_resolver.py +46 -0
  16. autocoder/agent/base_agentic/tools/execute_command_tool_resolver.py +72 -0
  17. autocoder/agent/base_agentic/tools/list_files_tool_resolver.py +110 -0
  18. autocoder/agent/base_agentic/tools/plan_mode_respond_tool_resolver.py +35 -0
  19. autocoder/agent/base_agentic/tools/read_file_tool_resolver.py +54 -0
  20. autocoder/agent/base_agentic/tools/replace_in_file_tool_resolver.py +156 -0
  21. autocoder/agent/base_agentic/tools/search_files_tool_resolver.py +134 -0
  22. autocoder/agent/base_agentic/tools/talk_to_group_tool_resolver.py +96 -0
  23. autocoder/agent/base_agentic/tools/talk_to_tool_resolver.py +79 -0
  24. autocoder/agent/base_agentic/tools/use_mcp_tool_resolver.py +44 -0
  25. autocoder/agent/base_agentic/tools/write_to_file_tool_resolver.py +58 -0
  26. autocoder/agent/base_agentic/types.py +189 -0
  27. autocoder/agent/base_agentic/utils.py +100 -0
  28. autocoder/auto_coder_runner.py +4 -4
  29. autocoder/chat/conf_command.py +11 -10
  30. autocoder/common/rulefiles/autocoderrules_utils.py +24 -0
  31. autocoder/common/save_formatted_log.py +1 -1
  32. autocoder/common/v2/agent/agentic_edit.py +21 -19
  33. autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +73 -1
  34. autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py +132 -4
  35. autocoder/common/v2/agent/agentic_edit_types.py +1 -2
  36. autocoder/common/v2/agent/agentic_tool_display.py +2 -3
  37. autocoder/rag/long_context_rag.py +424 -397
  38. autocoder/rag/test_doc_filter.py +393 -0
  39. autocoder/rag/test_long_context_rag.py +473 -0
  40. autocoder/rag/test_token_limiter.py +342 -0
  41. autocoder/shadows/shadow_manager.py +1 -3
  42. autocoder/version.py +1 -1
  43. {auto_coder-0.1.362.dist-info → auto_coder-0.1.363.dist-info}/LICENSE +0 -0
  44. {auto_coder-0.1.362.dist-info → auto_coder-0.1.363.dist-info}/WHEEL +0 -0
  45. {auto_coder-0.1.362.dist-info → auto_coder-0.1.363.dist-info}/entry_points.txt +0 -0
  46. {auto_coder-0.1.362.dist-info → auto_coder-0.1.363.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,96 @@
1
+ from typing import Optional, Dict, Any
2
+ import os
3
+ from loguru import logger
4
+ from datetime import datetime
5
+
6
+ from ..types import TalkToGroupTool, ToolResult
7
+ from ..tools.base_tool_resolver import BaseToolResolver
8
+ from ..agent_hub import AgentHub, Group
9
+
10
+
11
+ class TalkToGroupToolResolver(BaseToolResolver):
12
+ """
13
+ 处理talk_to_group工具的解析器
14
+ """
15
+
16
+ def resolve(self) -> ToolResult:
17
+ """
18
+ 解析和执行talk_to_group工具
19
+
20
+ Returns:
21
+ ToolResult: 工具执行结果
22
+ """
23
+ try:
24
+ # 获取参数
25
+ group_name = self.tool.group_name
26
+ content = self.tool.content
27
+ mentions_names = self.tool.mentions or []
28
+ print_conversation = self.tool.print_conversation
29
+
30
+ # 获取目标群组
31
+ groups = AgentHub.get_all_groups()
32
+ target_group = None
33
+ for group in groups:
34
+ if group.name == group_name:
35
+ target_group = group
36
+ break
37
+
38
+ if not target_group:
39
+ return ToolResult(
40
+ success=False,
41
+ message=f"找不到名为 '{group_name}' 的群组",
42
+ content=None
43
+ )
44
+
45
+ # 解析提及的代理
46
+ mentions = []
47
+ for name in mentions_names:
48
+ agent = AgentHub.get_agent(name)
49
+ if agent:
50
+ mentions.append(agent)
51
+ else:
52
+ logger.warning(f"找不到提及的代理: {name}")
53
+
54
+ # 执行talk_to_group操作
55
+ self.agent.talk_to_group(
56
+ group=target_group,
57
+ content=content,
58
+ mentions=mentions,
59
+ print_conversation=print_conversation
60
+ )
61
+
62
+ # 获取群组消息历史
63
+ with target_group._history_lock:
64
+ group_history = target_group.history.copy()
65
+
66
+ # 获取群组成员
67
+ with target_group._members_lock:
68
+ members = [member.name for member in target_group.members]
69
+
70
+ # 格式化群组历史
71
+ formatted_history = f"群组:{group_name}\n"
72
+ formatted_history += f"成员:{', '.join(members)}\n\n"
73
+ formatted_history += "对话历史:\n\n"
74
+
75
+ for msg in group_history:
76
+ sender_display = "你" if msg.sender == self.agent.name else msg.sender
77
+ mention_text = ""
78
+ if msg.mentions:
79
+ mention_display = ["你" if m == self.agent.name else m for m in msg.mentions]
80
+ mention_text = f" @{' @'.join(mention_display)}"
81
+ formatted_history += f"[{sender_display}]{mention_text}: {msg.content}\n\n"
82
+
83
+ # 返回结果
84
+ return ToolResult(
85
+ success=True,
86
+ message=f"已向群组 '{group_name}' 探讨",
87
+ content=formatted_history
88
+ )
89
+
90
+ except Exception as e:
91
+ logger.exception(f"执行talk_to_group工具时出错: {e}")
92
+ return ToolResult(
93
+ success=False,
94
+ message=f"执行talk_to_group工具时出错: {str(e)}",
95
+ content=None
96
+ )
@@ -0,0 +1,79 @@
1
+ from typing import Optional, Dict, Any
2
+ import os
3
+ from loguru import logger
4
+ from datetime import datetime
5
+
6
+ from ..types import TalkToTool, ToolResult
7
+ from ..tools.base_tool_resolver import BaseToolResolver
8
+ from ..agent_hub import AgentHub
9
+
10
+
11
+ class TalkToToolResolver(BaseToolResolver):
12
+ """
13
+ 处理talk_to工具的解析器
14
+ """
15
+
16
+ def resolve(self) -> ToolResult:
17
+ """
18
+ 解析和执行talk_to工具
19
+
20
+ Returns:
21
+ ToolResult: 工具执行结果
22
+ """
23
+ try:
24
+ # 获取参数
25
+ agent_name = self.tool.agent_name
26
+ content = self.tool.content
27
+ mentions_names = self.tool.mentions or []
28
+ print_conversation = self.tool.print_conversation
29
+
30
+ # 获取目标代理
31
+ target_agent = AgentHub.get_agent(agent_name)
32
+ if not target_agent:
33
+ return ToolResult(
34
+ success=False,
35
+ message=f"找不到名为 '{agent_name}' 的代理",
36
+ content=None
37
+ )
38
+
39
+ # 解析提及的代理
40
+ mentions = []
41
+ for name in mentions_names:
42
+ agent = AgentHub.get_agent(name)
43
+ if agent:
44
+ mentions.append(agent)
45
+ else:
46
+ logger.warning(f"找不到提及的代理: {name}")
47
+
48
+ # 执行talk_to操作
49
+ self.agent.talk_to(
50
+ other=target_agent,
51
+ content=content,
52
+ mentions=mentions,
53
+ print_conversation=print_conversation
54
+ )
55
+
56
+ # 获取对话历史记录,格式化为易读的形式
57
+ with self.agent._chat_lock:
58
+ chat_history = self.agent.private_chats.get(agent_name, [])
59
+
60
+ # 格式化聊天历史
61
+ formatted_history = "对话历史:\n\n"
62
+ for msg in chat_history:
63
+ sender_display = "你" if msg.sender == self.agent.name else msg.sender
64
+ formatted_history += f"[{sender_display}]: {msg.content}\n\n"
65
+
66
+ # 返回结果
67
+ return ToolResult(
68
+ success=True,
69
+ message=f"已向Agent '{agent_name}' 讨论",
70
+ content=formatted_history
71
+ )
72
+
73
+ except Exception as e:
74
+ logger.exception(f"执行talk_to工具时出错: {e}")
75
+ return ToolResult(
76
+ success=False,
77
+ message=f"执行talk_to工具时出错: {str(e)}",
78
+ content=None
79
+ )
@@ -0,0 +1,44 @@
1
+ from typing import Dict, Any, Optional
2
+ import typing
3
+ from autocoder.agent.base_agentic.tools.base_tool_resolver import BaseToolResolver
4
+ from autocoder.agent.base_agentic.types import UseMcpTool, ToolResult # Import ToolResult from types
5
+ from autocoder.common import AutoCoderArgs
6
+ from loguru import logger
7
+
8
+ if typing.TYPE_CHECKING:
9
+ from ..base_agent import BaseAgent
10
+
11
+
12
+ class UseMcpToolResolver(BaseToolResolver):
13
+ def __init__(self, agent: Optional['BaseAgent'], tool: UseMcpTool, args: AutoCoderArgs):
14
+ super().__init__(agent, tool, args)
15
+ self.tool: UseMcpTool = tool # For type hinting
16
+
17
+ def resolve(self) -> ToolResult:
18
+ """
19
+ Executes a tool via the Model Context Protocol (MCP) server.
20
+ """
21
+ final_query = ""
22
+ server_name = self.tool.server_name
23
+ tool_name = self.tool.tool_name
24
+
25
+ if server_name:
26
+ final_query += f"{server_name}\n"
27
+
28
+ if tool_name:
29
+ final_query += f"{tool_name} is recommended for the following query:\n"
30
+
31
+ final_query += f"{self.tool.query}"
32
+
33
+ logger.info(f"Resolving UseMcpTool: Server='{server_name}', Tool='{tool_name}', Query='{final_query}'")
34
+
35
+ mcp_server = get_mcp_server()
36
+ response = mcp_server.send_request(
37
+ McpRequest(
38
+ query=final_query,
39
+ model=self.args.inference_model or self.args.model,
40
+ product_mode=self.args.product_mode
41
+ )
42
+ )
43
+ return ToolResult(success=True, message=response.result)
44
+
@@ -0,0 +1,58 @@
1
+ import os
2
+ from typing import Dict, Any, Optional
3
+ from autocoder.agent.base_agentic.types import WriteToFileTool, ToolResult # Import ToolResult from types
4
+ from autocoder.agent.base_agentic.tools.base_tool_resolver import BaseToolResolver
5
+ from loguru import logger
6
+ from autocoder.common import AutoCoderArgs
7
+ import typing
8
+
9
+ if typing.TYPE_CHECKING:
10
+ from ..base_agent import BaseAgent
11
+
12
+ class WriteToFileToolResolver(BaseToolResolver):
13
+ def __init__(self, agent: Optional['BaseAgent'], tool: WriteToFileTool, args: AutoCoderArgs):
14
+ super().__init__(agent, tool, args)
15
+ self.tool: WriteToFileTool = tool # For type hinting
16
+ self.shadow_manager = self.agent.shadow_manager if self.agent else None
17
+
18
+ def resolve(self) -> ToolResult:
19
+ file_path = self.tool.path
20
+ content = self.tool.content
21
+ source_dir = self.args.source_dir or "."
22
+ abs_project_dir = os.path.abspath(source_dir)
23
+ abs_file_path = os.path.abspath(os.path.join(source_dir, file_path))
24
+
25
+ # Security check: ensure the path is within the source directory
26
+ if not abs_file_path.startswith(abs_project_dir):
27
+ return ToolResult(success=False, message=f"Error: Access denied. Attempted to write file outside the project directory: {file_path}")
28
+
29
+ try:
30
+ if self.shadow_manager:
31
+ shadow_path = self.shadow_manager.to_shadow_path(abs_file_path)
32
+ # Ensure shadow directory exists
33
+ os.makedirs(os.path.dirname(shadow_path), exist_ok=True)
34
+ with open(shadow_path, 'w', encoding='utf-8') as f:
35
+ f.write(content)
36
+ logger.info(f"[Shadow] Successfully wrote shadow file: {shadow_path}")
37
+
38
+ # 回调AgenticEdit,记录变更
39
+ if self.agent:
40
+ rel_path = os.path.relpath(abs_file_path, abs_project_dir)
41
+ self.agent.record_file_change(rel_path, "added", diff=None, content=content)
42
+
43
+ return ToolResult(success=True, message=f"Successfully wrote to file (shadow): {file_path}", content=content)
44
+ else:
45
+ # No shadow manager fallback to original file
46
+ os.makedirs(os.path.dirname(abs_file_path), exist_ok=True)
47
+ with open(abs_file_path, 'w', encoding='utf-8') as f:
48
+ f.write(content)
49
+ logger.info(f"Successfully wrote to file: {file_path}")
50
+
51
+ if self.agent:
52
+ rel_path = os.path.relpath(abs_file_path, abs_project_dir)
53
+ self.agent.record_file_change(rel_path, "added", diff=None, content=content)
54
+
55
+ return ToolResult(success=True, message=f"Successfully wrote to file: {file_path}", content=content)
56
+ except Exception as e:
57
+ logger.error(f"Error writing to file '{file_path}': {str(e)}")
58
+ return ToolResult(success=False, message=f"An error occurred while writing to the file: {str(e)}")
@@ -0,0 +1,189 @@
1
+ from pydantic import BaseModel, SkipValidation
2
+ from typing import List, Dict, Any, Optional, Type, Union, Tuple, Generator, Literal
3
+
4
+
5
+ # 工具结果类,由工具解析器使用
6
+ class ToolResult(BaseModel):
7
+ """
8
+ 工具执行结果
9
+ """
10
+ success: bool = False # 执行是否成功
11
+ message: str = "" # 结果消息
12
+ content: Any = None # 返回内容,可以是任何类型
13
+
14
+
15
+ # 工具的基本Pydantic模型
16
+ class BaseTool(BaseModel):
17
+ """
18
+ 代理工具的基类,所有工具类都应继承此类
19
+ """
20
+ pass
21
+
22
+
23
+ class ExecuteCommandTool(BaseTool):
24
+ command: str
25
+ requires_approval: bool
26
+
27
+ class ReadFileTool(BaseTool):
28
+ path: str
29
+
30
+ class WriteToFileTool(BaseTool):
31
+ path: str
32
+ content: str
33
+
34
+ class ReplaceInFileTool(BaseTool):
35
+ path: str
36
+ diff: str
37
+
38
+ class SearchFilesTool(BaseTool):
39
+ path: str
40
+ regex: str
41
+ file_pattern: Optional[str] = None
42
+
43
+ class ListFilesTool(BaseTool):
44
+ path: str
45
+ recursive: Optional[bool] = False
46
+
47
+ class AskFollowupQuestionTool(BaseTool):
48
+ question: str
49
+ options: Optional[List[str]] = None
50
+
51
+ class AttemptCompletionTool(BaseTool):
52
+ result: str
53
+ command: Optional[str] = None
54
+
55
+ class PlanModeRespondTool(BaseTool):
56
+ response: str
57
+ options: Optional[List[str]] = None
58
+
59
+ class UseMcpTool(BaseTool):
60
+ server_name: str
61
+ tool_name: str
62
+ query:str
63
+
64
+ class TalkToTool(BaseTool):
65
+ agent_name: str
66
+ content: str
67
+ mentions: List[str] = []
68
+ print_conversation: bool = False
69
+
70
+ class TalkToGroupTool(BaseTool):
71
+ group_name: str
72
+ content: str
73
+ mentions: List[str] = []
74
+ print_conversation: bool = False
75
+
76
+
77
+ # 工具指南相关类型
78
+ class ToolDescription(BaseModel):
79
+ """
80
+ 工具描述
81
+ """
82
+ description: str # 工具描述内容
83
+
84
+
85
+ class ToolExample(BaseModel):
86
+ """
87
+ 工具使用示例
88
+ """
89
+ title: str # 示例标题
90
+ body: str # 示例内容
91
+
92
+
93
+ class RoleDescription(BaseModel):
94
+ """
95
+ 代理角色描述
96
+ """
97
+ agent_type: str # 代理类型
98
+ description: str # 角色描述
99
+
100
+
101
+ # 事件类型,用于流式输出
102
+ class LLMOutputEvent(BaseModel):
103
+ """表示来自LLM的纯文本输出"""
104
+ text: str
105
+
106
+
107
+ class LLMThinkingEvent(BaseModel):
108
+ """表示来自LLM的<thinking>标签内的文本"""
109
+ text: str
110
+
111
+
112
+ class ToolCallEvent(BaseModel):
113
+ """表示LLM决定调用工具"""
114
+ tool: SkipValidation[BaseTool] # 使用SkipValidation因为BaseTool本身很复杂
115
+ tool_xml: str
116
+
117
+
118
+ class ToolResultEvent(BaseModel):
119
+ """表示执行工具的结果"""
120
+ tool_name: str
121
+ result: ToolResult
122
+
123
+
124
+ class TokenUsageEvent(BaseModel):
125
+ """表示Token使用情况"""
126
+ usage: Any
127
+
128
+
129
+ class CompletionEvent(BaseModel):
130
+ """表示LLM尝试完成任务"""
131
+ completion: Any # 完成的工具,使用Any以避免循环导入
132
+ completion_xml: str
133
+
134
+
135
+ class ErrorEvent(BaseModel):
136
+ """表示过程中的错误"""
137
+ message: str
138
+
139
+ class PlanModeRespondEvent(BaseModel):
140
+ """Represents the LLM attempting to complete the task."""
141
+ completion: SkipValidation[PlanModeRespondTool] # Skip validation
142
+ completion_xml: str
143
+
144
+
145
+ # 工具执行中的事件类型联合
146
+ AgentEvent = Union[
147
+ LLMOutputEvent,
148
+ LLMThinkingEvent,
149
+ ToolCallEvent,
150
+ ToolResultEvent,
151
+ TokenUsageEvent,
152
+ CompletionEvent,
153
+ ErrorEvent,
154
+ PlanModeRespondEvent
155
+ ]
156
+
157
+
158
+ # 文件变更记录
159
+ class FileChangeEntry(BaseModel):
160
+ """
161
+ 文件变更条目,用于记录文件的变更信息
162
+ """
163
+ type: str # 'added' 或 'modified'
164
+ diffs: List[str] = [] # 使用 replace_in_file 时,记录 diff 内容
165
+ content: Optional[str] = None # 使用 write_to_file 时,记录文件内容
166
+
167
+
168
+ # 代理编辑请求
169
+ class AgentRequest(BaseModel):
170
+ """
171
+ 代理请求
172
+ """
173
+ user_input: str
174
+
175
+
176
+ class Message(BaseModel):
177
+ sender: str
178
+ content: str
179
+ mentions: List[str] = []
180
+ is_group: bool = False
181
+ group_name: Optional[str] = None
182
+ reply_config: Dict[str, Any] = {}
183
+
184
+ class ReplyDecision(BaseModel):
185
+ content: str
186
+ strategy: Literal["broadcast", "private", "ignore"]
187
+ mentions: List[str] = []
188
+ priority: int = 0
189
+ reason: str = ""
@@ -0,0 +1,100 @@
1
+ from datetime import datetime
2
+ import typing
3
+
4
+ if typing.TYPE_CHECKING:
5
+ from .agent_hub import Group
6
+ import byzerllm
7
+ from typing import Union,List
8
+ from concurrent.futures import ThreadPoolExecutor
9
+ from pydantic import BaseModel
10
+ import threading
11
+ from loguru import logger
12
+ class GroupMember(BaseModel):
13
+ member: str
14
+ reason: str
15
+
16
+ class GroupMemberResponse(BaseModel):
17
+ group_name: str
18
+ members: List[GroupMember]
19
+
20
+ class GroupUtils:
21
+ _executor = ThreadPoolExecutor(max_workers=8)
22
+ _executor_lock = threading.Lock()
23
+
24
+ def __init__(self, llm: Union[byzerllm.ByzerLLM, byzerllm.SimpleByzerLLM]):
25
+ self.llm = llm
26
+
27
+ def auto_select_group(self, content: str, groups: List['Group']) -> List[GroupMemberResponse]:
28
+ futures = []
29
+ with self._executor_lock:
30
+ for group in groups:
31
+ future = self._executor.submit(
32
+ self._safe_select_group,
33
+ content,
34
+ group
35
+ )
36
+ futures.append((group.name, future))
37
+
38
+ results = []
39
+ for group_name, future in futures:
40
+ try:
41
+ members = future.result()
42
+ if members and len(members) > 0:
43
+ results.append(GroupMemberResponse(
44
+ group_name=group_name,
45
+ members=members
46
+ ))
47
+ except Exception as e:
48
+ import traceback
49
+ traceback.print_exc()
50
+ logger.error(f"Failed to select group {group_name}: {str(e)}")
51
+
52
+ return results
53
+
54
+ def _safe_select_group(self, content: str, group: 'Group') -> List[GroupMember]:
55
+ try:
56
+ return self.select_group.with_llm(self.llm).with_return_type(List[GroupMember]).run(content=content, group=group)
57
+ except Exception as e:
58
+ logger.error(f"Error in select_group: {str(e)}")
59
+ return []
60
+
61
+ @byzerllm.prompt()
62
+ def select_group(self, content: str, group: 'Group') -> List[GroupMember]:
63
+ '''
64
+ 当前时间: {{ time }}
65
+ 用户发来了如下问题:
66
+ <user_question>
67
+ {{ content }}
68
+ </user_question>
69
+
70
+ 下面是群组 {{ group_name }} 所有成员及其对应的角色:
71
+ {% for member_info in members_info %}
72
+ ===== {{ member_info[0] }} =====
73
+ <who_are_you>
74
+ {{ member_info[1] }}
75
+ </who_are_you>
76
+ {% endfor %}
77
+
78
+ 请分析该群组中的成员是否有人可以回答用户的问题。
79
+
80
+ 请生成 JSON 格式回复:
81
+
82
+ ```json
83
+ [
84
+ {
85
+ "member": "可以回答用户问题的用户名",
86
+ "reason": "选择这些用户的原因"
87
+ }
88
+ ]
89
+ ```
90
+ 如果群组中没有合适的成员可以回答问题,请返回空列表。
91
+ 请严格按照 JSON 格式输出,不要有任何多余的内容。
92
+ '''
93
+ members_info = [(member.name, member.system_prompt) for member in group.members]
94
+
95
+ context = {
96
+ "time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
97
+ "group_name": group.name,
98
+ "members_info": members_info
99
+ }
100
+ return context
@@ -231,7 +231,7 @@ def get_all_extensions(directory: str = ".") -> str:
231
231
  return ",".join(sorted(all_extensions))
232
232
 
233
233
  def configure_logger():
234
- # 设置日志目录和文件
234
+ # 设置日志目录和文件
235
235
  log_dir = os.path.join(project_root, ".auto-coder", "logs")
236
236
  os.makedirs(log_dir, exist_ok=True)
237
237
  log_file = os.path.join(log_dir, "auto-coder.log")
@@ -258,8 +258,6 @@ def configure_logger():
258
258
  ]
259
259
  )
260
260
 
261
- configure_logger()
262
-
263
261
  def init_singleton_instances():
264
262
  # 初始化文件监控系统
265
263
  try:
@@ -277,7 +275,9 @@ def init_singleton_instances():
277
275
  _ = IgnoreFileManager(project_root=project_root)
278
276
 
279
277
 
280
- init_singleton_instances()
278
+ if os.environ.get('autocoder_auto_init',"true") in ["true","True","True",True]:
279
+ configure_logger()
280
+ init_singleton_instances()
281
281
 
282
282
  def initialize_system(args:InitializeSystemRequest):
283
283
  from autocoder.utils.model_provider_selector import ModelProviderSelector
@@ -183,14 +183,15 @@ def _handle_help(memory: Dict[str, Any], args: List[str]) -> str:
183
183
 
184
184
  # Command dispatch table
185
185
  COMMAND_HANDLERS: Dict[str, Callable[[Dict[str, Any], List[str]], str]] = {
186
- "list": _handle_list_conf,
187
- "show": _handle_list_conf, # Alias
188
- "get": _handle_get_conf,
189
- "set": _handle_set_conf,
190
- "delete": _handle_delete_conf,
191
- "del": _handle_delete_conf, # Alias
192
- "rm": _handle_delete_conf, # Alias
193
- "help": _handle_help,
186
+ "/list": _handle_list_conf,
187
+ "/show": _handle_list_conf, # Alias
188
+ "/get": _handle_get_conf,
189
+ "/set": _handle_set_conf,
190
+ "/delete": _handle_delete_conf,
191
+ "/del": _handle_delete_conf, # Alias
192
+ "/rm": _handle_delete_conf, # Alias
193
+ "/drop": _handle_delete_conf, # Add this line for /drop command
194
+ "/help": _handle_help,
194
195
  }
195
196
 
196
197
  def handle_conf_command(command_args: str, memory: Dict[str, Any]) -> str:
@@ -205,7 +206,7 @@ def handle_conf_command(command_args: str, memory: Dict[str, Any]) -> str:
205
206
  Returns:
206
207
  A string response to be displayed to the user.
207
208
  """
208
- conf_str = command_args.strip()
209
+ conf_str = command_args.strip()
209
210
 
210
211
  # Handle special subcommands first
211
212
  if conf_str.startswith("/export"):
@@ -239,7 +240,7 @@ def handle_conf_command(command_args: str, memory: Dict[str, Any]) -> str:
239
240
  return _handle_list_conf(memory, [])
240
241
  else:
241
242
  command = args[0].lower()
242
- command_args_list = args[1:]
243
+ command_args_list = args[1:]
243
244
 
244
245
  # Check if the first argument is a known command or potentially a pattern
245
246
  handler = COMMAND_HANDLERS.get(command)
@@ -233,6 +233,25 @@ class AutocoderRulesManager:
233
233
  parsed_rules.append(parsed_rule)
234
234
  return parsed_rules
235
235
 
236
+ @classmethod
237
+ def reset_instance(cls):
238
+ """
239
+ 重置单例实例。
240
+ 如果当前实例正在运行,则先取消注册监控的目录,然后重置实例。
241
+ """
242
+ with cls._lock:
243
+ if cls._instance is not None:
244
+ # 取消注册监控的目录
245
+ if cls._instance._file_monitor:
246
+ for dir_path in cls._instance._monitored_dirs:
247
+ try:
248
+ cls._instance._file_monitor.unregister(dir_path)
249
+ logger.info(f"已取消注册目录监控: {dir_path}")
250
+ except Exception as e:
251
+ logger.warning(f"取消注册目录 {dir_path} 时出错: {e}")
252
+ cls._instance = None
253
+ logger.info("AutocoderRulesManager单例已被重置")
254
+
236
255
 
237
256
  # 对外提供单例
238
257
  _rules_manager = None
@@ -258,6 +277,11 @@ def parse_rule_file(file_path: str, project_root: Optional[str] = None) -> RuleF
258
277
  _rules_manager = AutocoderRulesManager(project_root=project_root)
259
278
  return _rules_manager.parse_rule_file(file_path)
260
279
 
280
+ def reset_rules_manager():
281
+ """重置AutocoderRulesManager单例实例"""
282
+ AutocoderRulesManager.reset_instance()
283
+ global _rules_manager
284
+ _rules_manager = None
261
285
 
262
286
  # 添加用于返回类型的Pydantic模型
263
287
  class RuleRelevance(BaseModel):
@@ -38,7 +38,7 @@ def save_formatted_log(project_root, json_text, suffix):
38
38
  md_content = "\n".join(md_lines)
39
39
 
40
40
  # Prepare directory
41
- logs_dir = os.path.join(project_root, ".cache", "logs")
41
+ logs_dir = os.path.join(project_root, ".auto-coder", "logs","agentic")
42
42
  os.makedirs(logs_dir, exist_ok=True)
43
43
 
44
44
  # Prepare filename