auto-coder 0.1.316__py3-none-any.whl → 0.1.317__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.
- {auto_coder-0.1.316.dist-info → auto_coder-0.1.317.dist-info}/METADATA +1 -1
- {auto_coder-0.1.316.dist-info → auto_coder-0.1.317.dist-info}/RECORD +41 -20
- autocoder/auto_coder_runner.py +1 -2
- autocoder/common/__init__.py +3 -0
- autocoder/common/auto_coder_lang.py +24 -0
- autocoder/common/code_auto_merge_editblock.py +2 -42
- autocoder/common/git_utils.py +2 -2
- autocoder/common/token_cost_caculate.py +103 -42
- autocoder/common/v2/__init__.py +0 -0
- autocoder/common/v2/code_auto_generate.py +199 -0
- autocoder/common/v2/code_auto_generate_diff.py +361 -0
- autocoder/common/v2/code_auto_generate_editblock.py +380 -0
- autocoder/common/v2/code_auto_generate_strict_diff.py +269 -0
- autocoder/common/v2/code_auto_merge.py +211 -0
- autocoder/common/v2/code_auto_merge_diff.py +354 -0
- autocoder/common/v2/code_auto_merge_editblock.py +523 -0
- autocoder/common/v2/code_auto_merge_strict_diff.py +259 -0
- autocoder/common/v2/code_diff_manager.py +266 -0
- autocoder/common/v2/code_editblock_manager.py +275 -0
- autocoder/common/v2/code_manager.py +238 -0
- autocoder/common/v2/code_strict_diff_manager.py +241 -0
- autocoder/dispacher/actions/action.py +16 -0
- autocoder/dispacher/actions/plugins/action_regex_project.py +6 -0
- autocoder/events/event_manager_singleton.py +2 -2
- autocoder/helper/__init__.py +0 -0
- autocoder/helper/project_creator.py +570 -0
- autocoder/linters/linter_factory.py +44 -25
- autocoder/linters/models.py +220 -0
- autocoder/linters/python_linter.py +1 -7
- autocoder/linters/reactjs_linter.py +580 -0
- autocoder/linters/shadow_linter.py +390 -0
- autocoder/linters/vue_linter.py +576 -0
- autocoder/memory/active_context_manager.py +0 -4
- autocoder/memory/active_package.py +12 -12
- autocoder/shadows/__init__.py +0 -0
- autocoder/shadows/shadow_manager.py +235 -0
- autocoder/version.py +1 -1
- {auto_coder-0.1.316.dist-info → auto_coder-0.1.317.dist-info}/LICENSE +0 -0
- {auto_coder-0.1.316.dist-info → auto_coder-0.1.317.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.316.dist-info → auto_coder-0.1.317.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.316.dist-info → auto_coder-0.1.317.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) ->
|
|
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
|