diff --git a/metagpt/ext/cr/actions/code_review.py b/metagpt/ext/cr/actions/code_review.py index 5f861c3e3..0235dc2c6 100644 --- a/metagpt/ext/cr/actions/code_review.py +++ b/metagpt/ext/cr/actions/code_review.py @@ -175,13 +175,16 @@ class CodeReview(Action): async def cr_by_points(self, patch: PatchSet, points: list[Point]): comments = [] + valid_patch_count = 0 for patched_file in patch: if not patched_file: continue if patched_file.path.endswith(".py"): points = [p for p in points if p.language == "Python"] + valid_patch_count += 1 elif patched_file.path.endswith(".java"): points = [p for p in points if p.language == "Java"] + valid_patch_count += 1 else: continue group_points = [points[i : i + 3] for i in range(0, len(points), 3)] @@ -198,6 +201,9 @@ class CodeReview(Action): c["commented_file"] = patched_file_path comments.extend(comments_batch) + if valid_patch_count == 0: + raise ValueError("Only code reviews for Python and Java languages are supported.") + return comments async def run(self, patch: PatchSet, points: list[Point], output_file: str): diff --git a/metagpt/roles/di/engineer2.py b/metagpt/roles/di/engineer2.py index 7a862dfcd..bcd5f5738 100644 --- a/metagpt/roles/di/engineer2.py +++ b/metagpt/roles/di/engineer2.py @@ -13,6 +13,7 @@ from metagpt.prompts.di.engineer2 import ( from metagpt.roles.di.role_zero import RoleZero from metagpt.schema import UserMessage from metagpt.strategy.experience_retriever import ENGINEER_EXAMPLE +from metagpt.tools.libs.cr import CodeReview from metagpt.tools.libs.terminal import Terminal from metagpt.tools.tool_registry import register_tool from metagpt.utils.common import CodeParser, awrite @@ -28,14 +29,17 @@ class Engineer2(RoleZero): terminal: Terminal = Field(default_factory=Terminal, exclude=True) - tools: list[str] = ["Plan", "Editor:read", "RoleZero", "Terminal:run_command", "SearchEnhancedQA", "Engineer2"] + tools: list[str] = ["Plan", "Editor:read", "RoleZero", "Terminal:run_command", "Engineer2", "SearchEnhancedQA", "CodeReview"] def _update_tool_execution(self): # validate = ValidateAndRewriteCode() + cr = CodeReview() self.tool_execution_map.update( { "Terminal.run_command": self.terminal.run_command, "Engineer2.write_new_code": self.write_new_code, + "CodeReview.review": cr.review, + "CodeReview.fix": cr.fix, # "ValidateAndRewriteCode.run": validate.run, # "ValidateAndRewriteCode": validate.run, } diff --git a/metagpt/tools/libs/cr.py b/metagpt/tools/libs/cr.py index 7d156b4d6..0a53dd194 100644 --- a/metagpt/tools/libs/cr.py +++ b/metagpt/tools/libs/cr.py @@ -45,11 +45,15 @@ class CodeReview: """ patch = await self._get_patch_content(patch_path) point_file = point_file if point_file else Path(metagpt.ext.cr.__file__).parent / "points.json" + await EditorReporter().async_report(str(point_file), "path") async with aiofiles.open(point_file, "rb") as f: cr_point_content = await f.read() cr_points = [Point(**i) for i in json.loads(cr_point_content)] - comments = await CodeReview_().run(patch, cr_points, output_file) - return f"The number of defects: {len(comments)} and the comments are stored in {output_file}" + try: + comments = await CodeReview_().run(patch, cr_points, output_file) + except ValueError as e: + return str(e) + return f"The number of defects: {len(comments)}, the comments are stored in {output_file}, and the checkpoints are stored in {str(point_file)}" async def fix( self,