Merge pull request '代理实现:Enhancement: 检查现有的代码框架,确认是否需要优化' (#4) from agent/issue-3-enhancement into main
Reviewed-on: http://gahow-pc.ipads-lab.se.sjtu.edu.cn:3300/gahow/agent-manager/pulls/4
This commit is contained in:
@@ -85,25 +85,34 @@ class GiteaClient:
|
|||||||
return repositories
|
return repositories
|
||||||
|
|
||||||
def list_open_issues(self, owner: str, name: str) -> list[GiteaIssue]:
|
def list_open_issues(self, owner: str, name: str) -> list[GiteaIssue]:
|
||||||
response = self.client.get(
|
|
||||||
f"/repos/{owner}/{name}/issues",
|
|
||||||
params={"state": "open", "type": "issues", "limit": 50},
|
|
||||||
)
|
|
||||||
response.raise_for_status()
|
|
||||||
issues: list[GiteaIssue] = []
|
issues: list[GiteaIssue] = []
|
||||||
for item in response.json():
|
page = 1
|
||||||
if item.get("pull_request"):
|
limit = 50
|
||||||
continue
|
while True:
|
||||||
issues.append(
|
response = self.client.get(
|
||||||
GiteaIssue(
|
f"/repos/{owner}/{name}/issues",
|
||||||
number=int(item["number"]),
|
params={"state": "open", "type": "issues", "page": page, "limit": limit},
|
||||||
title=item.get("title") or "",
|
|
||||||
body=item.get("body") or "",
|
|
||||||
labels=labels_from_gitea(item.get("labels")),
|
|
||||||
state=item.get("state") or "open",
|
|
||||||
html_url=item.get("html_url") or item.get("url") or "",
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
payload = response.json()
|
||||||
|
if not payload:
|
||||||
|
break
|
||||||
|
for item in payload:
|
||||||
|
if item.get("pull_request"):
|
||||||
|
continue
|
||||||
|
issues.append(
|
||||||
|
GiteaIssue(
|
||||||
|
number=int(item["number"]),
|
||||||
|
title=item.get("title") or "",
|
||||||
|
body=item.get("body") or "",
|
||||||
|
labels=labels_from_gitea(item.get("labels")),
|
||||||
|
state=item.get("state") or "open",
|
||||||
|
html_url=item.get("html_url") or item.get("url") or "",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if len(payload) < limit:
|
||||||
|
break
|
||||||
|
page += 1
|
||||||
return issues
|
return issues
|
||||||
|
|
||||||
def create_pull_request(
|
def create_pull_request(
|
||||||
|
|||||||
@@ -86,11 +86,13 @@ def render_pr_body(issue: IssueRecord, implementation_report: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def parse_review_report(raw: str) -> ReviewReport:
|
def parse_review_report(raw: str) -> ReviewReport:
|
||||||
verdict_match = re.search(r"(?im)^\s*(?:##\s*)?Verdict\s*:?\s*`?([A-Z_]+)`?", raw)
|
verdict_match = re.search(r"(?im)^\s*(?:[-*]\s*)?(?:##\s*)?Verdict\s*:?\s*`?([A-Z_]+)`?", raw)
|
||||||
verdict = verdict_match.group(1) if verdict_match else "NEEDS_HUMAN_DECISION"
|
verdict = verdict_match.group(1) if verdict_match else "NEEDS_HUMAN_DECISION"
|
||||||
if verdict not in VALID_VERDICTS:
|
if verdict not in VALID_VERDICTS:
|
||||||
verdict = "NEEDS_HUMAN_DECISION"
|
verdict = "NEEDS_HUMAN_DECISION"
|
||||||
suggested = extract_section(raw, "Suggested PR Comment").strip()
|
suggested = extract_section(raw, "Suggested PR Comment").strip()
|
||||||
|
if not suggested:
|
||||||
|
suggested = extract_inline_field(raw, "Suggested PR Comment").strip()
|
||||||
if not suggested:
|
if not suggested:
|
||||||
suggested = raw.strip()
|
suggested = raw.strip()
|
||||||
return ReviewReport(verdict=verdict, raw=raw, suggested_pr_comment=suggested)
|
return ReviewReport(verdict=verdict, raw=raw, suggested_pr_comment=suggested)
|
||||||
@@ -104,6 +106,12 @@ def extract_section(raw: str, title: str) -> str:
|
|||||||
return match.group("body") if match else ""
|
return match.group("body") if match else ""
|
||||||
|
|
||||||
|
|
||||||
|
def extract_inline_field(raw: str, title: str) -> str:
|
||||||
|
pattern = re.compile(rf"(?im)^\s*(?:[-*]\s*)?{re.escape(title)}\s*:\s*(?P<body>.+?)\s*$")
|
||||||
|
match = pattern.search(raw)
|
||||||
|
return match.group("body") if match else ""
|
||||||
|
|
||||||
|
|
||||||
def render_human_review_summary(review: ReviewReport) -> str:
|
def render_human_review_summary(review: ReviewReport) -> str:
|
||||||
return f"""## 代理评审摘要
|
return f"""## 代理评审摘要
|
||||||
|
|
||||||
|
|||||||
@@ -119,6 +119,49 @@ def test_list_open_issues_keeps_normal_issues_with_null_pull_request():
|
|||||||
assert [issue.number for issue in issues] == [1]
|
assert [issue.number for issue in issues] == [1]
|
||||||
|
|
||||||
|
|
||||||
|
def test_list_open_issues_reads_all_pages():
|
||||||
|
seen_pages: list[int] = []
|
||||||
|
|
||||||
|
def handler(request: httpx.Request) -> httpx.Response:
|
||||||
|
assert request.url.path == "/api/v1/repos/acme/service/issues"
|
||||||
|
page = int(request.url.params["page"])
|
||||||
|
limit = int(request.url.params["limit"])
|
||||||
|
seen_pages.append(page)
|
||||||
|
if page == 1:
|
||||||
|
return httpx.Response(
|
||||||
|
200,
|
||||||
|
json=[
|
||||||
|
{
|
||||||
|
"number": number,
|
||||||
|
"title": f"Issue {number}",
|
||||||
|
"body": "",
|
||||||
|
"state": "open",
|
||||||
|
"labels": [],
|
||||||
|
}
|
||||||
|
for number in range(1, limit + 1)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
if page == 2:
|
||||||
|
return httpx.Response(
|
||||||
|
200,
|
||||||
|
json=[
|
||||||
|
{
|
||||||
|
"number": 51,
|
||||||
|
"title": "Issue 51",
|
||||||
|
"body": "",
|
||||||
|
"state": "open",
|
||||||
|
"labels": [],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
)
|
||||||
|
return httpx.Response(500)
|
||||||
|
|
||||||
|
issues = make_client(handler).list_open_issues("acme", "service")
|
||||||
|
|
||||||
|
assert [issue.number for issue in issues] == list(range(1, 52))
|
||||||
|
assert seen_pages == [1, 2]
|
||||||
|
|
||||||
|
|
||||||
class FakeWorkspaceManager:
|
class FakeWorkspaceManager:
|
||||||
def __init__(self, root: Path, *, diff: bool = True):
|
def __init__(self, root: Path, *, diff: bool = True):
|
||||||
self.root = root
|
self.root = root
|
||||||
|
|||||||
@@ -58,3 +58,15 @@ Please add tests.
|
|||||||
|
|
||||||
assert parsed.verdict == "REQUEST_CHANGES"
|
assert parsed.verdict == "REQUEST_CHANGES"
|
||||||
assert parsed.suggested_pr_comment == "Please add tests."
|
assert parsed.suggested_pr_comment == "Please add tests."
|
||||||
|
|
||||||
|
|
||||||
|
def test_review_report_parsing_accepts_prompt_bullet_contract():
|
||||||
|
report = """- Verdict: APPROVE
|
||||||
|
- Summary: Done
|
||||||
|
- Suggested PR Comment: Looks good.
|
||||||
|
"""
|
||||||
|
|
||||||
|
parsed = parse_review_report(report)
|
||||||
|
|
||||||
|
assert parsed.verdict == "APPROVE"
|
||||||
|
assert parsed.suggested_pr_comment == "Looks good."
|
||||||
|
|||||||
Reference in New Issue
Block a user