auto-coder 0.1.330__py3-none-any.whl → 0.1.332__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.330.dist-info → auto_coder-0.1.332.dist-info}/METADATA +1 -1
- {auto_coder-0.1.330.dist-info → auto_coder-0.1.332.dist-info}/RECORD +47 -45
- autocoder/agent/agentic_filter.py +928 -0
- autocoder/agent/project_reader.py +1 -14
- autocoder/auto_coder.py +6 -47
- autocoder/auto_coder_runner.py +2 -0
- autocoder/command_args.py +1 -6
- autocoder/commands/auto_command.py +1 -1
- autocoder/commands/tools.py +68 -16
- autocoder/common/__init__.py +8 -3
- autocoder/common/auto_coder_lang.py +21 -1
- autocoder/common/code_auto_generate.py +6 -160
- autocoder/common/code_auto_generate_diff.py +5 -111
- autocoder/common/code_auto_generate_editblock.py +5 -95
- autocoder/common/code_auto_generate_strict_diff.py +6 -112
- autocoder/common/code_auto_merge_editblock.py +1 -45
- autocoder/common/code_modification_ranker.py +6 -2
- autocoder/common/command_templates.py +2 -9
- autocoder/common/conf_utils.py +36 -0
- autocoder/common/stream_out_type.py +7 -2
- autocoder/common/types.py +3 -2
- autocoder/common/v2/code_auto_generate.py +6 -4
- autocoder/common/v2/code_auto_generate_diff.py +4 -3
- autocoder/common/v2/code_auto_generate_editblock.py +9 -4
- autocoder/common/v2/code_auto_generate_strict_diff.py +182 -14
- autocoder/common/v2/code_auto_merge_diff.py +560 -306
- autocoder/common/v2/code_auto_merge_editblock.py +12 -45
- autocoder/common/v2/code_auto_merge_strict_diff.py +76 -7
- autocoder/common/v2/code_diff_manager.py +73 -6
- autocoder/common/v2/code_editblock_manager.py +534 -82
- autocoder/dispacher/actions/action.py +15 -28
- autocoder/dispacher/actions/plugins/action_regex_project.py +5 -9
- autocoder/helper/project_creator.py +0 -1
- autocoder/index/entry.py +35 -53
- autocoder/index/filter/normal_filter.py +0 -16
- autocoder/lang.py +2 -4
- autocoder/linters/shadow_linter.py +4 -0
- autocoder/pyproject/__init__.py +2 -19
- autocoder/rag/cache/simple_cache.py +31 -6
- autocoder/regexproject/__init__.py +4 -22
- autocoder/suffixproject/__init__.py +6 -24
- autocoder/tsproject/__init__.py +5 -22
- autocoder/version.py +1 -1
- {auto_coder-0.1.330.dist-info → auto_coder-0.1.332.dist-info}/LICENSE +0 -0
- {auto_coder-0.1.330.dist-info → auto_coder-0.1.332.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.330.dist-info → auto_coder-0.1.332.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.330.dist-info → auto_coder-0.1.332.dist-info}/top_level.txt +0 -0
|
@@ -269,10 +269,12 @@ class CodeAutoMergeEditBlock:
|
|
|
269
269
|
codes = self.get_edits(content)
|
|
270
270
|
file_content_mapping = {}
|
|
271
271
|
failed_blocks = []
|
|
272
|
+
merged_blocks = []
|
|
272
273
|
|
|
273
274
|
for block in codes:
|
|
274
|
-
file_path, head, update = block
|
|
275
|
+
file_path, head, update = block
|
|
275
276
|
if not os.path.exists(file_path):
|
|
277
|
+
merged_blocks.append((file_path, "", update))
|
|
276
278
|
file_content_mapping[file_path] = update
|
|
277
279
|
else:
|
|
278
280
|
if file_path not in file_content_mapping:
|
|
@@ -286,7 +288,7 @@ class CodeAutoMergeEditBlock:
|
|
|
286
288
|
else existing_content + "\n" + update
|
|
287
289
|
)
|
|
288
290
|
|
|
289
|
-
# If exact match fails, try similarity match
|
|
291
|
+
# If exact match fails, try similarity match
|
|
290
292
|
if new_content == existing_content and head:
|
|
291
293
|
similarity, best_window = TextSimilarity(
|
|
292
294
|
head, existing_content
|
|
@@ -297,6 +299,7 @@ class CodeAutoMergeEditBlock:
|
|
|
297
299
|
)
|
|
298
300
|
|
|
299
301
|
if new_content != existing_content:
|
|
302
|
+
merged_blocks.append((file_path, head, update))
|
|
300
303
|
file_content_mapping[file_path] = new_content
|
|
301
304
|
else:
|
|
302
305
|
failed_blocks.append((file_path, head, update))
|
|
@@ -304,7 +307,8 @@ class CodeAutoMergeEditBlock:
|
|
|
304
307
|
return MergeCodeWithoutEffect(
|
|
305
308
|
success_blocks=[(path, content)
|
|
306
309
|
for path, content in file_content_mapping.items()],
|
|
307
|
-
failed_blocks=failed_blocks
|
|
310
|
+
failed_blocks=failed_blocks,
|
|
311
|
+
merged_blocks=merged_blocks
|
|
308
312
|
)
|
|
309
313
|
|
|
310
314
|
|
|
@@ -363,35 +367,12 @@ class CodeAutoMergeEditBlock:
|
|
|
363
367
|
else:
|
|
364
368
|
unmerged_blocks.append(
|
|
365
369
|
(file_path, head, update, similarity))
|
|
366
|
-
|
|
367
|
-
if unmerged_blocks:
|
|
368
|
-
if self.args.request_id and not self.args.skip_events:
|
|
369
|
-
# collect unmerged blocks
|
|
370
|
-
event_data = []
|
|
371
|
-
for file_path, head, update, similarity in unmerged_blocks:
|
|
372
|
-
event_data.append(
|
|
373
|
-
{
|
|
374
|
-
"file_path": file_path,
|
|
375
|
-
"head": head,
|
|
376
|
-
"update": update,
|
|
377
|
-
"similarity": similarity,
|
|
378
|
-
}
|
|
379
|
-
)
|
|
380
|
-
return
|
|
381
370
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
for file_path, new_content in file_content_mapping.items():
|
|
388
|
-
if file_path.endswith(".py"):
|
|
389
|
-
pylint_passed, error_message = self.run_pylint(new_content)
|
|
390
|
-
if not pylint_passed:
|
|
391
|
-
self.printer.print_in_terminal("pylint_file_check_failed",
|
|
392
|
-
file_path=file_path,
|
|
393
|
-
error_message=error_message)
|
|
394
|
-
|
|
371
|
+
if unmerged_blocks:
|
|
372
|
+
self.printer.print_in_terminal("unmerged_blocks_warning", num_blocks=len(unmerged_blocks))
|
|
373
|
+
self._print_unmerged_blocks(unmerged_blocks)
|
|
374
|
+
return
|
|
375
|
+
|
|
395
376
|
if changes_made and not force_skip_git and not self.args.skip_commit:
|
|
396
377
|
try:
|
|
397
378
|
git_utils.commit_changes(
|
|
@@ -410,20 +391,6 @@ class CodeAutoMergeEditBlock:
|
|
|
410
391
|
with open(file_path, "w") as f:
|
|
411
392
|
f.write(new_content)
|
|
412
393
|
|
|
413
|
-
if self.args.request_id and not self.args.skip_events:
|
|
414
|
-
# collect modified files
|
|
415
|
-
event_data = []
|
|
416
|
-
for code in merged_blocks:
|
|
417
|
-
file_path, head, update, similarity = code
|
|
418
|
-
event_data.append(
|
|
419
|
-
{
|
|
420
|
-
"file_path": file_path,
|
|
421
|
-
"head": head,
|
|
422
|
-
"update": update,
|
|
423
|
-
"similarity": similarity,
|
|
424
|
-
}
|
|
425
|
-
)
|
|
426
|
-
|
|
427
394
|
|
|
428
395
|
if changes_made:
|
|
429
396
|
if not force_skip_git and not self.args.skip_commit:
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import difflib
|
|
3
3
|
import diff_match_patch as dmp_module
|
|
4
|
-
from
|
|
5
|
-
from typing import List,
|
|
4
|
+
from autocoder.common import AutoCoderArgs, git_utils
|
|
5
|
+
from typing import List,Tuple
|
|
6
6
|
import pydantic
|
|
7
7
|
import byzerllm
|
|
8
|
-
from autocoder.common import
|
|
8
|
+
from autocoder.common.action_yml_file_manager import ActionYmlFileManager
|
|
9
|
+
from autocoder.common.printer import Printer
|
|
10
|
+
import hashlib
|
|
11
|
+
from pathlib import Path
|
|
9
12
|
from autocoder.common.types import CodeGenerateResult, MergeCodeWithoutEffect
|
|
10
|
-
from autocoder.common.
|
|
11
|
-
from autocoder.common import files as
|
|
13
|
+
from autocoder.common.code_modification_ranker import CodeModificationRanker
|
|
14
|
+
from autocoder.common import files as FileUtils
|
|
15
|
+
from autocoder.memory.active_context_manager import ActiveContextManager
|
|
12
16
|
|
|
13
17
|
class PathAndCode(pydantic.BaseModel):
|
|
14
18
|
path: str
|
|
@@ -49,6 +53,7 @@ def apply_hunk(content, hunk):
|
|
|
49
53
|
|
|
50
54
|
return "\n".join(content_out)
|
|
51
55
|
|
|
56
|
+
|
|
52
57
|
def hunk_to_before_after(hunk, lines=False):
|
|
53
58
|
before = []
|
|
54
59
|
after = []
|
|
@@ -77,7 +82,14 @@ def hunk_to_before_after(hunk, lines=False):
|
|
|
77
82
|
|
|
78
83
|
return before, after
|
|
79
84
|
|
|
80
|
-
|
|
85
|
+
|
|
86
|
+
class CodeAutoMergeStrictDiff:
|
|
87
|
+
def __init__(self, llm: byzerllm.ByzerLLM, args: AutoCoderArgs):
|
|
88
|
+
self.llm = llm
|
|
89
|
+
self.args = args
|
|
90
|
+
self.printer = Printer()
|
|
91
|
+
|
|
92
|
+
|
|
81
93
|
def parse_diff_block(self,text: str) -> List[PathAndCode]:
|
|
82
94
|
lines = text.split('\n')
|
|
83
95
|
lines_len = len(lines)
|
|
@@ -121,6 +133,46 @@ class CodeAutoMergeStrictDiff(CodeAutoMerge):
|
|
|
121
133
|
|
|
122
134
|
return path_and_code_list
|
|
123
135
|
|
|
136
|
+
def merge_code(self, generate_result: CodeGenerateResult, force_skip_git: bool = False):
|
|
137
|
+
result = self.choose_best_choice(generate_result)
|
|
138
|
+
self._merge_code(result.contents[0], force_skip_git)
|
|
139
|
+
return result
|
|
140
|
+
|
|
141
|
+
def choose_best_choice(self, generate_result: CodeGenerateResult) -> CodeGenerateResult:
|
|
142
|
+
if len(generate_result.contents) == 1:
|
|
143
|
+
return generate_result
|
|
144
|
+
|
|
145
|
+
merge_results = []
|
|
146
|
+
for content,conversations in zip(generate_result.contents,generate_result.conversations):
|
|
147
|
+
merge_result = self._merge_code_without_effect(content)
|
|
148
|
+
merge_results.append(merge_result)
|
|
149
|
+
|
|
150
|
+
# If all merge results are None, return first one
|
|
151
|
+
if all(len(result.failed_blocks) != 0 for result in merge_results):
|
|
152
|
+
self.printer.print_in_terminal("all_merge_results_failed")
|
|
153
|
+
return CodeGenerateResult(contents=[generate_result.contents[0]], conversations=[generate_result.conversations[0]])
|
|
154
|
+
|
|
155
|
+
# If only one merge result is not None, return that one
|
|
156
|
+
not_none_indices = [i for i, result in enumerate(merge_results) if len(result.failed_blocks) == 0]
|
|
157
|
+
if len(not_none_indices) == 1:
|
|
158
|
+
idx = not_none_indices[0]
|
|
159
|
+
self.printer.print_in_terminal("only_one_merge_result_success")
|
|
160
|
+
return CodeGenerateResult(contents=[generate_result.contents[idx]], conversations=[generate_result.conversations[idx]])
|
|
161
|
+
|
|
162
|
+
# 最后,如果有多个,那么根据质量排序再返回
|
|
163
|
+
ranker = CodeModificationRanker(self.llm, self.args)
|
|
164
|
+
ranked_result = ranker.rank_modifications(generate_result,merge_results)
|
|
165
|
+
|
|
166
|
+
## 得到的结果,再做一次合并,第一个通过的返回 , 返回做合并有点重复低效,未来修改。
|
|
167
|
+
for content,conversations in zip(ranked_result.contents,ranked_result.conversations):
|
|
168
|
+
merge_result = self._merge_code_without_effect(content)
|
|
169
|
+
if not merge_result.failed_blocks:
|
|
170
|
+
return CodeGenerateResult(contents=[content], conversations=[conversations])
|
|
171
|
+
|
|
172
|
+
# 最后保底,但实际不会出现
|
|
173
|
+
return CodeGenerateResult(contents=[ranked_result.contents[0]], conversations=[ranked_result.conversations[0]])
|
|
174
|
+
|
|
175
|
+
|
|
124
176
|
def abs_root_path(self, path):
|
|
125
177
|
if path.startswith(self.args.source_dir):
|
|
126
178
|
return safe_abs_path(Path(path))
|
|
@@ -207,6 +259,7 @@ class CodeAutoMergeStrictDiff(CodeAutoMerge):
|
|
|
207
259
|
|
|
208
260
|
file_content = FileUtils.read_file(self.args.file)
|
|
209
261
|
md5 = hashlib.md5(file_content.encode('utf-8')).hexdigest()
|
|
262
|
+
# get the file name
|
|
210
263
|
file_name = os.path.basename(self.args.file)
|
|
211
264
|
|
|
212
265
|
if not force_skip_git and not self.args.skip_commit:
|
|
@@ -256,4 +309,20 @@ class CodeAutoMergeStrictDiff(CodeAutoMerge):
|
|
|
256
309
|
git_utils.print_commit_info(commit_result=commit_result)
|
|
257
310
|
else:
|
|
258
311
|
# Print diff blocks for review
|
|
259
|
-
self.print_diff_blocks(diff_blocks)
|
|
312
|
+
self.print_diff_blocks(diff_blocks)
|
|
313
|
+
|
|
314
|
+
@byzerllm.prompt(render="jinja2")
|
|
315
|
+
def git_require_msg(self, source_dir: str, error: str) -> str:
|
|
316
|
+
'''
|
|
317
|
+
auto_merge only works for git repositories.
|
|
318
|
+
|
|
319
|
+
Try to use git init in the source directory.
|
|
320
|
+
|
|
321
|
+
```shell
|
|
322
|
+
cd {{ source_dir }}
|
|
323
|
+
git init .
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
Then try to run auto-coder again.
|
|
327
|
+
Error: {{ error }}
|
|
328
|
+
'''
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
from typing import List, Dict, Tuple, Optional, Any
|
|
2
2
|
import os
|
|
3
|
-
import json
|
|
4
3
|
import time
|
|
5
|
-
from concurrent.futures import ThreadPoolExecutor
|
|
6
4
|
|
|
7
5
|
import byzerllm
|
|
8
6
|
from byzerllm.utils.client import code_utils
|
|
9
7
|
|
|
10
8
|
from autocoder.common.types import Mode, CodeGenerateResult, MergeCodeWithoutEffect
|
|
11
|
-
from autocoder.common import AutoCoderArgs, git_utils, SourceCodeList
|
|
9
|
+
from autocoder.common import AutoCoderArgs, git_utils, SourceCodeList, SourceCode
|
|
10
|
+
from autocoder.common.action_yml_file_manager import ActionYmlFileManager
|
|
12
11
|
from autocoder.common import sys_prompt
|
|
12
|
+
from autocoder.compilers.shadow_compiler import ShadowCompiler
|
|
13
13
|
from autocoder.privacy.model_filter import ModelPathFilter
|
|
14
14
|
from autocoder.common.utils_code_auto_generate import chat_with_continue, stream_chat_with_continue, ChatWithContinueResult
|
|
15
15
|
from autocoder.utils.auto_coder_utils.chat_stream_out import stream_out
|
|
16
|
-
from autocoder.common.stream_out_type import CodeGenerateStreamOutType
|
|
16
|
+
from autocoder.common.stream_out_type import LintStreamOutType, CompileStreamOutType, UnmergedBlocksStreamOutType, CodeGenerateStreamOutType
|
|
17
17
|
from autocoder.common.auto_coder_lang import get_message_with_format
|
|
18
18
|
from autocoder.common.printer import Printer
|
|
19
19
|
from autocoder.rag.token_counter import count_tokens
|
|
@@ -28,6 +28,9 @@ from loguru import logger
|
|
|
28
28
|
from autocoder.common.global_cancel import global_cancel
|
|
29
29
|
from autocoder.linters.models import ProjectLintResult
|
|
30
30
|
from autocoder.common.token_cost_caculate import TokenCostCalculator
|
|
31
|
+
from autocoder.events.event_manager_singleton import get_event_manager
|
|
32
|
+
from autocoder.events.event_types import Event, EventType, EventMetadata
|
|
33
|
+
from autocoder.events import event_content as EventContentCreator
|
|
31
34
|
|
|
32
35
|
|
|
33
36
|
class CodeDiffManager:
|
|
@@ -47,7 +50,8 @@ class CodeDiffManager:
|
|
|
47
50
|
self.args = args
|
|
48
51
|
self.action = action
|
|
49
52
|
self.generate_times_same_model = args.generate_times_same_model
|
|
50
|
-
self.
|
|
53
|
+
self.auto_fix_lint_max_attempts = args.auto_fix_lint_max_attempts
|
|
54
|
+
self.auto_fix_compile_max_attempts = args.auto_fix_compile_max_attempts
|
|
51
55
|
self.printer = Printer()
|
|
52
56
|
|
|
53
57
|
# Initialize sub-components
|
|
@@ -55,8 +59,11 @@ class CodeDiffManager:
|
|
|
55
59
|
self.code_merger = CodeAutoMergeDiff(llm, args)
|
|
56
60
|
|
|
57
61
|
# Create shadow manager for linting
|
|
58
|
-
self.shadow_manager = ShadowManager(
|
|
62
|
+
self.shadow_manager = ShadowManager(
|
|
63
|
+
args.source_dir, args.event_file, args.ignore_clean_shadows)
|
|
59
64
|
self.shadow_linter = ShadowLinter(self.shadow_manager, verbose=False)
|
|
65
|
+
self.shadow_compiler = ShadowCompiler(
|
|
66
|
+
self.shadow_manager, verbose=False)
|
|
60
67
|
|
|
61
68
|
@byzerllm.prompt()
|
|
62
69
|
def fix_linter_errors(self, query: str, lint_issues: str) -> str:
|
|
@@ -75,6 +82,66 @@ class CodeDiffManager:
|
|
|
75
82
|
请使用 unified diff 格式输出修改。
|
|
76
83
|
"""
|
|
77
84
|
|
|
85
|
+
@byzerllm.prompt()
|
|
86
|
+
def fix_compile_errors(self, query: str, compile_errors: str) -> str:
|
|
87
|
+
"""
|
|
88
|
+
编译错误:
|
|
89
|
+
<compile_errors>
|
|
90
|
+
{{ compile_errors }}
|
|
91
|
+
</compile_errors>
|
|
92
|
+
|
|
93
|
+
用户原始需求:
|
|
94
|
+
<user_query_wrapper>
|
|
95
|
+
{{ query }}
|
|
96
|
+
</user_query_wrapper>
|
|
97
|
+
|
|
98
|
+
修复上述问题,请确保代码质量问题被解决,同时保持代码的原有功能。
|
|
99
|
+
请使用 unified diff 格式输出修改。
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
@byzerllm.prompt()
|
|
103
|
+
def fix_missing_context(self, query: str, original_code: str, missing_files: str) -> str:
|
|
104
|
+
"""
|
|
105
|
+
下面是你根据格式要求输出的一份修改代码:
|
|
106
|
+
<original_code>
|
|
107
|
+
{{ original_code }}
|
|
108
|
+
</original_code>
|
|
109
|
+
|
|
110
|
+
我发现你尝试修改以下文件,但这些文件没有在上下文中提供,所以你无法看到它们的内容:
|
|
111
|
+
<missing_files>
|
|
112
|
+
{{ missing_files }}
|
|
113
|
+
</missing_files>
|
|
114
|
+
|
|
115
|
+
下面是用户原始的需求:
|
|
116
|
+
<user_query_wrapper>
|
|
117
|
+
{{ query }}
|
|
118
|
+
</user_query_wrapper>
|
|
119
|
+
|
|
120
|
+
我已经将这些文件添加到上下文中,请重新生成代码,确保使用 unified diff 格式正确修改这些文件。
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
@byzerllm.prompt()
|
|
124
|
+
def fix_unmerged_blocks(self, query: str, original_code: str, unmerged_blocks: str) -> str:
|
|
125
|
+
"""
|
|
126
|
+
下面是你根据格式要求输出的一份修改代码:
|
|
127
|
+
<original_code>
|
|
128
|
+
{{ original_code }}
|
|
129
|
+
</original_code>
|
|
130
|
+
|
|
131
|
+
但是我发现下面的代码块无法合并:
|
|
132
|
+
<unmerged_blocks>
|
|
133
|
+
{{ unmerged_blocks }}
|
|
134
|
+
</unmerged_blocks>
|
|
135
|
+
|
|
136
|
+
下面是用户原始的需求:
|
|
137
|
+
<user_query_wrapper>
|
|
138
|
+
{{ query }}
|
|
139
|
+
</user_query_wrapper>
|
|
140
|
+
|
|
141
|
+
请根据反馈,回顾之前的格式要求,重新生成一份修改代码,确保所有代码块都能够正确合并。
|
|
142
|
+
请使用 unified diff 格式输出修改。
|
|
143
|
+
"""
|
|
144
|
+
|
|
78
145
|
def _create_shadow_files_from_edits(self, generation_result: CodeGenerateResult) -> Dict[str, str]:
|
|
79
146
|
"""
|
|
80
147
|
从编辑块内容中提取代码并创建临时影子文件用于检查。
|