auto-coder 0.1.331__py3-none-any.whl → 0.1.333__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.331.dist-info → auto_coder-0.1.333.dist-info}/METADATA +1 -1
- {auto_coder-0.1.331.dist-info → auto_coder-0.1.333.dist-info}/RECORD +28 -26
- autocoder/agent/agentic_filter.py +929 -0
- autocoder/auto_coder.py +5 -23
- autocoder/auto_coder_runner.py +2 -0
- autocoder/commands/auto_command.py +1 -1
- autocoder/commands/tools.py +68 -3
- autocoder/common/__init__.py +2 -0
- autocoder/common/auto_coder_lang.py +9 -1
- autocoder/common/code_modification_ranker.py +6 -2
- autocoder/common/conf_utils.py +36 -0
- autocoder/common/stream_out_type.py +4 -2
- autocoder/common/types.py +2 -2
- autocoder/common/v2/code_auto_merge_editblock.py +1 -1
- autocoder/common/v2/code_diff_manager.py +73 -6
- autocoder/common/v2/code_editblock_manager.py +480 -163
- autocoder/compilers/provided_compiler.py +39 -0
- autocoder/helper/project_creator.py +282 -100
- autocoder/index/entry.py +35 -10
- autocoder/linters/reactjs_linter.py +55 -61
- autocoder/linters/shadow_linter.py +4 -0
- autocoder/shadows/shadow_manager.py +1 -1
- autocoder/utils/project_structure.py +2 -2
- autocoder/version.py +1 -1
- {auto_coder-0.1.331.dist-info → auto_coder-0.1.333.dist-info}/LICENSE +0 -0
- {auto_coder-0.1.331.dist-info → auto_coder-0.1.333.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.331.dist-info → auto_coder-0.1.333.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.331.dist-info → auto_coder-0.1.333.dist-info}/top_level.txt +0 -0
|
@@ -1,14 +1,12 @@
|
|
|
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
|
-
from byzerllm.utils.client import code_utils
|
|
9
6
|
|
|
10
7
|
from autocoder.common.types import Mode, CodeGenerateResult, MergeCodeWithoutEffect
|
|
11
|
-
from autocoder.common import AutoCoderArgs,
|
|
8
|
+
from autocoder.common import AutoCoderArgs, SourceCodeList,SourceCode
|
|
9
|
+
from autocoder.common.action_yml_file_manager import ActionYmlFileManager
|
|
12
10
|
from autocoder.common import sys_prompt
|
|
13
11
|
from autocoder.compilers.shadow_compiler import ShadowCompiler
|
|
14
12
|
from autocoder.privacy.model_filter import ModelPathFilter
|
|
@@ -87,7 +85,7 @@ class CodeEditBlockManager:
|
|
|
87
85
|
修复上述问题,请确保代码质量问题被解决,同时保持代码的原有功能。
|
|
88
86
|
请严格遵守*SEARCH/REPLACE block*的格式。
|
|
89
87
|
"""
|
|
90
|
-
|
|
88
|
+
@byzerllm.prompt()
|
|
91
89
|
def fix_compile_errors(self, query: str, compile_errors: str) -> str:
|
|
92
90
|
"""
|
|
93
91
|
编译错误:
|
|
@@ -103,6 +101,29 @@ class CodeEditBlockManager:
|
|
|
103
101
|
修复上述问题,请确保代码质量问题被解决,同时保持代码的原有功能。
|
|
104
102
|
请严格遵守*SEARCH/REPLACE block*的格式。
|
|
105
103
|
"""
|
|
104
|
+
|
|
105
|
+
@byzerllm.prompt()
|
|
106
|
+
def fix_missing_context(self, query: str, original_code: str, missing_files: str) -> str:
|
|
107
|
+
"""
|
|
108
|
+
下面是你根据格式要求输出的一份修改代码:
|
|
109
|
+
<original_code>
|
|
110
|
+
{{ original_code }}
|
|
111
|
+
</original_code>
|
|
112
|
+
|
|
113
|
+
我发现你尝试修改以下文件,但这些文件没有在上下文中提供,所以你无法看到它们的内容:
|
|
114
|
+
<missing_files>
|
|
115
|
+
{{ missing_files }}
|
|
116
|
+
</missing_files>
|
|
117
|
+
|
|
118
|
+
下面是用户原始的需求:
|
|
119
|
+
<user_query_wrapper>
|
|
120
|
+
{{ query }}
|
|
121
|
+
</user_query_wrapper>
|
|
122
|
+
|
|
123
|
+
我已经将这些文件添加到上下文中,请重新生成代码,确保使用SEARCH/REPLACE格式正确修改这些文件。
|
|
124
|
+
对于每个文件,请确保SEARCH部分包含文件中的实际内容,而不是空的SEARCH块。
|
|
125
|
+
"""
|
|
126
|
+
|
|
106
127
|
@byzerllm.prompt()
|
|
107
128
|
def fix_unmerged_blocks(self, query: str, original_code: str, unmerged_blocks: str) -> str:
|
|
108
129
|
"""
|
|
@@ -209,24 +230,96 @@ class CodeEditBlockManager:
|
|
|
209
230
|
|
|
210
231
|
return error_count
|
|
211
232
|
|
|
212
|
-
def
|
|
233
|
+
def _fix_missing_context(self, query: str, generation_result: CodeGenerateResult, source_code_list: SourceCodeList) -> CodeGenerateResult:
|
|
213
234
|
"""
|
|
214
|
-
|
|
235
|
+
检查是否有空的SEARCH块但目标文件存在,如果有,将文件添加到动态上下文并重新生成代码
|
|
215
236
|
|
|
216
237
|
参数:
|
|
217
238
|
query (str): 用户查询
|
|
239
|
+
generation_result (CodeGenerateResult): 生成的代码结果
|
|
218
240
|
source_code_list (SourceCodeList): 源代码列表
|
|
219
241
|
|
|
220
242
|
返回:
|
|
221
|
-
CodeGenerateResult:
|
|
243
|
+
CodeGenerateResult: 修复后的代码结果
|
|
222
244
|
"""
|
|
223
|
-
|
|
224
|
-
|
|
245
|
+
token_cost_calculator = TokenCostCalculator(args=self.args)
|
|
246
|
+
|
|
247
|
+
# 获取编辑块
|
|
248
|
+
codes = self.code_merger.get_edits(generation_result.contents[0])
|
|
249
|
+
|
|
250
|
+
# 检查是否有空的SEARCH块但目标文件存在
|
|
251
|
+
missing_files = []
|
|
252
|
+
for file_path, head, update in codes:
|
|
253
|
+
# 如果SEARCH块为空,检查文件是否存在但不在上下文中
|
|
254
|
+
if not head and os.path.exists(file_path):
|
|
255
|
+
# 检查文件是否已经在上下文中
|
|
256
|
+
in_context = False
|
|
257
|
+
if hasattr(self.args, 'urls') and self.args.urls:
|
|
258
|
+
in_context = file_path in self.args.urls
|
|
259
|
+
if hasattr(self.args, 'dynamic_urls') and self.args.dynamic_urls and not in_context:
|
|
260
|
+
in_context = file_path in self.args.dynamic_urls
|
|
261
|
+
|
|
262
|
+
# 如果文件存在但不在上下文中,添加到缺失文件列表
|
|
263
|
+
if not in_context:
|
|
264
|
+
missing_files.append(file_path)
|
|
265
|
+
# 将文件添加到动态上下文中
|
|
266
|
+
if not hasattr(self.args, 'dynamic_urls'):
|
|
267
|
+
self.args.dynamic_urls = []
|
|
268
|
+
if file_path not in self.args.dynamic_urls:
|
|
269
|
+
self.args.dynamic_urls.append(file_path)
|
|
270
|
+
|
|
271
|
+
# 如果没有缺失文件,直接返回原结果
|
|
272
|
+
if not missing_files:
|
|
273
|
+
return generation_result
|
|
274
|
+
|
|
275
|
+
# 格式化缺失文件列表
|
|
276
|
+
missing_files_text = "\n".join(missing_files)
|
|
277
|
+
|
|
278
|
+
# 打印当前修复状态
|
|
279
|
+
self.printer.print_in_terminal(
|
|
280
|
+
"missing_context_attempt_status",
|
|
281
|
+
style="yellow",
|
|
282
|
+
missing_files=missing_files_text
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
# 更新源代码列表,包含新添加的文件
|
|
286
|
+
updated_source_code_list = SourceCodeList([])
|
|
287
|
+
for source in source_code_list.sources:
|
|
288
|
+
updated_source_code_list.sources.append(source)
|
|
289
|
+
|
|
290
|
+
# 添加缺失的文件到源代码列表
|
|
291
|
+
for file_path in missing_files:
|
|
292
|
+
if os.path.exists(file_path):
|
|
293
|
+
with open(file_path, 'r') as f:
|
|
294
|
+
file_content = f.read()
|
|
295
|
+
source = SourceCode(module_name=file_path, source_code=file_content)
|
|
296
|
+
updated_source_code_list.sources.append(source)
|
|
297
|
+
|
|
298
|
+
# 更新action yml文件
|
|
299
|
+
if missing_files and hasattr(self.args, 'dynamic_urls') and self.args.dynamic_urls:
|
|
300
|
+
action_yml_file_manager = ActionYmlFileManager(self.args.source_dir)
|
|
301
|
+
action_file_name = os.path.basename(self.args.file)
|
|
302
|
+
update_yaml_success = action_yml_file_manager.update_yaml_field(
|
|
303
|
+
action_file_name, "dynamic_urls", self.args.dynamic_urls)
|
|
304
|
+
if not update_yaml_success:
|
|
305
|
+
self.printer.print_in_terminal(
|
|
306
|
+
"yaml_save_error", style="red", yaml_file=action_file_name)
|
|
307
|
+
|
|
308
|
+
# 准备修复提示
|
|
309
|
+
fix_prompt = self.fix_missing_context.prompt(
|
|
310
|
+
query=query,
|
|
311
|
+
original_code=generation_result.contents[0],
|
|
312
|
+
missing_files=missing_files_text
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
logger.info(f"fix_missing_context_prompt: {fix_prompt}")
|
|
316
|
+
|
|
317
|
+
# 使用修复提示重新生成代码
|
|
225
318
|
start_time = time.time()
|
|
226
319
|
generation_result = self.code_generator.single_round_run(
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
320
|
+
fix_prompt, updated_source_code_list)
|
|
321
|
+
|
|
322
|
+
# 计算这次修复缺失上下文花费的token情况
|
|
230
323
|
token_cost_calculator.track_token_usage_by_generate(
|
|
231
324
|
llm=self.llm,
|
|
232
325
|
generate=generation_result,
|
|
@@ -234,32 +327,49 @@ class CodeEditBlockManager:
|
|
|
234
327
|
start_time=start_time,
|
|
235
328
|
end_time=time.time()
|
|
236
329
|
)
|
|
330
|
+
|
|
331
|
+
# 选择最佳结果
|
|
332
|
+
generation_result = self.code_merger.choose_best_choice(generation_result)
|
|
333
|
+
## 因为已经排完结果,就不要触发后面的排序了,所以只要保留第一个即可。
|
|
334
|
+
generation_result = CodeGenerateResult(contents=[generation_result.contents[0]],conversations=[generation_result.conversations[0]],metadata=generation_result.metadata)
|
|
335
|
+
|
|
336
|
+
return generation_result
|
|
237
337
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
return generation_result
|
|
338
|
+
def _fix_unmerged_blocks(self, query: str, generation_result: CodeGenerateResult, source_code_list: SourceCodeList) -> CodeGenerateResult:
|
|
339
|
+
"""
|
|
340
|
+
修复未合并的代码块,最多尝试指定次数
|
|
242
341
|
|
|
243
|
-
|
|
244
|
-
|
|
342
|
+
参数:
|
|
343
|
+
query (str): 用户查询
|
|
344
|
+
generation_result (CodeGenerateResult): 生成的代码结果
|
|
345
|
+
source_code_list (SourceCodeList): 源代码列表
|
|
346
|
+
|
|
347
|
+
返回:
|
|
348
|
+
CodeGenerateResult: 修复后的代码结果
|
|
349
|
+
"""
|
|
350
|
+
token_cost_calculator = TokenCostCalculator(args=self.args)
|
|
351
|
+
merge = self.code_merger._merge_code_without_effect(generation_result.contents[0])
|
|
352
|
+
|
|
353
|
+
if not self.args.enable_auto_fix_merge or not merge.failed_blocks:
|
|
354
|
+
return generation_result
|
|
245
355
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
356
|
+
def _format_blocks(merge: MergeCodeWithoutEffect) -> Tuple[str, str]:
|
|
357
|
+
unmerged_formatted_text = ""
|
|
358
|
+
for file_path, head, update in merge.failed_blocks:
|
|
359
|
+
unmerged_formatted_text += "```lang\n"
|
|
360
|
+
unmerged_formatted_text += f"##File: {file_path}\n"
|
|
361
|
+
unmerged_formatted_text += "<<<<<<< SEARCH\n"
|
|
362
|
+
unmerged_formatted_text += head
|
|
363
|
+
unmerged_formatted_text += "=======\n"
|
|
364
|
+
unmerged_formatted_text += update
|
|
365
|
+
unmerged_formatted_text += ">>>>>>> REPLACE\n"
|
|
366
|
+
unmerged_formatted_text += "```"
|
|
367
|
+
unmerged_formatted_text += "\n"
|
|
368
|
+
|
|
369
|
+
merged_formatted_text = ""
|
|
370
|
+
if merge.merged_blocks:
|
|
261
371
|
for file_path, head, update in merge.merged_blocks:
|
|
262
|
-
merged_formatted_text += "```lang"
|
|
372
|
+
merged_formatted_text += "```lang\n"
|
|
263
373
|
merged_formatted_text += f"##File: {file_path}\n"
|
|
264
374
|
merged_formatted_text += head
|
|
265
375
|
merged_formatted_text += "=======\n"
|
|
@@ -267,42 +377,212 @@ class CodeEditBlockManager:
|
|
|
267
377
|
merged_formatted_text += "```"
|
|
268
378
|
merged_formatted_text += "\n"
|
|
269
379
|
|
|
380
|
+
get_event_manager(self.args.event_file).write_result(EventContentCreator.create_result(
|
|
381
|
+
content=EventContentCreator.ResultContent(content=f"Unmerged blocks:\n\n {unmerged_formatted_text}",
|
|
382
|
+
metadata={
|
|
383
|
+
"merged_blocks": merge.success_blocks,
|
|
384
|
+
"failed_blocks": merge.failed_blocks
|
|
385
|
+
}
|
|
386
|
+
).to_dict(),
|
|
387
|
+
metadata={
|
|
388
|
+
"stream_out_type": UnmergedBlocksStreamOutType.UNMERGED_BLOCKS.value,
|
|
389
|
+
"action_file": self.args.file
|
|
390
|
+
}
|
|
391
|
+
))
|
|
392
|
+
return (unmerged_formatted_text, merged_formatted_text)
|
|
393
|
+
|
|
394
|
+
for attempt in range(self.args.auto_fix_merge_max_attempts):
|
|
395
|
+
global_cancel.check_and_raise()
|
|
396
|
+
unmerged_formatted_text, merged_formatted_text = _format_blocks(merge)
|
|
397
|
+
fix_prompt = self.fix_unmerged_blocks.prompt(
|
|
398
|
+
query=query,
|
|
399
|
+
original_code=generation_result.contents[0],
|
|
400
|
+
unmerged_blocks=unmerged_formatted_text
|
|
401
|
+
)
|
|
402
|
+
|
|
403
|
+
logger.info(f"fix_prompt: {fix_prompt}")
|
|
404
|
+
|
|
405
|
+
# 打印当前修复尝试状态
|
|
406
|
+
self.printer.print_in_terminal(
|
|
407
|
+
"unmerged_blocks_attempt_status",
|
|
408
|
+
style="yellow",
|
|
409
|
+
attempt=(attempt + 1),
|
|
410
|
+
max_correction_attempts=self.args.auto_fix_merge_max_attempts
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
get_event_manager(self.args.event_file).write_result(EventContentCreator.create_result(
|
|
414
|
+
content=EventContentCreator.ResultContent(content=f"Unmerged blocks attempt {attempt + 1}/{self.args.auto_fix_merge_max_attempts}: {unmerged_formatted_text}",
|
|
415
|
+
metadata={}
|
|
416
|
+
).to_dict(),
|
|
417
|
+
metadata={
|
|
418
|
+
"stream_out_type": UnmergedBlocksStreamOutType.UNMERGED_BLOCKS.value,
|
|
419
|
+
"action_file": self.args.file
|
|
420
|
+
}
|
|
421
|
+
))
|
|
422
|
+
|
|
423
|
+
# 使用修复提示重新生成代码
|
|
424
|
+
start_time = time.time()
|
|
425
|
+
generation_result = self.code_generator.single_round_run(
|
|
426
|
+
fix_prompt, source_code_list)
|
|
427
|
+
|
|
428
|
+
# 计算这次修复未合并块花费的token情况
|
|
429
|
+
token_cost_calculator.track_token_usage_by_generate(
|
|
430
|
+
llm=self.llm,
|
|
431
|
+
generate=generation_result,
|
|
432
|
+
operation_name="code_generation_complete",
|
|
433
|
+
start_time=start_time,
|
|
434
|
+
end_time=time.time()
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
# 检查修复后的代码是否仍有未合并块
|
|
438
|
+
generation_result = self.code_merger.choose_best_choice(generation_result)
|
|
439
|
+
## 因为已经排完结果,就不要触发后面的排序了,所以只要保留第一个即可。
|
|
440
|
+
generation_result = CodeGenerateResult(contents=[generation_result.contents[0]],conversations=[generation_result.conversations[0]],metadata=generation_result.metadata)
|
|
441
|
+
merge = self.code_merger._merge_code_without_effect(
|
|
442
|
+
generation_result.contents[0])
|
|
443
|
+
|
|
444
|
+
# 如果没有失败的块,则修复成功,退出循环
|
|
445
|
+
if not merge.failed_blocks:
|
|
446
|
+
self.printer.print_in_terminal(
|
|
447
|
+
"unmerged_blocks_fixed", style="green")
|
|
448
|
+
break
|
|
449
|
+
|
|
450
|
+
# 如果是最后一次尝试仍未成功,打印警告
|
|
451
|
+
if attempt == self.args.auto_fix_merge_max_attempts - 1:
|
|
452
|
+
self.printer.print_in_terminal(
|
|
453
|
+
"max_unmerged_blocks_attempts_reached", style="yellow")
|
|
270
454
|
get_event_manager(self.args.event_file).write_result(EventContentCreator.create_result(
|
|
271
|
-
content=EventContentCreator.ResultContent(content=
|
|
272
|
-
metadata={
|
|
273
|
-
"merged_blocks": merge.success_blocks,
|
|
274
|
-
"failed_blocks": merge.failed_blocks
|
|
275
|
-
}
|
|
455
|
+
content=EventContentCreator.ResultContent(content=self.printer.get_message_from_key("max_unmerged_blocks_attempts_reached"),
|
|
456
|
+
metadata={}
|
|
276
457
|
).to_dict(),
|
|
277
458
|
metadata={
|
|
278
459
|
"stream_out_type": UnmergedBlocksStreamOutType.UNMERGED_BLOCKS.value,
|
|
279
460
|
"action_file": self.args.file
|
|
280
461
|
}
|
|
281
462
|
))
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
463
|
+
raise Exception(self.printer.get_message_from_key(
|
|
464
|
+
"max_unmerged_blocks_attempts_reached"))
|
|
465
|
+
|
|
466
|
+
return generation_result
|
|
467
|
+
|
|
468
|
+
def _fix_unmerged_blocks(self, query: str, generation_result: CodeGenerateResult, source_code_list: SourceCodeList) -> CodeGenerateResult:
|
|
469
|
+
"""
|
|
470
|
+
修复未合并的代码块,最多尝试指定次数
|
|
471
|
+
|
|
472
|
+
参数:
|
|
473
|
+
query (str): 用户查询
|
|
474
|
+
generation_result (CodeGenerateResult): 生成的代码结果
|
|
475
|
+
source_code_list (SourceCodeList): 源代码列表
|
|
476
|
+
|
|
477
|
+
返回:
|
|
478
|
+
CodeGenerateResult: 修复后的代码结果
|
|
479
|
+
"""
|
|
480
|
+
token_cost_calculator = TokenCostCalculator(args=self.args)
|
|
481
|
+
merge = self.code_merger._merge_code_without_effect(generation_result.contents[0])
|
|
482
|
+
|
|
483
|
+
if not self.args.enable_auto_fix_merge or not merge.failed_blocks:
|
|
484
|
+
return generation_result
|
|
485
|
+
|
|
486
|
+
def _format_blocks(merge: MergeCodeWithoutEffect) -> Tuple[str, str]:
|
|
487
|
+
unmerged_formatted_text = ""
|
|
488
|
+
for file_path, head, update in merge.failed_blocks:
|
|
489
|
+
unmerged_formatted_text += "```lang"
|
|
490
|
+
unmerged_formatted_text += f"##File: {file_path}\n"
|
|
491
|
+
unmerged_formatted_text += "<<<<<<< SEARCH\n"
|
|
492
|
+
unmerged_formatted_text += head
|
|
493
|
+
unmerged_formatted_text += "=======\n"
|
|
494
|
+
unmerged_formatted_text += update
|
|
495
|
+
unmerged_formatted_text += ">>>>>>> REPLACE\n"
|
|
496
|
+
unmerged_formatted_text += "```"
|
|
497
|
+
unmerged_formatted_text += "\n"
|
|
498
|
+
|
|
499
|
+
merged_formatted_text = ""
|
|
500
|
+
if merge.merged_blocks:
|
|
501
|
+
for file_path, head, update in merge.merged_blocks:
|
|
502
|
+
merged_formatted_text += "```lang"
|
|
503
|
+
merged_formatted_text += f"##File: {file_path}\n"
|
|
504
|
+
merged_formatted_text += head
|
|
505
|
+
merged_formatted_text += "=======\n"
|
|
506
|
+
merged_formatted_text += update
|
|
507
|
+
merged_formatted_text += "```"
|
|
508
|
+
merged_formatted_text += "\n"
|
|
509
|
+
|
|
510
|
+
get_event_manager(self.args.event_file).write_result(EventContentCreator.create_result(
|
|
511
|
+
content=EventContentCreator.ResultContent(content=f"Unmerged blocks:\\n {unmerged_formatted_text}",
|
|
512
|
+
metadata={
|
|
513
|
+
"merged_blocks": merge.success_blocks,
|
|
514
|
+
"failed_blocks": merge.failed_blocks
|
|
515
|
+
}
|
|
516
|
+
).to_dict(),
|
|
517
|
+
metadata={
|
|
518
|
+
"stream_out_type": UnmergedBlocksStreamOutType.UNMERGED_BLOCKS.value,
|
|
519
|
+
"action_file": self.args.file
|
|
520
|
+
}
|
|
521
|
+
))
|
|
522
|
+
return (unmerged_formatted_text, merged_formatted_text)
|
|
523
|
+
|
|
524
|
+
for attempt in range(self.args.auto_fix_merge_max_attempts):
|
|
525
|
+
global_cancel.check_and_raise()
|
|
526
|
+
unmerged_formatted_text, merged_formatted_text = _format_blocks(merge)
|
|
527
|
+
fix_prompt = self.fix_unmerged_blocks.prompt(
|
|
528
|
+
query=query,
|
|
529
|
+
original_code=generation_result.contents[0],
|
|
530
|
+
unmerged_blocks=unmerged_formatted_text
|
|
531
|
+
)
|
|
532
|
+
|
|
533
|
+
logger.info(f"fix_prompt: {fix_prompt}")
|
|
293
534
|
|
|
294
|
-
|
|
535
|
+
# 打印当前修复尝试状态
|
|
536
|
+
self.printer.print_in_terminal(
|
|
537
|
+
"unmerged_blocks_attempt_status",
|
|
538
|
+
style="yellow",
|
|
539
|
+
attempt=(attempt + 1),
|
|
540
|
+
max_correction_attempts=self.args.auto_fix_merge_max_attempts
|
|
541
|
+
)
|
|
542
|
+
|
|
543
|
+
get_event_manager(self.args.event_file).write_result(EventContentCreator.create_result(
|
|
544
|
+
content=EventContentCreator.ResultContent(content=f"Unmerged blocks attempt {attempt + 1}/{self.args.auto_fix_merge_max_attempts}: {unmerged_formatted_text}",
|
|
545
|
+
metadata={}
|
|
546
|
+
).to_dict(),
|
|
547
|
+
metadata={
|
|
548
|
+
"stream_out_type": UnmergedBlocksStreamOutType.UNMERGED_BLOCKS.value,
|
|
549
|
+
"action_file": self.args.file
|
|
550
|
+
}
|
|
551
|
+
))
|
|
552
|
+
|
|
553
|
+
# 使用修复提示重新生成代码
|
|
554
|
+
start_time = time.time()
|
|
555
|
+
generation_result = self.code_generator.single_round_run(
|
|
556
|
+
fix_prompt, source_code_list)
|
|
295
557
|
|
|
296
|
-
|
|
558
|
+
# 计算这次修复未合并块花费的token情况
|
|
559
|
+
token_cost_calculator.track_token_usage_by_generate(
|
|
560
|
+
llm=self.llm,
|
|
561
|
+
generate=generation_result,
|
|
562
|
+
operation_name="code_generation_complete",
|
|
563
|
+
start_time=start_time,
|
|
564
|
+
end_time=time.time()
|
|
565
|
+
)
|
|
566
|
+
|
|
567
|
+
# 检查修复后的代码是否仍有未合并块
|
|
568
|
+
generation_result = self.code_merger.choose_best_choice(generation_result)
|
|
569
|
+
## 因为已经排完结果,就不要触发后面的排序了,所以只要保留第一个即可。
|
|
570
|
+
generation_result = CodeGenerateResult(contents=[generation_result.contents[0]],conversations=[generation_result.conversations[0]],metadata=generation_result.metadata)
|
|
571
|
+
merge = self.code_merger._merge_code_without_effect(
|
|
572
|
+
generation_result.contents[0])
|
|
573
|
+
|
|
574
|
+
# 如果没有失败的块,则修复成功,退出循环
|
|
575
|
+
if not merge.failed_blocks:
|
|
297
576
|
self.printer.print_in_terminal(
|
|
298
|
-
"
|
|
299
|
-
|
|
300
|
-
attempt=(attempt + 1),
|
|
301
|
-
max_correction_attempts=self.args.auto_fix_merge_max_attempts
|
|
302
|
-
)
|
|
577
|
+
"unmerged_blocks_fixed", style="green")
|
|
578
|
+
break
|
|
303
579
|
|
|
580
|
+
# 如果是最后一次尝试仍未成功,打印警告
|
|
581
|
+
if attempt == self.args.auto_fix_merge_max_attempts - 1:
|
|
582
|
+
self.printer.print_in_terminal(
|
|
583
|
+
"max_unmerged_blocks_attempts_reached", style="yellow")
|
|
304
584
|
get_event_manager(self.args.event_file).write_result(EventContentCreator.create_result(
|
|
305
|
-
content=EventContentCreator.ResultContent(content=
|
|
585
|
+
content=EventContentCreator.ResultContent(content=self.printer.get_message_from_key("max_unmerged_blocks_attempts_reached"),
|
|
306
586
|
metadata={}
|
|
307
587
|
).to_dict(),
|
|
308
588
|
metadata={
|
|
@@ -310,50 +590,25 @@ class CodeEditBlockManager:
|
|
|
310
590
|
"action_file": self.args.file
|
|
311
591
|
}
|
|
312
592
|
))
|
|
593
|
+
raise Exception(self.printer.get_message_from_key(
|
|
594
|
+
"max_unmerged_blocks_attempts_reached"))
|
|
595
|
+
|
|
596
|
+
return generation_result
|
|
313
597
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
)
|
|
598
|
+
def _fix_lint_errors(self, query: str, generation_result: CodeGenerateResult, source_code_list: SourceCodeList) -> CodeGenerateResult:
|
|
599
|
+
"""
|
|
600
|
+
自动修复lint错误,最多尝试指定次数
|
|
601
|
+
|
|
602
|
+
参数:
|
|
603
|
+
query (str): 用户查询
|
|
604
|
+
generation_result (CodeGenerateResult): 生成的代码结果
|
|
605
|
+
source_code_list (SourceCodeList): 源代码列表
|
|
606
|
+
|
|
607
|
+
返回:
|
|
608
|
+
CodeGenerateResult: 修复后的代码结果
|
|
609
|
+
"""
|
|
610
|
+
token_cost_calculator = TokenCostCalculator(args=self.args)
|
|
328
611
|
|
|
329
|
-
# 检查修复后的代码是否仍有未合并块
|
|
330
|
-
result = self.code_merger.choose_best_choice(generation_result)
|
|
331
|
-
merge = self.code_merger._merge_code_without_effect(
|
|
332
|
-
result.contents[0])
|
|
333
|
-
|
|
334
|
-
# 如果没有失败的块,则修复成功,退出循环
|
|
335
|
-
if not merge.failed_blocks:
|
|
336
|
-
self.printer.print_in_terminal(
|
|
337
|
-
"unmerged_blocks_fixed", style="green")
|
|
338
|
-
break
|
|
339
|
-
|
|
340
|
-
# 如果是最后一次尝试仍未成功,打印警告
|
|
341
|
-
if attempt == self.args.auto_fix_merge_max_attempts - 1:
|
|
342
|
-
self.printer.print_in_terminal(
|
|
343
|
-
"max_unmerged_blocks_attempts_reached", style="yellow")
|
|
344
|
-
get_event_manager(self.args.event_file).write_result(EventContentCreator.create_result(
|
|
345
|
-
content=EventContentCreator.ResultContent(content=self.printer.get_message_from_key("max_unmerged_blocks_attempts_reached"),
|
|
346
|
-
metadata={}
|
|
347
|
-
).to_dict(),
|
|
348
|
-
metadata={
|
|
349
|
-
"stream_out_type": UnmergedBlocksStreamOutType.UNMERGED_BLOCKS.value,
|
|
350
|
-
"action_file": self.args.file
|
|
351
|
-
}
|
|
352
|
-
))
|
|
353
|
-
raise Exception(self.printer.get_message_from_key(
|
|
354
|
-
"max_unmerged_blocks_attempts_reached"))
|
|
355
|
-
|
|
356
|
-
# 最多尝试修复5次
|
|
357
612
|
for attempt in range(self.auto_fix_lint_max_attempts):
|
|
358
613
|
global_cancel.check_and_raise()
|
|
359
614
|
# 代码生成结果更新到影子文件里去
|
|
@@ -368,8 +623,6 @@ class CodeEditBlockManager:
|
|
|
368
623
|
# 运行linter
|
|
369
624
|
lint_results = self.shadow_linter.lint_all_shadow_files()
|
|
370
625
|
error_count = self._count_errors(lint_results)
|
|
371
|
-
# print(f"error_count: {error_count}")
|
|
372
|
-
# print(f"lint_results: {json.dumps(lint_results.model_dump(), indent=4,ensure_ascii=False)}")
|
|
373
626
|
|
|
374
627
|
# 如果没有错误则完成
|
|
375
628
|
if error_count == 0:
|
|
@@ -413,10 +666,6 @@ class CodeEditBlockManager:
|
|
|
413
666
|
lint_issues=formatted_issues
|
|
414
667
|
)
|
|
415
668
|
|
|
416
|
-
# for source in source_code_list.sources:
|
|
417
|
-
# print(f"file_path: {source.module_name}")
|
|
418
|
-
# print(f"fix_prompt: {fix_prompt}")
|
|
419
|
-
|
|
420
669
|
# 将 shadow_files 转化为 source_code_list
|
|
421
670
|
start_time = time.time()
|
|
422
671
|
source_code_list = self.code_merger.get_source_code_list_from_shadow_files(
|
|
@@ -424,7 +673,7 @@ class CodeEditBlockManager:
|
|
|
424
673
|
generation_result = self.code_generator.single_round_run(
|
|
425
674
|
fix_prompt, source_code_list)
|
|
426
675
|
|
|
427
|
-
# 计算这次修复lint
|
|
676
|
+
# 计算这次修复lint问题花费的token情况
|
|
428
677
|
token_cost_calculator.track_token_usage_by_generate(
|
|
429
678
|
llm=self.llm,
|
|
430
679
|
generate=generation_result,
|
|
@@ -432,67 +681,135 @@ class CodeEditBlockManager:
|
|
|
432
681
|
start_time=start_time,
|
|
433
682
|
end_time=time.time()
|
|
434
683
|
)
|
|
684
|
+
|
|
685
|
+
return generation_result
|
|
435
686
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
global_cancel.check_and_raise()
|
|
440
|
-
# 先更新增量影子系统的文件
|
|
441
|
-
shadow_files = self._create_shadow_files_from_edits(
|
|
442
|
-
generation_result)
|
|
687
|
+
def _fix_compile_errors(self, query: str, generation_result: CodeGenerateResult, source_code_list: SourceCodeList) -> CodeGenerateResult:
|
|
688
|
+
"""
|
|
689
|
+
自动修复编译错误,最多尝试指定次数
|
|
443
690
|
|
|
444
|
-
|
|
445
|
-
|
|
691
|
+
参数:
|
|
692
|
+
query (str): 用户查询
|
|
693
|
+
generation_result (CodeGenerateResult): 生成的代码结果
|
|
694
|
+
source_code_list (SourceCodeList): 源代码列表
|
|
446
695
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
696
|
+
返回:
|
|
697
|
+
CodeGenerateResult: 修复后的代码结果
|
|
698
|
+
"""
|
|
699
|
+
if not self.args.enable_auto_fix_compile:
|
|
700
|
+
return generation_result
|
|
701
|
+
|
|
702
|
+
token_cost_calculator = TokenCostCalculator(args=self.args)
|
|
703
|
+
|
|
704
|
+
for attempt in range(self.auto_fix_compile_max_attempts):
|
|
705
|
+
global_cancel.check_and_raise()
|
|
706
|
+
# 先更新增量影子系统的文件
|
|
707
|
+
shadow_files = self._create_shadow_files_from_edits(
|
|
708
|
+
generation_result)
|
|
709
|
+
|
|
710
|
+
# 在影子系统生成完整的项目,然后编译
|
|
711
|
+
compile_result = self.shadow_compiler.compile_all_shadow_files()
|
|
452
712
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
metadata={
|
|
459
|
-
"stream_out_type": CompileStreamOutType.COMPILE.value,
|
|
460
|
-
"action_file": self.args.file
|
|
461
|
-
}
|
|
462
|
-
))
|
|
713
|
+
# 如果编译成功,则退出,继续往后走
|
|
714
|
+
if compile_result.success or compile_result.total_errors == 0:
|
|
715
|
+
self.printer.print_in_terminal(
|
|
716
|
+
"compile_success", style="green")
|
|
717
|
+
break
|
|
463
718
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
formatted_issues=compile_result.to_str())
|
|
475
|
-
|
|
476
|
-
fix_compile_prompt = self.fix_compile_errors.prompt(
|
|
477
|
-
query=query,
|
|
478
|
-
compile_errors=compile_result.to_str()
|
|
479
|
-
)
|
|
719
|
+
# 如果有错误,则把compile结果记录到事件系统
|
|
720
|
+
get_event_manager(self.args.event_file).write_result(EventContentCreator.create_result(
|
|
721
|
+
content=EventContentCreator.ResultContent(content=f"Compile attempt {attempt + 1}/{self.auto_fix_compile_max_attempts}: Found {compile_result.total_errors} errors:\n {compile_result.to_str()}",
|
|
722
|
+
metadata={}
|
|
723
|
+
).to_dict(),
|
|
724
|
+
metadata={
|
|
725
|
+
"stream_out_type": CompileStreamOutType.COMPILE.value,
|
|
726
|
+
"action_file": self.args.file
|
|
727
|
+
}
|
|
728
|
+
))
|
|
480
729
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
)
|
|
730
|
+
if attempt == self.auto_fix_compile_max_attempts - 1:
|
|
731
|
+
self.printer.print_in_terminal(
|
|
732
|
+
"max_compile_attempts_reached", style="yellow")
|
|
733
|
+
break
|
|
734
|
+
|
|
735
|
+
# 打印当前compile错误
|
|
736
|
+
self.printer.print_in_terminal("compile_attempt_status",
|
|
737
|
+
style="yellow",
|
|
738
|
+
attempt=(attempt + 1), max_correction_attempts=self.auto_fix_compile_max_attempts,
|
|
739
|
+
error_count=compile_result.total_errors,
|
|
740
|
+
formatted_issues=compile_result.to_str())
|
|
741
|
+
|
|
742
|
+
fix_compile_prompt = self.fix_compile_errors.prompt(
|
|
743
|
+
query=query,
|
|
744
|
+
compile_errors=compile_result.to_str()
|
|
745
|
+
)
|
|
746
|
+
|
|
747
|
+
# 将 shadow_files 转化为 source_code_list
|
|
748
|
+
start_time = time.time()
|
|
749
|
+
source_code_list = self.code_merger.get_source_code_list_from_shadow_files(
|
|
750
|
+
shadow_files)
|
|
751
|
+
generation_result = self.code_generator.single_round_run(
|
|
752
|
+
fix_compile_prompt, source_code_list)
|
|
753
|
+
|
|
754
|
+
# 计算这次修复compile问题花费的token情况
|
|
755
|
+
token_cost_calculator.track_token_usage_by_generate(
|
|
756
|
+
llm=self.llm,
|
|
757
|
+
generate=generation_result,
|
|
758
|
+
operation_name="code_generation_complete",
|
|
759
|
+
start_time=start_time,
|
|
760
|
+
end_time=time.time()
|
|
761
|
+
)
|
|
762
|
+
|
|
763
|
+
return generation_result
|
|
764
|
+
|
|
765
|
+
def generate_and_fix(self, query: str, source_code_list: SourceCodeList) -> CodeGenerateResult:
|
|
766
|
+
"""
|
|
767
|
+
生成代码,运行linter/compile,修复错误,最多尝试指定次数
|
|
768
|
+
|
|
769
|
+
参数:
|
|
770
|
+
query (str): 用户查询
|
|
771
|
+
source_code_list (SourceCodeList): 源代码列表
|
|
772
|
+
|
|
773
|
+
返回:
|
|
774
|
+
CodeGenerateResult: 生成的代码结果
|
|
775
|
+
"""
|
|
776
|
+
# 初始代码生成
|
|
777
|
+
self.printer.print_in_terminal("generating_initial_code")
|
|
778
|
+
start_time = time.time()
|
|
779
|
+
generation_result = self.code_generator.single_round_run(
|
|
780
|
+
query, source_code_list)
|
|
781
|
+
|
|
782
|
+
token_cost_calculator = TokenCostCalculator(args=self.args)
|
|
783
|
+
token_cost_calculator.track_token_usage_by_generate(
|
|
784
|
+
llm=self.llm,
|
|
785
|
+
generate=generation_result,
|
|
786
|
+
operation_name="code_generation_complete",
|
|
787
|
+
start_time=start_time,
|
|
788
|
+
end_time=time.time()
|
|
789
|
+
)
|
|
790
|
+
|
|
791
|
+
# 确保结果非空
|
|
792
|
+
if not generation_result.contents:
|
|
793
|
+
self.printer.print_in_terminal("generation_failed", style="red")
|
|
794
|
+
return generation_result
|
|
795
|
+
|
|
796
|
+
## 可能第一次触发排序
|
|
797
|
+
generation_result = self.code_merger.choose_best_choice(generation_result)
|
|
798
|
+
|
|
799
|
+
## 因为已经排完结果,就不要触发后面的排序了,所以只要保留第一个即可。
|
|
800
|
+
generation_result = CodeGenerateResult(contents=[generation_result.contents[0]],conversations=[generation_result.conversations[0]],metadata=generation_result.metadata)
|
|
801
|
+
|
|
802
|
+
# 修复缺少上下文的文件
|
|
803
|
+
generation_result = self._fix_missing_context(query, generation_result, source_code_list)
|
|
804
|
+
|
|
805
|
+
# 修复未合并的代码块
|
|
806
|
+
generation_result = self._fix_unmerged_blocks(query, generation_result, source_code_list)
|
|
807
|
+
|
|
808
|
+
# 修复lint错误
|
|
809
|
+
generation_result = self._fix_lint_errors(query, generation_result, source_code_list)
|
|
810
|
+
|
|
811
|
+
# 修复编译错误
|
|
812
|
+
generation_result = self._fix_compile_errors(query, generation_result, source_code_list)
|
|
496
813
|
|
|
497
814
|
# 清理临时影子文件
|
|
498
815
|
self.shadow_manager.clean_shadows()
|