auto-coder 0.1.316__py3-none-any.whl → 0.1.318__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 (41) hide show
  1. {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/METADATA +2 -2
  2. {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/RECORD +41 -20
  3. autocoder/auto_coder_runner.py +1 -2
  4. autocoder/common/__init__.py +3 -0
  5. autocoder/common/auto_coder_lang.py +24 -0
  6. autocoder/common/code_auto_merge_editblock.py +2 -42
  7. autocoder/common/git_utils.py +2 -2
  8. autocoder/common/token_cost_caculate.py +103 -42
  9. autocoder/common/v2/__init__.py +0 -0
  10. autocoder/common/v2/code_auto_generate.py +199 -0
  11. autocoder/common/v2/code_auto_generate_diff.py +361 -0
  12. autocoder/common/v2/code_auto_generate_editblock.py +380 -0
  13. autocoder/common/v2/code_auto_generate_strict_diff.py +269 -0
  14. autocoder/common/v2/code_auto_merge.py +211 -0
  15. autocoder/common/v2/code_auto_merge_diff.py +354 -0
  16. autocoder/common/v2/code_auto_merge_editblock.py +523 -0
  17. autocoder/common/v2/code_auto_merge_strict_diff.py +259 -0
  18. autocoder/common/v2/code_diff_manager.py +266 -0
  19. autocoder/common/v2/code_editblock_manager.py +282 -0
  20. autocoder/common/v2/code_manager.py +238 -0
  21. autocoder/common/v2/code_strict_diff_manager.py +241 -0
  22. autocoder/dispacher/actions/action.py +16 -0
  23. autocoder/dispacher/actions/plugins/action_regex_project.py +6 -0
  24. autocoder/events/event_manager_singleton.py +2 -2
  25. autocoder/helper/__init__.py +0 -0
  26. autocoder/helper/project_creator.py +570 -0
  27. autocoder/linters/linter_factory.py +44 -25
  28. autocoder/linters/models.py +220 -0
  29. autocoder/linters/python_linter.py +1 -7
  30. autocoder/linters/reactjs_linter.py +580 -0
  31. autocoder/linters/shadow_linter.py +390 -0
  32. autocoder/linters/vue_linter.py +576 -0
  33. autocoder/memory/active_context_manager.py +0 -4
  34. autocoder/memory/active_package.py +12 -12
  35. autocoder/shadows/__init__.py +0 -0
  36. autocoder/shadows/shadow_manager.py +235 -0
  37. autocoder/version.py +1 -1
  38. {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/LICENSE +0 -0
  39. {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/WHEEL +0 -0
  40. {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/entry_points.txt +0 -0
  41. {auto_coder-0.1.316.dist-info → auto_coder-0.1.318.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,241 @@
1
+ from typing import Dict
2
+ from autocoder.common.types import CodeGenerateResult
3
+ from autocoder.common.v2.code_auto_merge_strict_diff import CodeAutoMergeStrictDiff
4
+ from autocoder.common.v2.code_auto_generate_strict_diff import CodeAutoGenerateStrictDiff
5
+ import byzerllm
6
+ from autocoder.common import AutoCoderArgs, git_utils, SourceCodeList
7
+ from autocoder.linters.shadow_linter import ShadowLinter
8
+ from autocoder.shadows.shadow_manager import ShadowManager
9
+ from autocoder.linters.models import IssueSeverity
10
+ from autocoder.common.global_cancel import global_cancel
11
+ from autocoder.linters.models import ProjectLintResult
12
+ from autocoder.common.token_cost_caculate import TokenCostCalculator
13
+ import time
14
+
15
+
16
+ class CodeStrictDiffManager:
17
+ """
18
+ A class that combines code generation, linting, and merging with automatic error correction,
19
+ specifically for strict diff-based code generation.
20
+ """
21
+
22
+ def __init__(
23
+ self,
24
+ llm: byzerllm.ByzerLLM,
25
+ args: AutoCoderArgs,
26
+ action=None,
27
+ ) -> None:
28
+ super().__init__(llm, args, action)
29
+
30
+ # Initialize sub-components
31
+ self.code_generator = CodeAutoGenerateStrictDiff(llm, args, action)
32
+ self.code_merger = CodeAutoMergeStrictDiff(llm, args)
33
+ self.shadow_manager = ShadowManager(args.source_dir)
34
+ self.shadow_linter = ShadowLinter(self.shadow_manager, verbose=False)
35
+
36
+ @byzerllm.prompt()
37
+ def fix_linter_errors(self, query: str, lint_issues: str) -> str:
38
+ """
39
+ Linter 检测到的问题:
40
+ <lint_issues>
41
+ {{ lint_issues }}
42
+ </lint_issues>
43
+
44
+ 用户原始需求:
45
+ <user_query_wrapper>
46
+ {{ query }}
47
+ </user_query_wrapper>
48
+
49
+ 修复上述问题,请确保代码质量问题被解决,同时保持代码的原有功能。
50
+ 请使用 unified diff 格式输出修改。
51
+ """
52
+
53
+ def _create_shadow_files_from_edits(self, generation_result: CodeGenerateResult) -> Dict[str, str]:
54
+ """
55
+ 从编辑块内容中提取代码并创建临时影子文件用于检查。
56
+
57
+ 参数:
58
+ generation_result (CodeGenerateResult): 包含diff格式的内容
59
+
60
+ 返回:
61
+ Dict[str, str]: 映射 {影子文件路径: 内容}
62
+ """
63
+ result = self.code_merger.choose_best_choice(generation_result)
64
+ merge = self.code_merger._merge_code_without_effect(result.contents[0])
65
+ shadow_files = {}
66
+ for file_path, new_content in merge.success_blocks:
67
+ self.shadow_manager.update_file(file_path, new_content)
68
+ shadow_files[self.shadow_manager.to_shadow_path(file_path)] = new_content
69
+
70
+ return shadow_files
71
+
72
+ def _format_lint_issues(self, lint_results:ProjectLintResult,level:IssueSeverity) -> str:
73
+ """
74
+ 将linter结果格式化为字符串供模型使用
75
+
76
+ 参数:
77
+ lint_results: Linter结果对象
78
+ level: 过滤问题的级别
79
+
80
+ 返回:
81
+ str: 格式化的问题描述
82
+ """
83
+ formatted_issues = []
84
+
85
+ for file_path, result in lint_results.file_results.items():
86
+ file_has_issues = False
87
+ file_issues = []
88
+
89
+ for issue in result.issues:
90
+ if issue.severity.value != level.value:
91
+ continue
92
+
93
+ if not file_has_issues:
94
+ file_has_issues = True
95
+ file_issues.append(f"文件: {file_path}")
96
+
97
+ severity = "错误" if issue.severity == IssueSeverity.ERROR else "警告" if issue.severity == IssueSeverity.WARNING else "信息"
98
+ line_info = f"第{issue.position.line}行"
99
+ if issue.position.column:
100
+ line_info += f", 第{issue.position.column}列"
101
+
102
+ file_issues.append(
103
+ f" - [{severity}] {line_info}: {issue.message} (规则: {issue.code})"
104
+ )
105
+
106
+ if file_has_issues:
107
+ formatted_issues.extend(file_issues)
108
+ formatted_issues.append("") # 空行分隔不同文件
109
+
110
+ return "\n".join(formatted_issues)
111
+
112
+ def _count_errors(self, lint_results:ProjectLintResult) -> int:
113
+ """
114
+ 计算lint结果中的错误数量
115
+
116
+ 参数:
117
+ lint_results: Linter结果对象
118
+
119
+ 返回:
120
+ int: 错误数量
121
+ """
122
+ error_count = 0
123
+
124
+ for _, result in lint_results.file_results.items():
125
+ error_count += result.error_count
126
+
127
+ return error_count
128
+
129
+ def generate_and_fix(self, query: str, source_code_list: SourceCodeList) -> CodeGenerateResult:
130
+ """
131
+ 生成代码,运行linter,修复错误,最多尝试指定次数
132
+
133
+ 参数:
134
+ query (str): 用户查询
135
+ source_code_list (SourceCodeList): 源代码列表
136
+
137
+ 返回:
138
+ CodeGenerateResult: 生成的代码结果
139
+ """
140
+ # 初始代码生成
141
+ self.printer.print_in_terminal("generating_initial_code")
142
+ start_time = time.time()
143
+ generation_result = self.code_generator.single_round_run(query, source_code_list)
144
+
145
+ token_cost_calculator = TokenCostCalculator(args=self.args)
146
+ token_cost_calculator.track_token_usage_by_generate(
147
+ llm=self.llm,
148
+ generate=generation_result,
149
+ operation_name="code_generation_complete",
150
+ start_time=start_time,
151
+ end_time=time.time()
152
+ )
153
+
154
+ # 确保结果非空
155
+ if not generation_result.contents:
156
+ self.printer.print_in_terminal("generation_failed", style="red")
157
+ return generation_result
158
+
159
+
160
+ # 最多尝试修复5次
161
+ for attempt in range(self.max_correction_attempts):
162
+ global_cancel.check_and_raise()
163
+ # 代码生成结果更新到影子文件里去
164
+ shadow_files = self._create_shadow_files_from_edits(generation_result)
165
+
166
+ if not shadow_files:
167
+ self.printer.print_in_terminal("no_files_to_lint", style="yellow")
168
+ break
169
+
170
+ # 运行linter
171
+ lint_results = self.shadow_linter.lint_all_shadow_files()
172
+ error_count = self._count_errors(lint_results)
173
+
174
+ # 如果没有错误则完成
175
+ if error_count == 0:
176
+ self.printer.print_in_terminal("no_lint_errors_found", style="green")
177
+ break
178
+
179
+ # 格式化lint问题
180
+ formatted_issues = self._format_lint_issues(lint_results, IssueSeverity.ERROR)
181
+
182
+ # 打印当前错误
183
+ self.printer.print_in_terminal(
184
+ "lint_attempt_status",
185
+ style="yellow",
186
+ attempt=(attempt + 1),
187
+ max_correction_attempts=self.max_correction_attempts,
188
+ error_count=error_count,
189
+ formatted_issues=formatted_issues
190
+ )
191
+
192
+ if attempt == self.max_correction_attempts - 1:
193
+ self.printer.print_in_terminal("max_attempts_reached", style="yellow")
194
+ break
195
+
196
+ # 准备修复提示
197
+ fix_prompt = self.fix_linter_errors.prompt(
198
+ query=query,
199
+ lint_issues=formatted_issues
200
+ )
201
+
202
+ for source in source_code_list.sources:
203
+ print(f"file_path: {source.module_name}")
204
+ print(f"fix_prompt: {fix_prompt}")
205
+
206
+ # 将 shadow_files 转化为 source_code_list
207
+ source_code_list = self.code_merger.get_source_code_list_from_shadow_files(shadow_files)
208
+ start_time = time.time()
209
+ generation_result = self.code_generator.single_round_run(fix_prompt, source_code_list)
210
+ token_cost_calculator.track_token_usage_by_generate(
211
+ llm=self.llm,
212
+ generate=generation_result,
213
+ operation_name="code_generation_complete",
214
+ start_time=start_time,
215
+ end_time=time.time()
216
+ )
217
+
218
+ # 清理临时影子文件
219
+ self.shadow_manager.clean_shadows()
220
+
221
+ # 返回最终结果
222
+ return generation_result
223
+
224
+ def run(self, query: str, source_code_list: SourceCodeList) -> CodeGenerateResult:
225
+ """
226
+ 执行完整的代码生成、修复、合并流程
227
+
228
+ 参数:
229
+ query (str): 用户查询
230
+ source_code_list (SourceCodeList): 源代码列表
231
+
232
+ 返回:
233
+ CodeGenerateResult: 生成和修复的代码结果
234
+ """
235
+ # 生成代码并自动修复lint错误
236
+ generation_result = self.generate_and_fix(query, source_code_list)
237
+ global_cancel.check_and_raise()
238
+ # 合并代码
239
+ self.code_merger.merge_code(generation_result)
240
+
241
+ return generation_result
@@ -33,6 +33,7 @@ from autocoder.common.global_cancel import global_cancel
33
33
  from autocoder.events.event_manager_singleton import get_event_manager
34
34
  from autocoder.events import event_content as EventContentCreator
35
35
  from autocoder.events.event_types import EventMetadata
36
+ from autocoder.common.v2.code_editblock_manager import CodeEditBlockManager
36
37
 
37
38
 
38
39
  class BaseAction:
@@ -114,6 +115,11 @@ class ActionTSProject(BaseAction):
114
115
 
115
116
  global_cancel.check_and_raise()
116
117
 
118
+ if args.enable_auto_fix_lint and args.execute and args.auto_merge=="editblock":
119
+ code_merge_manager = CodeEditBlockManager(llm=self.llm, args=self.args,action=self)
120
+ code_merge_manager.run(query=args.query, source_code_list=source_code_list)
121
+ return
122
+
117
123
  if args.execute:
118
124
  self.printer.print_in_terminal("code_generation_start")
119
125
  start_time = time.time()
@@ -268,6 +274,11 @@ class ActionPyProject(BaseAction):
268
274
 
269
275
  global_cancel.check_and_raise()
270
276
 
277
+ if args.enable_auto_fix_lint and args.execute and args.auto_merge=="editblock":
278
+ code_merge_manager = CodeEditBlockManager(llm=self.llm, args=self.args,action=self)
279
+ code_merge_manager.run(query=args.query, source_code_list=source_code_list)
280
+ return
281
+
271
282
  if args.execute:
272
283
  self.printer.print_in_terminal("code_generation_start")
273
284
  start_time = time.time()
@@ -415,6 +426,11 @@ class ActionSuffixProject(BaseAction):
415
426
 
416
427
  global_cancel.check_and_raise()
417
428
 
429
+ if args.enable_auto_fix_lint and args.execute and args.auto_merge=="editblock":
430
+ code_merge_manager = CodeEditBlockManager(llm=self.llm, args=self.args,action=self)
431
+ code_merge_manager.run(query=args.query, source_code_list=source_code_list)
432
+ return
433
+
418
434
  if args.execute:
419
435
  self.printer.print_in_terminal("code_generation_start")
420
436
  start_time = time.time()
@@ -9,6 +9,7 @@ from autocoder.common.code_auto_generate import CodeAutoGenerate
9
9
  from autocoder.common.code_auto_generate_diff import CodeAutoGenerateDiff
10
10
  from autocoder.common.code_auto_generate_strict_diff import CodeAutoGenerateStrictDiff
11
11
  from autocoder.common.code_auto_generate_editblock import CodeAutoGenerateEditBlock
12
+ from autocoder.common.v2.code_editblock_manager import CodeEditBlockManager
12
13
  from autocoder.index.entry import build_index_and_filter_files
13
14
  from autocoder.regexproject import RegexProject
14
15
  from autocoder.utils.conversation_store import store_code_model_conversation
@@ -67,6 +68,11 @@ class ActionRegexProject:
67
68
  start_time = time.time()
68
69
 
69
70
  global_cancel.check_and_raise()
71
+
72
+ if args.enable_auto_fix_lint and args.execute and args.auto_merge=="editblock":
73
+ code_merge_manager = CodeEditBlockManager(llm=self.llm, args=self.args,action=self)
74
+ code_merge_manager.run(query=args.query, source_code_list=source_code_list)
75
+ return
70
76
 
71
77
  if args.execute:
72
78
  self.printer.print_in_terminal("code_generation_start")
@@ -1,6 +1,6 @@
1
1
  import os
2
2
  import threading
3
- from typing import Optional, Dict, Any, List
3
+ from typing import Optional, Dict, Any, List, Tuple
4
4
  import uuid
5
5
  from datetime import datetime
6
6
  import glob
@@ -75,7 +75,7 @@ def get_event_file_path(file_id:str,project_path: Optional[str] = None) -> str:
75
75
  else:
76
76
  return os.path.join(project_path, ".auto-coder", "events", f"{file_id}.jsonl")
77
77
 
78
- def gengerate_event_file_path(project_path: Optional[str] = None) -> (str,str):
78
+ def gengerate_event_file_path(project_path: Optional[str] = None) -> Tuple[str,str]:
79
79
  """
80
80
  生成一个格式为 uuid_timestamp.jsonl 的事件文件名。
81
81
  timestamp 格式为 YYYYMMDD-HHMMSS。
File without changes