mirror of
https://github.com/FoundationAgents/MetaGPT.git
synced 2026-04-29 10:56:22 +02:00
add cr tool
This commit is contained in:
parent
4dfe8524a1
commit
4cb0696df0
9 changed files with 781 additions and 0 deletions
90
metagpt/tools/libs/cr.py
Normal file
90
metagpt/tools/libs/cr.py
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
import json
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
import aiofiles
|
||||
from unidiff import PatchSet
|
||||
|
||||
import metagpt.ext.cr
|
||||
from metagpt.ext.cr.actions.code_review import CodeReview as CodeReview_
|
||||
from metagpt.ext.cr.actions.modify_code import ModifyCode
|
||||
from metagpt.ext.cr.utils.schema import Point
|
||||
from metagpt.tools.libs.browser import Browser
|
||||
from metagpt.tools.tool_registry import register_tool
|
||||
from metagpt.utils.report import EditorReporter
|
||||
|
||||
|
||||
@register_tool(tags=["codereview"], include_functions=["review", "fix"])
|
||||
class CodeReview:
|
||||
"""Review and fix the patch content from the pull request URL or a file."""
|
||||
|
||||
async def review(
|
||||
self,
|
||||
patch_path: str,
|
||||
cr_output_file: str,
|
||||
cr_point_file: Optional[str] = None,
|
||||
) -> str:
|
||||
"""Review a PR and save code review comments.
|
||||
|
||||
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. Defaults to a predefined file.
|
||||
"""
|
||||
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:
|
||||
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") 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}"
|
||||
|
||||
async def fix(
|
||||
self,
|
||||
patch_path: str,
|
||||
cr_file: str,
|
||||
output_dir: str,
|
||||
) -> str:
|
||||
"""Fix the patch content based on code review comments.
|
||||
|
||||
Args:
|
||||
patch_path: The local path of the patch file or the url of the pull request.
|
||||
cr_file: File path where code review comments are stored.
|
||||
output_dir: File path where code review comments are stored.
|
||||
"""
|
||||
patch = await self._get_patch_content(patch_path)
|
||||
async with aiofiles.open(cr_file, "r") as f:
|
||||
comments = json.loads(await f.read())
|
||||
await ModifyCode(pr="").run(patch, comments, output_dir)
|
||||
return f"The fixed patch files store in {output_dir}"
|
||||
|
||||
async def _get_patch_content(self, patch_path):
|
||||
if patch_path.startswith(("https://", "http://")):
|
||||
# async with aiohttp.ClientSession(trust_env=True) as client:
|
||||
# async with client.get(f"{patch_path}.diff", ) as resp:
|
||||
# patch_file_content = await resp.text()
|
||||
browser = Browser()
|
||||
browser.proxy = {"server": "http://127.0.0.1:20172"}
|
||||
async with browser:
|
||||
await browser.goto(f"{patch_path}.diff")
|
||||
patch_file_content = await browser.page.content()
|
||||
|
||||
else:
|
||||
async with aiofiles.open(patch_path) as f:
|
||||
patch_file_content = await f.read()
|
||||
await EditorReporter().async_report(patch_path)
|
||||
|
||||
patch: PatchSet = PatchSet(patch_file_content)
|
||||
return patch
|
||||
Loading…
Add table
Add a link
Reference in a new issue