auto-coder 0.1.399__py3-none-any.whl → 1.0.0__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 (71) hide show
  1. {auto_coder-0.1.399.dist-info → auto_coder-1.0.0.dist-info}/METADATA +1 -1
  2. {auto_coder-0.1.399.dist-info → auto_coder-1.0.0.dist-info}/RECORD +71 -35
  3. autocoder/agent/agentic_filter.py +1 -1
  4. autocoder/agent/base_agentic/tools/read_file_tool_resolver.py +1 -1
  5. autocoder/auto_coder_runner.py +121 -26
  6. autocoder/chat_auto_coder.py +81 -22
  7. autocoder/commands/auto_command.py +1 -1
  8. autocoder/common/__init__.py +2 -2
  9. autocoder/common/ac_style_command_parser/parser.py +27 -12
  10. autocoder/common/auto_coder_lang.py +78 -0
  11. autocoder/common/command_completer_v2.py +1 -1
  12. autocoder/common/file_monitor/test_file_monitor.py +307 -0
  13. autocoder/common/git_utils.py +7 -2
  14. autocoder/common/pruner/__init__.py +0 -0
  15. autocoder/common/pruner/agentic_conversation_pruner.py +197 -0
  16. autocoder/common/pruner/context_pruner.py +574 -0
  17. autocoder/common/pruner/conversation_pruner.py +132 -0
  18. autocoder/common/pruner/test_agentic_conversation_pruner.py +342 -0
  19. autocoder/common/pruner/test_context_pruner.py +546 -0
  20. autocoder/common/pull_requests/__init__.py +256 -0
  21. autocoder/common/pull_requests/base_provider.py +191 -0
  22. autocoder/common/pull_requests/config.py +66 -0
  23. autocoder/common/pull_requests/example.py +1 -0
  24. autocoder/common/pull_requests/exceptions.py +46 -0
  25. autocoder/common/pull_requests/manager.py +201 -0
  26. autocoder/common/pull_requests/models.py +164 -0
  27. autocoder/common/pull_requests/providers/__init__.py +23 -0
  28. autocoder/common/pull_requests/providers/gitcode_provider.py +19 -0
  29. autocoder/common/pull_requests/providers/gitee_provider.py +20 -0
  30. autocoder/common/pull_requests/providers/github_provider.py +214 -0
  31. autocoder/common/pull_requests/providers/gitlab_provider.py +29 -0
  32. autocoder/common/pull_requests/test_module.py +1 -0
  33. autocoder/common/pull_requests/utils.py +344 -0
  34. autocoder/common/tokens/__init__.py +77 -0
  35. autocoder/common/tokens/counter.py +231 -0
  36. autocoder/common/tokens/file_detector.py +105 -0
  37. autocoder/common/tokens/filters.py +111 -0
  38. autocoder/common/tokens/models.py +28 -0
  39. autocoder/common/v2/agent/agentic_edit.py +538 -590
  40. autocoder/common/v2/agent/agentic_edit_tools/__init__.py +8 -1
  41. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_read_tool_resolver.py +40 -0
  42. autocoder/common/v2/agent/agentic_edit_tools/ac_mod_write_tool_resolver.py +43 -0
  43. autocoder/common/v2/agent/agentic_edit_tools/ask_followup_question_tool_resolver.py +8 -0
  44. autocoder/common/v2/agent/agentic_edit_tools/execute_command_tool_resolver.py +1 -1
  45. autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +1 -1
  46. autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py +33 -88
  47. autocoder/common/v2/agent/agentic_edit_tools/test_write_to_file_tool_resolver.py +8 -8
  48. autocoder/common/v2/agent/agentic_edit_tools/todo_read_tool_resolver.py +118 -0
  49. autocoder/common/v2/agent/agentic_edit_tools/todo_write_tool_resolver.py +324 -0
  50. autocoder/common/v2/agent/agentic_edit_types.py +47 -4
  51. autocoder/common/v2/agent/runner/__init__.py +31 -0
  52. autocoder/common/v2/agent/runner/base_runner.py +106 -0
  53. autocoder/common/v2/agent/runner/event_runner.py +216 -0
  54. autocoder/common/v2/agent/runner/sdk_runner.py +40 -0
  55. autocoder/common/v2/agent/runner/terminal_runner.py +283 -0
  56. autocoder/common/v2/agent/runner/tool_display.py +191 -0
  57. autocoder/index/entry.py +1 -1
  58. autocoder/plugins/token_helper_plugin.py +107 -7
  59. autocoder/run_context.py +9 -0
  60. autocoder/sdk/__init__.py +114 -81
  61. autocoder/sdk/cli/handlers.py +2 -1
  62. autocoder/sdk/cli/main.py +9 -2
  63. autocoder/sdk/cli/options.py +4 -3
  64. autocoder/sdk/core/auto_coder_core.py +7 -152
  65. autocoder/sdk/core/bridge.py +5 -4
  66. autocoder/sdk/models/options.py +8 -6
  67. autocoder/version.py +1 -1
  68. {auto_coder-0.1.399.dist-info → auto_coder-1.0.0.dist-info}/WHEEL +0 -0
  69. {auto_coder-0.1.399.dist-info → auto_coder-1.0.0.dist-info}/entry_points.txt +0 -0
  70. {auto_coder-0.1.399.dist-info → auto_coder-1.0.0.dist-info}/licenses/LICENSE +0 -0
  71. {auto_coder-0.1.399.dist-info → auto_coder-1.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,324 @@
1
+ from typing import Dict, Any, Optional, List
2
+ from autocoder.common.v2.agent.agentic_edit_tools.base_tool_resolver import BaseToolResolver
3
+ from autocoder.common.v2.agent.agentic_edit_types import TodoWriteTool, ToolResult
4
+ from loguru import logger
5
+ import typing
6
+ from autocoder.common import AutoCoderArgs
7
+ import os
8
+ import json
9
+ import uuid
10
+ from datetime import datetime
11
+
12
+ if typing.TYPE_CHECKING:
13
+ from autocoder.common.v2.agent.agentic_edit import AgenticEdit
14
+
15
+
16
+ class TodoWriteToolResolver(BaseToolResolver):
17
+ def __init__(self, agent: Optional['AgenticEdit'], tool: TodoWriteTool, args: AutoCoderArgs):
18
+ super().__init__(agent, tool, args)
19
+ self.tool: TodoWriteTool = tool # For type hinting
20
+
21
+ def _get_todo_file_path(self) -> str:
22
+ """Get the path to the todo file for this session."""
23
+ source_dir = self.args.source_dir or "."
24
+ todo_dir = os.path.join(source_dir, ".auto-coder", "todos")
25
+ os.makedirs(todo_dir, exist_ok=True)
26
+ return os.path.join(todo_dir, "current_session.json")
27
+
28
+ def _load_todos(self) -> Dict[str, Any]:
29
+ """Load todos from the session file."""
30
+ todo_file = self._get_todo_file_path()
31
+ if not os.path.exists(todo_file):
32
+ return {
33
+ "created_at": datetime.now().isoformat(),
34
+ "updated_at": datetime.now().isoformat(),
35
+ "todos": []
36
+ }
37
+
38
+ try:
39
+ with open(todo_file, 'r', encoding='utf-8') as f:
40
+ return json.load(f)
41
+ except Exception as e:
42
+ logger.warning(f"Failed to load todos: {e}")
43
+ return {
44
+ "created_at": datetime.now().isoformat(),
45
+ "updated_at": datetime.now().isoformat(),
46
+ "todos": []
47
+ }
48
+
49
+ def _save_todos(self, data: Dict[str, Any]) -> bool:
50
+ """Save todos to the session file."""
51
+ try:
52
+ todo_file = self._get_todo_file_path()
53
+ data["updated_at"] = datetime.now().isoformat()
54
+
55
+ with open(todo_file, 'w', encoding='utf-8') as f:
56
+ json.dump(data, f, ensure_ascii=False, indent=2)
57
+ return True
58
+ except Exception as e:
59
+ logger.error(f"Failed to save todos: {e}")
60
+ return False
61
+
62
+ def _generate_todo_id(self) -> str:
63
+ """Generate a unique ID for a todo item."""
64
+ return str(uuid.uuid4())[:8]
65
+
66
+ def _find_todo_by_id(self, todos: List[Dict[str, Any]], task_id: str) -> Optional[Dict[str, Any]]:
67
+ """Find a todo item by ID."""
68
+ for todo in todos:
69
+ if todo.get('id') == task_id:
70
+ return todo
71
+ return None
72
+
73
+ def _create_todo_list(self, content: str) -> List[Dict[str, Any]]:
74
+ """Create a new todo list from content."""
75
+ import re
76
+
77
+ todos = []
78
+
79
+ # First, try to parse <task> tags
80
+ task_pattern = r'<task>(.*?)</task>'
81
+ task_matches = re.findall(task_pattern, content, re.DOTALL)
82
+
83
+ if task_matches:
84
+ # Found <task> tags, use them
85
+ for task_content in task_matches:
86
+ task_content = task_content.strip()
87
+ if task_content:
88
+ todo = {
89
+ "id": self._generate_todo_id(),
90
+ "content": task_content,
91
+ "status": "pending",
92
+ "priority": self.tool.priority or "medium",
93
+ "created_at": datetime.now().isoformat(),
94
+ "updated_at": datetime.now().isoformat()
95
+ }
96
+
97
+ if self.tool.notes:
98
+ todo["notes"] = self.tool.notes
99
+
100
+ todos.append(todo)
101
+ else:
102
+ # Fallback to original line-by-line parsing
103
+ lines = content.strip().split('\n')
104
+
105
+ for line in lines:
106
+ line = line.strip()
107
+ if not line:
108
+ continue
109
+
110
+ # Remove common prefixes like "1.", "- ", "* ", etc.
111
+ line = line.lstrip('0123456789.- *\t')
112
+
113
+ if line:
114
+ todo = {
115
+ "id": self._generate_todo_id(),
116
+ "content": line,
117
+ "status": "pending",
118
+ "priority": self.tool.priority or "medium",
119
+ "created_at": datetime.now().isoformat(),
120
+ "updated_at": datetime.now().isoformat()
121
+ }
122
+
123
+ if self.tool.notes:
124
+ todo["notes"] = self.tool.notes
125
+
126
+ todos.append(todo)
127
+
128
+ return todos
129
+
130
+ def _add_single_task(self, todos: List[Dict[str, Any]], content: str) -> Dict[str, Any]:
131
+ """Add a single task to the existing todo list."""
132
+ import re
133
+
134
+ # Check if content contains <task> tags
135
+ task_pattern = r'<task>(.*?)</task>'
136
+ task_matches = re.findall(task_pattern, content, re.DOTALL)
137
+
138
+ if task_matches:
139
+ # If <task> tags found, use the first one
140
+ task_content = task_matches[0].strip()
141
+ else:
142
+ # Use the content as-is
143
+ task_content = content.strip()
144
+
145
+ todo = {
146
+ "id": self._generate_todo_id(),
147
+ "content": task_content,
148
+ "status": self.tool.status or "pending",
149
+ "priority": self.tool.priority or "medium",
150
+ "created_at": datetime.now().isoformat(),
151
+ "updated_at": datetime.now().isoformat()
152
+ }
153
+
154
+ if self.tool.notes:
155
+ todo["notes"] = self.tool.notes
156
+
157
+ todos.append(todo)
158
+ return todo
159
+
160
+ def _update_task(self, todo: Dict[str, Any]) -> None:
161
+ """Update an existing task."""
162
+ if self.tool.content:
163
+ todo["content"] = self.tool.content
164
+ if self.tool.status:
165
+ todo["status"] = self.tool.status
166
+ if self.tool.priority:
167
+ todo["priority"] = self.tool.priority
168
+ if self.tool.notes:
169
+ todo["notes"] = self.tool.notes
170
+
171
+ todo["updated_at"] = datetime.now().isoformat()
172
+
173
+ def _format_todo_response(self, todos: List[Dict[str, Any]], action_performed: str) -> str:
174
+ """Format the response message after todo operations."""
175
+ if not todos:
176
+ return f"Operation completed: {action_performed}"
177
+
178
+ # Show the latest todos
179
+ recent_todos = todos[-3:] if len(todos) > 3 else todos
180
+
181
+ output = [f"✅ Operation completed: {action_performed}\n"]
182
+
183
+ if action_performed.startswith("Created"):
184
+ output.append("📝 Newly created todos:")
185
+ for todo in recent_todos:
186
+ priority_icon = {"high": "🔴", "medium": "🟡", "low": "🟢"}.get(todo.get('priority', 'medium'), "⚪")
187
+ status_icon = {"pending": "⏳", "in_progress": "🔄", "completed": "✅"}.get(todo.get('status', 'pending'), "⏳")
188
+ output.append(f" {priority_icon} {status_icon} [{todo['id']}] {todo['content']}")
189
+
190
+ elif action_performed.startswith("Updated") or action_performed.startswith("Marked"):
191
+ output.append("📝 Updated todos:")
192
+ for todo in recent_todos:
193
+ priority_icon = {"high": "🔴", "medium": "🟡", "low": "🟢"}.get(todo.get('priority', 'medium'), "⚪")
194
+ status_icon = {"pending": "⏳", "in_progress": "🔄", "completed": "✅"}.get(todo.get('status', 'pending'), "⏳")
195
+ output.append(f" {priority_icon} {status_icon} [{todo['id']}] {todo['content']}")
196
+
197
+ total_todos = len(todos)
198
+ pending_count = len([t for t in todos if t.get('status') == 'pending'])
199
+ in_progress_count = len([t for t in todos if t.get('status') == 'in_progress'])
200
+ completed_count = len([t for t in todos if t.get('status') == 'completed'])
201
+
202
+ output.append(f"\n📊 Current summary: Total {total_todos} items | Pending {pending_count} | In Progress {in_progress_count} | Completed {completed_count}")
203
+
204
+ return "\n".join(output)
205
+
206
+ def resolve(self) -> ToolResult:
207
+ """
208
+ Create and manage a structured task list based on the action specified.
209
+ """
210
+ try:
211
+ action = self.tool.action.lower()
212
+ logger.info(f"Performing todo action: {action}")
213
+
214
+ # Load existing todos
215
+ data = self._load_todos()
216
+ todos = data["todos"]
217
+
218
+ if action == "create":
219
+ if not self.tool.content:
220
+ return ToolResult(
221
+ success=False,
222
+ message="Error: Content is required for creating todos.",
223
+ content=None
224
+ )
225
+
226
+ # Clear existing todos and create new ones
227
+ new_todos = self._create_todo_list(self.tool.content)
228
+ data["todos"] = new_todos
229
+
230
+ if self._save_todos(data):
231
+ response = self._format_todo_response(new_todos, f"Created {len(new_todos)} new todo items")
232
+ return ToolResult(
233
+ success=True,
234
+ message="Todo list created successfully.",
235
+ content=response
236
+ )
237
+ else:
238
+ return ToolResult(
239
+ success=False,
240
+ message="Failed to save todo list.",
241
+ content=None
242
+ )
243
+
244
+ elif action == "add_task":
245
+ if not self.tool.content:
246
+ return ToolResult(
247
+ success=False,
248
+ message="Error: Content is required for adding a task.",
249
+ content=None
250
+ )
251
+
252
+ new_todo = self._add_single_task(todos, self.tool.content)
253
+
254
+ if self._save_todos(data):
255
+ response = self._format_todo_response([new_todo], f"Added new task: {new_todo['content']}")
256
+ return ToolResult(
257
+ success=True,
258
+ message="Task added successfully.",
259
+ content=response
260
+ )
261
+ else:
262
+ return ToolResult(
263
+ success=False,
264
+ message="Failed to save new task.",
265
+ content=None
266
+ )
267
+
268
+ elif action in ["update", "mark_progress", "mark_completed"]:
269
+ if not self.tool.task_id:
270
+ return ToolResult(
271
+ success=False,
272
+ message="Error: Task ID is required for update operations.",
273
+ content=None
274
+ )
275
+
276
+ todo = self._find_todo_by_id(todos, self.tool.task_id)
277
+ if not todo:
278
+ return ToolResult(
279
+ success=False,
280
+ message=f"Error: Task with ID '{self.tool.task_id}' not found.",
281
+ content=None
282
+ )
283
+
284
+ # Apply specific action
285
+ if action == "mark_progress":
286
+ todo["status"] = "in_progress"
287
+ todo["updated_at"] = datetime.now().isoformat()
288
+ action_msg = f"Marked task as in progress: {todo['content']}"
289
+ elif action == "mark_completed":
290
+ todo["status"] = "completed"
291
+ todo["updated_at"] = datetime.now().isoformat()
292
+ action_msg = f"Marked task as completed: {todo['content']}"
293
+ else: # update
294
+ self._update_task(todo)
295
+ action_msg = f"Updated task: {todo['content']}"
296
+
297
+ if self._save_todos(data):
298
+ response = self._format_todo_response([todo], action_msg)
299
+ return ToolResult(
300
+ success=True,
301
+ message="Task updated successfully.",
302
+ content=response
303
+ )
304
+ else:
305
+ return ToolResult(
306
+ success=False,
307
+ message="Failed to save task update.",
308
+ content=None
309
+ )
310
+
311
+ else:
312
+ return ToolResult(
313
+ success=False,
314
+ message=f"Error: Unknown action '{action}'. Supported actions: create, add_task, update, mark_progress, mark_completed.",
315
+ content=None
316
+ )
317
+
318
+ except Exception as e:
319
+ logger.error(f"Error in todo write operation: {e}")
320
+ return ToolResult(
321
+ success=False,
322
+ message=f"Failed to perform todo operation: {str(e)}",
323
+ content=None
324
+ )
@@ -1,5 +1,5 @@
1
1
  from pydantic import BaseModel
2
- from typing import List, Dict, Any, Callable, Optional, Type
2
+ from typing import List, Dict, Any, Callable, Optional, Type, Union
3
3
  from pydantic import SkipValidation
4
4
 
5
5
  # Result class used by Tool Resolvers
@@ -60,9 +60,34 @@ class UseRAGTool(BaseTool):
60
60
  server_name: str
61
61
  query: str
62
62
 
63
- class ListPackageInfoTool(BaseTool):
63
+ class ACModReadTool(BaseTool):
64
64
  path: str # 源码包目录,相对路径或绝对路径
65
65
 
66
+ class ACModWriteTool(BaseTool):
67
+ """
68
+ Tool for creating or updating an AC Module's .ac.mod.md file.
69
+ """
70
+ path: str # AC Module directory path, relative or absolute path
71
+ diff: str # diff content to edit the .ac.mod.md file
72
+
73
+ class TodoReadTool(BaseTool):
74
+ """
75
+ Tool for reading the current todo list.
76
+ Takes no parameters.
77
+ """
78
+ pass # No parameters needed
79
+
80
+ class TodoWriteTool(BaseTool):
81
+ """
82
+ Tool for creating and managing a structured task list.
83
+ """
84
+ action: str # 'create', 'update', 'mark_progress', 'mark_completed', 'add_task'
85
+ task_id: Optional[str] = None # Task ID for update/mark operations
86
+ content: Optional[str] = None # Task content for create/add operations
87
+ priority: Optional[str] = None # 'high', 'medium', 'low'
88
+ status: Optional[str] = None # 'pending', 'in_progress', 'completed'
89
+ notes: Optional[str] = None # Additional notes for the task
90
+
66
91
  # Event Types for Rich Output Streaming
67
92
  class LLMOutputEvent(BaseModel):
68
93
  """Represents plain text output from the LLM."""
@@ -109,6 +134,20 @@ class WindowLengthChangeEvent(BaseModel):
109
134
  """Represents the token usage in the conversation window."""
110
135
  tokens_used: int
111
136
 
137
+ # Base event class for all agent events
138
+ class AgentEvent(BaseModel):
139
+ """Base class for all agent events."""
140
+ pass
141
+
142
+ # Metadata for token usage tracking
143
+ class SingleOutputMeta(BaseModel):
144
+ """Metadata for tracking token usage for a single LLM output."""
145
+ model_name: str
146
+ input_tokens: int
147
+ output_tokens: int
148
+ input_cost: float
149
+ output_cost: float
150
+
112
151
  # Deprecated: Will be replaced by specific Event types
113
152
  # class PlainTextOutput(BaseModel):
114
153
  # text: str
@@ -127,8 +166,11 @@ TOOL_MODEL_MAP: Dict[str, Type[BaseTool]] = {
127
166
  "attempt_completion": AttemptCompletionTool,
128
167
  "plan_mode_respond": PlanModeRespondTool,
129
168
  "use_mcp_tool": UseMcpTool,
130
- "use_rag_tool": UseRAGTool,
131
- "list_package_info": ListPackageInfoTool,
169
+ "use_rag_tool": UseRAGTool,
170
+ "todo_read": TodoReadTool,
171
+ "todo_write": TodoWriteTool,
172
+ "ac_mod_read": ACModReadTool,
173
+ "ac_mod_write": ACModWriteTool,
132
174
  }
133
175
 
134
176
  class FileChangeEntry(BaseModel):
@@ -187,3 +229,4 @@ class AgenticEditConversationConfig(BaseModel):
187
229
  conversation_id: Optional[str] = None
188
230
  action: Optional[str] = None
189
231
  query: Optional[str] = None
232
+ pull_request: bool = False
@@ -0,0 +1,31 @@
1
+ """
2
+ Runner 模块提供了多种运行模式,用于在不同环境下执行 AgenticEdit 代理。
3
+
4
+ 这个模块包含三种主要的运行器:
5
+ 1. TerminalRunner: 在终端环境中运行代理,提供格式化输出
6
+ 2. EventRunner: 将代理事件转换为标准事件系统格式
7
+ 3. SdkRunner: 提供生成器接口,适用于SDK环境
8
+
9
+ 使用示例:
10
+ ```python
11
+ from autocoder.common.v2.agent.runner import TerminalRunner
12
+ from autocoder.common.v2.agent.agentic_edit_types import AgenticEditRequest
13
+
14
+ runner = TerminalRunner(llm=llm, args=args, ...)
15
+ runner.run(AgenticEditRequest(user_input="请帮我实现一个HTTP服务器"))
16
+ ```
17
+ """
18
+
19
+ from .base_runner import BaseRunner
20
+ from .terminal_runner import TerminalRunner
21
+ from .event_runner import EventRunner
22
+ from .sdk_runner import SdkRunner
23
+ from .tool_display import get_tool_display_message
24
+
25
+ __all__ = [
26
+ "BaseRunner",
27
+ "TerminalRunner",
28
+ "EventRunner",
29
+ "SdkRunner",
30
+ "get_tool_display_message"
31
+ ]
@@ -0,0 +1,106 @@
1
+ """
2
+ BaseRunner 提供了所有运行器的基础实现和接口定义。
3
+
4
+ 这个模块定义了代理运行的核心流程,包括请求处理、事件流生成和变更应用等。
5
+ 各种具体运行器通过继承 BaseRunner 并实现特定的运行逻辑来提供不同的运行模式。
6
+ """
7
+
8
+ import logging
9
+ from typing import Generator, Any, Dict, Optional, Callable, List
10
+
11
+ from autocoder.common.v2.agent.agentic_edit_types import (
12
+ AgenticEditRequest, AgentEvent, CompletionEvent,
13
+ AgenticEditConversationConfig, CommandConfig, MemoryConfig
14
+ )
15
+ from autocoder.common import AutoCoderArgs, SourceCodeList
16
+ from autocoder.common.v2.agent.agentic_edit import AgenticEdit
17
+ from autocoder.common.printer import Printer
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+ class BaseRunner:
22
+ """
23
+ 代理运行器的基类,定义了运行代理的核心流程和接口。
24
+
25
+ 所有具体的运行器实现(终端、事件系统、SDK)都应该继承这个类,
26
+ 并根据特定需求实现 run 方法。
27
+ """
28
+
29
+ def __init__(
30
+ self,
31
+ llm: Any,
32
+ conversation_history: List[Dict[str, Any]],
33
+ files: SourceCodeList,
34
+ args: AutoCoderArgs,
35
+ memory_config: MemoryConfig,
36
+ command_config: Optional[CommandConfig] = None,
37
+ conversation_name: str = "current",
38
+ conversation_config: Optional[AgenticEditConversationConfig] = None
39
+ ):
40
+ """
41
+ 初始化代理运行器。
42
+
43
+ Args:
44
+ llm: 大语言模型实例
45
+ conversation_history: 对话历史
46
+ files: 源代码文件列表
47
+ args: 自动编码器参数
48
+ memory_config: 内存配置
49
+ command_config: 命令配置(可选)
50
+ conversation_name: 会话名称(默认为"current")
51
+ conversation_config: 会话配置(可选)
52
+ """
53
+ self.llm = llm
54
+ self.conversation_history = conversation_history
55
+ self.files = files
56
+ self.args = args
57
+ self.memory_config = memory_config
58
+ self.command_config = command_config
59
+ self.conversation_name = conversation_name
60
+ self.conversation_config = conversation_config
61
+ self.printer = Printer()
62
+
63
+ self.agent = AgenticEdit(
64
+ llm=llm,
65
+ conversation_history=conversation_history,
66
+ files=files,
67
+ args=args,
68
+ memory_config=memory_config,
69
+ command_config=command_config,
70
+ conversation_name=conversation_name,
71
+ conversation_config=conversation_config
72
+ )
73
+
74
+ def run(self, request: AgenticEditRequest) -> Any:
75
+ """
76
+ 运行代理处理请求。
77
+
78
+ 这是一个抽象方法,需要由子类实现。
79
+
80
+ Args:
81
+ request: 代理编辑请求
82
+
83
+ Returns:
84
+ 根据具体实现返回不同类型的结果
85
+ """
86
+ raise NotImplementedError("子类必须实现run方法")
87
+
88
+ def apply_pre_changes(self) -> None:
89
+ """应用预处理变更"""
90
+ self.agent.apply_pre_changes()
91
+
92
+ def apply_changes(self) -> None:
93
+ """应用代理执行后的变更"""
94
+ self.agent.apply_changes()
95
+
96
+ def analyze(self, request: AgenticEditRequest) -> Generator[AgentEvent, None, None]:
97
+ """
98
+ 分析请求并生成事件流。
99
+
100
+ Args:
101
+ request: 代理编辑请求
102
+
103
+ Returns:
104
+ 事件生成器
105
+ """
106
+ return self.agent.analyze(request)