mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-05-11 08:42:38 +02:00
add support for local file cr
This commit is contained in:
parent
f513e7925d
commit
13f0e6b3dd
2 changed files with 52 additions and 23 deletions
|
|
@ -4,7 +4,9 @@
|
|||
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
import aiofiles
|
||||
from unidiff import PatchSet
|
||||
|
||||
from metagpt.actions.action import Action
|
||||
|
|
@ -16,6 +18,7 @@ from metagpt.ext.cr.utils.cleaner import (
|
|||
from metagpt.ext.cr.utils.schema import Point
|
||||
from metagpt.logs import logger
|
||||
from metagpt.utils.common import parse_json_code_block
|
||||
from metagpt.utils.report import EditorReporter
|
||||
|
||||
CODE_REVIEW_PROMPT_TEMPLATE = """
|
||||
NOTICE
|
||||
|
|
@ -193,16 +196,26 @@ class CodeReview(Action):
|
|||
patched_file_path = patched_file.path
|
||||
for c in comments_batch:
|
||||
c["commented_file"] = patched_file_path
|
||||
comments += comments_batch
|
||||
comments.extend(comments_batch)
|
||||
|
||||
return comments
|
||||
|
||||
async def run(self, patch: PatchSet, points: list[Point]):
|
||||
async def run(self, patch: PatchSet, points: list[Point], output_file: str):
|
||||
patch: PatchSet = rm_patch_useless_part(patch)
|
||||
patch: PatchSet = add_line_num_on_patch(patch)
|
||||
|
||||
result = []
|
||||
comments = await self.cr_by_points(patch=patch, points=points)
|
||||
async with EditorReporter(enable_llm_stream=True) as reporter:
|
||||
log_cr_output_path = Path(output_file).with_suffix(".log")
|
||||
await reporter.async_report(
|
||||
{"src_path": str(log_cr_output_path), "filename": log_cr_output_path.name}, "meta"
|
||||
)
|
||||
comments = await self.cr_by_points(patch=patch, points=points)
|
||||
log_cr_output_path.parent.mkdir(exist_ok=True, parents=True)
|
||||
async with aiofiles.open(log_cr_output_path, "w", encoding="utf-8") as f:
|
||||
await f.write(json.dumps(comments, ensure_ascii=False, indent=2))
|
||||
await reporter.async_report(log_cr_output_path)
|
||||
|
||||
if len(comments) != 0:
|
||||
comments = self.format_comments(comments, points, patch)
|
||||
comments = await self.confirm_comments(patch=patch, comments=comments, points=points)
|
||||
|
|
@ -210,4 +223,14 @@ class CodeReview(Action):
|
|||
if comment["code"]:
|
||||
if not (comment["code"].isspace()):
|
||||
result.append(comment)
|
||||
|
||||
async with EditorReporter() as reporter:
|
||||
src_path = output_file
|
||||
cr_output_path = Path(output_file)
|
||||
await reporter.async_report(
|
||||
{"type": "CodeReview", "src_path": src_path, "filename": cr_output_path.name}, "meta"
|
||||
)
|
||||
async with aiofiles.open(cr_output_path, "w", encoding="utf-8") as f:
|
||||
await f.write(json.dumps(comments, ensure_ascii=False, indent=2))
|
||||
await reporter.async_report(cr_output_path)
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import difflib
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
|
@ -22,35 +23,34 @@ class CodeReview:
|
|||
async def review(
|
||||
self,
|
||||
patch_path: str,
|
||||
cr_output_file: str,
|
||||
cr_point_file: Optional[str] = None,
|
||||
output_file: str,
|
||||
point_file: Optional[str] = None,
|
||||
) -> str:
|
||||
"""Review a PR and save code review comments.
|
||||
|
||||
Notes:
|
||||
If the user does not specify an output path, saved it using a relative path in the current working directory.
|
||||
|
||||
Args:
|
||||
patch_path: The local path of the patch file or the url of the pull request. Example: "/data/xxx-pr-1.patch", "https://github.com/xx/XX/pull/1362"
|
||||
cr_output_file: Output file path where code review comments will be saved. Example: "cr/xxx-pr-1.json"
|
||||
cr_point_file: File path for specifying code review points. If not specified, this parameter is not passed..
|
||||
patch_path: The local path of the patch file or the URL of the pull request.
|
||||
output_file: Output file path where code review comments will be saved.
|
||||
point_file: File path for specifying code review points. If not specified, this parameter does not need to be passed.
|
||||
|
||||
Examples:
|
||||
|
||||
>>> cr = CodeReview()
|
||||
>>> await cr.review(patch_path="https://github.com/geekan/MetaGPT/pull/136", output_file="cr/MetaGPT_136.json")
|
||||
>>> await cr.review(patch_path="/data/uploads/dev-master.diff", output_file="cr/dev-master.json")
|
||||
>>> await cr.review(patch_path="/data/uploads/main.py", output_file="cr/main.json")
|
||||
"""
|
||||
patch = await self._get_patch_content(patch_path)
|
||||
cr_point_file = cr_point_file if cr_point_file else Path(metagpt.ext.cr.__file__).parent / "points.json"
|
||||
async with aiofiles.open(cr_point_file, "rb") as f:
|
||||
point_file = point_file if point_file else Path(metagpt.ext.cr.__file__).parent / "points.json"
|
||||
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)]
|
||||
|
||||
async with EditorReporter(enable_llm_stream=True) as reporter:
|
||||
src_path = cr_output_file
|
||||
cr_output_path = Path(cr_output_file)
|
||||
await reporter.async_report(
|
||||
{"type": "CodeReview", "src_path": src_path, "filename": cr_output_path.name}, "meta"
|
||||
)
|
||||
comments = await CodeReview_().run(patch, cr_points)
|
||||
cr_output_path.parent.mkdir(exist_ok=True, parents=True)
|
||||
async with aiofiles.open(cr_output_path, "w", encoding="utf-8") as f:
|
||||
await f.write(json.dumps(comments, ensure_ascii=False))
|
||||
await reporter.async_report(cr_output_path)
|
||||
|
||||
return f"The number of defects: {len(comments)} and the comments are stored in {cr_output_file}"
|
||||
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}"
|
||||
|
||||
async def fix(
|
||||
self,
|
||||
|
|
@ -88,6 +88,12 @@ class CodeReview:
|
|||
async with aiofiles.open(patch_path, encoding="utf-8") as f:
|
||||
patch_file_content = await f.read()
|
||||
await EditorReporter().async_report(patch_path)
|
||||
if not patch_path.endswith((".diff", "patch")):
|
||||
name = Path(patch_path).name
|
||||
patch_file_content = "".join(
|
||||
difflib.unified_diff([], patch_file_content.splitlines(keepends=True), "/dev/null", f"b/{name}"),
|
||||
)
|
||||
patch_file_content = f"diff --git a/{name} b/{name}\n{patch_file_content}"
|
||||
|
||||
patch: PatchSet = PatchSet(patch_file_content)
|
||||
return patch
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue