auto-coder 0.1.363__py3-none-any.whl → 0.1.365__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 (39) hide show
  1. {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/METADATA +2 -2
  2. {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/RECORD +39 -23
  3. autocoder/agent/base_agentic/tools/execute_command_tool_resolver.py +1 -1
  4. autocoder/auto_coder.py +46 -2
  5. autocoder/auto_coder_runner.py +2 -0
  6. autocoder/common/__init__.py +5 -0
  7. autocoder/common/file_checkpoint/__init__.py +21 -0
  8. autocoder/common/file_checkpoint/backup.py +264 -0
  9. autocoder/common/file_checkpoint/conversation_checkpoint.py +182 -0
  10. autocoder/common/file_checkpoint/examples.py +217 -0
  11. autocoder/common/file_checkpoint/manager.py +611 -0
  12. autocoder/common/file_checkpoint/models.py +156 -0
  13. autocoder/common/file_checkpoint/store.py +383 -0
  14. autocoder/common/file_checkpoint/test_backup.py +242 -0
  15. autocoder/common/file_checkpoint/test_manager.py +570 -0
  16. autocoder/common/file_checkpoint/test_models.py +360 -0
  17. autocoder/common/file_checkpoint/test_store.py +327 -0
  18. autocoder/common/file_checkpoint/test_utils.py +297 -0
  19. autocoder/common/file_checkpoint/utils.py +119 -0
  20. autocoder/common/rulefiles/autocoderrules_utils.py +114 -55
  21. autocoder/common/save_formatted_log.py +76 -5
  22. autocoder/common/utils_code_auto_generate.py +2 -1
  23. autocoder/common/v2/agent/agentic_edit.py +545 -225
  24. autocoder/common/v2/agent/agentic_edit_tools/list_files_tool_resolver.py +83 -43
  25. autocoder/common/v2/agent/agentic_edit_tools/read_file_tool_resolver.py +116 -29
  26. autocoder/common/v2/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +179 -48
  27. autocoder/common/v2/agent/agentic_edit_tools/search_files_tool_resolver.py +101 -56
  28. autocoder/common/v2/agent/agentic_edit_tools/test_write_to_file_tool_resolver.py +322 -0
  29. autocoder/common/v2/agent/agentic_edit_tools/write_to_file_tool_resolver.py +173 -132
  30. autocoder/common/v2/agent/agentic_edit_types.py +4 -0
  31. autocoder/compilers/normal_compiler.py +64 -0
  32. autocoder/events/event_manager_singleton.py +133 -4
  33. autocoder/linters/normal_linter.py +373 -0
  34. autocoder/linters/python_linter.py +4 -2
  35. autocoder/version.py +1 -1
  36. {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/LICENSE +0 -0
  37. {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/WHEEL +0 -0
  38. {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/entry_points.txt +0 -0
  39. {auto_coder-0.1.363.dist-info → auto_coder-0.1.365.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,182 @@
1
+ import os
2
+ import json
3
+ import time
4
+ import uuid
5
+ from typing import List, Dict, Any, Optional
6
+ from pydantic import BaseModel
7
+ from loguru import logger
8
+
9
+
10
+ class ConversationCheckpoint(BaseModel):
11
+ """对话检查点,用于保存特定时刻的对话状态"""
12
+
13
+ checkpoint_id: str # 检查点ID,与变更组ID对应
14
+ timestamp: float # 创建时间戳
15
+ conversations: List[Dict[str, Any]] # 对话历史
16
+ metadata: Optional[Dict[str, Any]] = None # 元数据,可包含额外信息
17
+
18
+
19
+ class ConversationCheckpointStore:
20
+ """对话检查点存储管理器"""
21
+
22
+ def __init__(self, store_dir: Optional[str] = None, max_history: int = 50):
23
+ """
24
+ 初始化对话检查点存储
25
+
26
+ Args:
27
+ store_dir: 存储目录,默认为用户主目录下的.autocoder/conversation_checkpoints
28
+ max_history: 最大保存的历史版本数量
29
+ """
30
+ if store_dir is None:
31
+ home_dir = os.path.expanduser("~")
32
+ store_dir = os.path.join(home_dir, ".autocoder", "conversation_checkpoints")
33
+
34
+ self.store_dir = os.path.abspath(store_dir)
35
+ self.max_history = max_history
36
+
37
+ # 确保存储目录存在
38
+ os.makedirs(self.store_dir, exist_ok=True)
39
+ logger.info(f"对话检查点存储目录: {self.store_dir}")
40
+
41
+ def save_checkpoint(self, checkpoint: ConversationCheckpoint) -> str:
42
+ """
43
+ 保存对话检查点
44
+
45
+ Args:
46
+ checkpoint: 对话检查点对象
47
+
48
+ Returns:
49
+ str: 检查点ID
50
+ """
51
+ # 确保检查点有ID
52
+ if not checkpoint.checkpoint_id:
53
+ checkpoint.checkpoint_id = str(uuid.uuid4())
54
+
55
+ # 确保时间戳存在
56
+ if not checkpoint.timestamp:
57
+ checkpoint.timestamp = time.time()
58
+
59
+ # 构建文件路径
60
+ file_path = os.path.join(self.store_dir, f"{checkpoint.checkpoint_id}.json")
61
+
62
+ # 保存为JSON文件
63
+ try:
64
+ with open(file_path, 'w', encoding='utf-8') as f:
65
+ f.write(checkpoint.json(ensure_ascii=False, indent=2))
66
+
67
+ logger.info(f"已保存对话检查点: {checkpoint.checkpoint_id}")
68
+
69
+ # 检查并清理过期的检查点
70
+ self._cleanup_old_checkpoints()
71
+
72
+ return checkpoint.checkpoint_id
73
+ except Exception as e:
74
+ logger.error(f"保存对话检查点失败: {str(e)}")
75
+ return ""
76
+
77
+ def get_checkpoint(self, checkpoint_id: str) -> Optional[ConversationCheckpoint]:
78
+ """
79
+ 获取指定ID的对话检查点
80
+
81
+ Args:
82
+ checkpoint_id: 检查点ID
83
+
84
+ Returns:
85
+ Optional[ConversationCheckpoint]: 对话检查点对象,如果不存在则返回None
86
+ """
87
+ file_path = os.path.join(self.store_dir, f"{checkpoint_id}.json")
88
+
89
+ if not os.path.exists(file_path):
90
+ logger.warning(f"对话检查点不存在: {checkpoint_id}")
91
+ return None
92
+
93
+ try:
94
+ with open(file_path, 'r', encoding='utf-8') as f:
95
+ data = json.load(f)
96
+
97
+ return ConversationCheckpoint(**data)
98
+ except Exception as e:
99
+ logger.error(f"读取对话检查点失败: {str(e)}")
100
+ return None
101
+
102
+ def get_latest_checkpoint(self) -> Optional[ConversationCheckpoint]:
103
+ """
104
+ 获取最新的对话检查点
105
+
106
+ Returns:
107
+ Optional[ConversationCheckpoint]: 最新的对话检查点对象,如果不存在则返回None
108
+ """
109
+ checkpoints = self._get_all_checkpoints()
110
+
111
+ if not checkpoints:
112
+ return None
113
+
114
+ # 按时间戳降序排序
115
+ checkpoints.sort(key=lambda x: x.timestamp, reverse=True)
116
+
117
+ return checkpoints[0] if checkpoints else None
118
+
119
+ def delete_checkpoint(self, checkpoint_id: str) -> bool:
120
+ """
121
+ 删除指定的对话检查点
122
+
123
+ Args:
124
+ checkpoint_id: 检查点ID
125
+
126
+ Returns:
127
+ bool: 是否成功删除
128
+ """
129
+ file_path = os.path.join(self.store_dir, f"{checkpoint_id}.json")
130
+
131
+ if not os.path.exists(file_path):
132
+ logger.warning(f"要删除的对话检查点不存在: {checkpoint_id}")
133
+ return False
134
+
135
+ try:
136
+ os.remove(file_path)
137
+ logger.info(f"已删除对话检查点: {checkpoint_id}")
138
+ return True
139
+ except Exception as e:
140
+ logger.error(f"删除对话检查点失败: {str(e)}")
141
+ return False
142
+
143
+ def _get_all_checkpoints(self) -> List[ConversationCheckpoint]:
144
+ """
145
+ 获取所有对话检查点
146
+
147
+ Returns:
148
+ List[ConversationCheckpoint]: 对话检查点列表
149
+ """
150
+ checkpoints = []
151
+
152
+ try:
153
+ for filename in os.listdir(self.store_dir):
154
+ if filename.endswith('.json'):
155
+ file_path = os.path.join(self.store_dir, filename)
156
+
157
+ try:
158
+ with open(file_path, 'r', encoding='utf-8') as f:
159
+ data = json.load(f)
160
+
161
+ checkpoint = ConversationCheckpoint(**data)
162
+ checkpoints.append(checkpoint)
163
+ except Exception as e:
164
+ logger.error(f"读取对话检查点文件失败 {filename}: {str(e)}")
165
+ except Exception as e:
166
+ logger.error(f"获取所有对话检查点失败: {str(e)}")
167
+
168
+ return checkpoints
169
+
170
+ def _cleanup_old_checkpoints(self):
171
+ """清理过期的检查点,保持历史记录数量在限制范围内"""
172
+ checkpoints = self._get_all_checkpoints()
173
+
174
+ if len(checkpoints) <= self.max_history:
175
+ return
176
+
177
+ # 按时间戳降序排序
178
+ checkpoints.sort(key=lambda x: x.timestamp, reverse=True)
179
+
180
+ # 删除超出限制的旧检查点
181
+ for checkpoint in checkpoints[self.max_history:]:
182
+ self.delete_checkpoint(checkpoint.checkpoint_id)
@@ -0,0 +1,217 @@
1
+ """
2
+ 文件变更管理模块的使用示例
3
+
4
+ 展示如何使用文件变更管理模块进行文件变更的应用和撤销。
5
+ """
6
+
7
+ import os
8
+ import sys
9
+ import json
10
+ from typing import Dict, Any
11
+
12
+ from autocoder.common.file_checkpoint.models import FileChange
13
+ from autocoder.common.file_checkpoint.manager import FileChangeManager
14
+
15
+
16
+ def example_apply_changes(project_dir: str):
17
+ """
18
+ 示例:应用文件变更
19
+
20
+ Args:
21
+ project_dir: 项目目录
22
+ """
23
+ print(f"示例:应用文件变更到项目 {project_dir}")
24
+
25
+ # 创建文件变更管理器
26
+ manager = FileChangeManager(project_dir)
27
+
28
+ # 准备文件变更
29
+ changes = {
30
+ "example.txt": FileChange(
31
+ file_path="example.txt",
32
+ content="这是一个示例文件\n用于演示文件变更管理模块的功能\n",
33
+ is_new=True
34
+ ),
35
+ "README.md": FileChange(
36
+ file_path="README.md",
37
+ content="# 示例项目\n\n这是一个用于演示文件变更管理模块的示例项目。\n",
38
+ is_new=True
39
+ )
40
+ }
41
+
42
+ # 应用变更
43
+ result = manager.apply_changes(changes)
44
+
45
+ # 输出结果
46
+ if result.success:
47
+ print(f"成功应用了 {len(result.change_ids)} 个文件变更")
48
+ for change_id in result.change_ids:
49
+ print(f" - 变更ID: {change_id}")
50
+ else:
51
+ print("应用变更失败")
52
+ for file_path, error in result.errors.items():
53
+ print(f" - {file_path}: {error}")
54
+
55
+
56
+ def example_preview_changes(project_dir: str):
57
+ """
58
+ 示例:预览文件变更
59
+
60
+ Args:
61
+ project_dir: 项目目录
62
+ """
63
+ print(f"示例:预览文件变更")
64
+
65
+ # 创建文件变更管理器
66
+ manager = FileChangeManager(project_dir)
67
+
68
+ # 准备文件变更
69
+ changes = {
70
+ "example.txt": FileChange(
71
+ file_path="example.txt",
72
+ content="这是一个修改后的示例文件\n用于演示文件变更管理模块的功能\n新增的一行\n",
73
+ is_new=False
74
+ )
75
+ }
76
+
77
+ # 预览变更
78
+ diff_results = manager.preview_changes(changes)
79
+
80
+ # 输出差异
81
+ for file_path, diff_result in diff_results.items():
82
+ print(f"\n文件: {file_path}")
83
+ print(diff_result.get_diff_summary())
84
+ if diff_result.old_content is not None and not diff_result.is_new and not diff_result.is_deletion:
85
+ diff_text = manager.get_diff_text(diff_result.old_content, diff_result.new_content)
86
+ print("\n差异:")
87
+ print(diff_text)
88
+
89
+
90
+ def example_undo_changes(project_dir: str):
91
+ """
92
+ 示例:撤销文件变更
93
+
94
+ Args:
95
+ project_dir: 项目目录
96
+ """
97
+ print(f"示例:撤销文件变更")
98
+
99
+ # 创建文件变更管理器
100
+ manager = FileChangeManager(project_dir)
101
+
102
+ # 撤销最近的变更
103
+ result = manager.undo_last_change()
104
+
105
+ # 输出结果
106
+ if result.success:
107
+ print(f"成功撤销了变更,恢复了 {len(result.restored_files)} 个文件")
108
+ for file_path in result.restored_files:
109
+ print(f" - {file_path}")
110
+ else:
111
+ print("撤销变更失败")
112
+ for file_path, error in result.errors.items():
113
+ print(f" - {file_path}: {error}")
114
+
115
+
116
+ def example_get_history(project_dir: str):
117
+ """
118
+ 示例:获取变更历史
119
+
120
+ Args:
121
+ project_dir: 项目目录
122
+ """
123
+ print(f"示例:获取变更历史")
124
+
125
+ # 创建文件变更管理器
126
+ manager = FileChangeManager(project_dir)
127
+
128
+ # 获取变更历史
129
+ changes = manager.get_change_history(limit=5)
130
+
131
+ # 输出历史记录
132
+ print(f"最近 {len(changes)} 条变更记录:")
133
+ for change in changes:
134
+ timestamp = change.timestamp
135
+ file_path = change.file_path
136
+ change_type = "新建" if change.is_new else "删除" if change.is_deletion else "修改"
137
+ print(f" - [{timestamp}] {change_type} {file_path} (ID: {change.change_id})")
138
+
139
+
140
+ def example_integration_with_agentic_edit():
141
+ """
142
+ 示例:与 AgenticEdit 集成
143
+
144
+ 展示如何将文件变更管理模块集成到 AgenticEdit 中
145
+ """
146
+ print("示例:与 AgenticEdit 集成")
147
+
148
+ # 这是一个伪代码示例,展示如何修改 AgenticEdit.apply_changes 方法
149
+ code = """
150
+ def apply_changes(self):
151
+ \"\"\"
152
+ Apply all tracked file changes to the original project directory.
153
+ \"\"\"
154
+ from autocoder.common.file_checkpoint.models import FileChange
155
+ from autocoder.common.file_checkpoint.manager import FileChangeManager
156
+
157
+ # 创建文件变更管理器
158
+ manager = FileChangeManager(self.args.source_dir)
159
+
160
+ # 将影子系统的变更转换为 FileChange 对象
161
+ changes = {}
162
+ for file_path, change in self.get_all_file_changes().items():
163
+ changes[file_path] = FileChange(
164
+ file_path=file_path,
165
+ content=change.content,
166
+ is_new=not os.path.exists(file_path)
167
+ )
168
+
169
+ # 应用变更
170
+ result = manager.apply_changes(changes)
171
+
172
+ # 处理结果
173
+ if result.success:
174
+ # 继续执行原有的 Git 提交等逻辑
175
+ if not self.args.skip_commit:
176
+ try:
177
+ # ... 原有的 Git 提交代码 ...
178
+ except Exception as e:
179
+ # ... 原有的错误处理 ...
180
+ else:
181
+ # 处理应用变更失败的情况
182
+ error_messages = "\\n".join([f"{path}: {error}" for path, error in result.errors.items()])
183
+ self.printer.print_str_in_terminal(
184
+ f"Failed to apply changes:\\n{error_messages}",
185
+ style="red"
186
+ )
187
+ """
188
+
189
+ print(code)
190
+
191
+
192
+ def main():
193
+ """主函数"""
194
+ if len(sys.argv) < 2:
195
+ print("用法: python examples.py <项目目录>")
196
+ return
197
+
198
+ project_dir = sys.argv[1]
199
+
200
+ # 运行示例
201
+ example_apply_changes(project_dir)
202
+ print("\n" + "-" * 50 + "\n")
203
+
204
+ example_preview_changes(project_dir)
205
+ print("\n" + "-" * 50 + "\n")
206
+
207
+ example_get_history(project_dir)
208
+ print("\n" + "-" * 50 + "\n")
209
+
210
+ example_undo_changes(project_dir)
211
+ print("\n" + "-" * 50 + "\n")
212
+
213
+ example_integration_with_agentic_edit()
214
+
215
+
216
+ if __name__ == "__main__":
217
+ main()