feat(python/robomp): added followup thread context to comment handling

- Normalized reviewer-bot matching by stripping a trailing `[bot]` suffix when resolving configured bot logins.
- Fetched PR thread history for followup comments without directives and carried it through task execution.
- Updated followup prompt rendering to include prior conversation context for handle_comment tasks.
This commit is contained in:
can1357
2026-05-25 20:09:26 +02:00
parent 7a867a5e85
commit 4cd86383c0
8 changed files with 117 additions and 11 deletions
+2 -2
View File
@@ -592,7 +592,7 @@ def test_route_reviewer_bot_comment_is_directive_without_mention() -> None:
{
"action": "created",
"comment": {
"user": {"login": "chatgpt-codex-connector", "type": "Bot"},
"user": {"login": "chatgpt-codex-connector[bot]", "type": "Bot"},
"body": "Found two issues in the diff: ...",
},
"issue": {"number": 9, "pull_request": {"url": "x"}},
@@ -616,7 +616,7 @@ def test_route_reviewer_bot_review_comment_is_directive() -> None:
{
"action": "created",
"comment": {
"user": {"login": "chatgpt-codex-connector", "type": "Bot"},
"user": {"login": "chatgpt-codex-connector[bot]", "type": "Bot"},
"body": "This branch leaks memory.",
},
"pull_request": {"number": 50, "user": {"login": BOT}},
+21
View File
@@ -102,6 +102,27 @@ def test_directive_prompt_embeds_thread_and_directive_body() -> None:
assert "PR #1080 is open" in out
def test_followup_comment_prompt_embeds_thread_context() -> None:
thread = (
ThreadMessage(kind="pr_body", author="roboomp", body="PR body", created_at=""),
ThreadMessage(kind="comment", author="can1357", body="prior request", created_at="2026-05-01T10:00:00Z"),
)
out = persona.followup_comment(
repo=_Repo(),
issue=_Issue(),
comment=_Comment(body="current request"),
workspace=_Workspace(),
pr_status="PR #1080 is open",
pr_number=1080,
thread=thread,
)
assert "Prior conversation" in out
assert "PR body" in out
assert "prior request" in out
assert "current request" in out
def test_kickoff_directive_prompt_embeds_thread_and_classify_instruction() -> None:
thread = (ThreadMessage(kind="issue_body", author="alice", body="failing on macos", created_at=""),)
out = persona.kickoff_directive(
+61 -4
View File
@@ -1610,7 +1610,7 @@ async def test_handle_pr_conversation_unmapped_bot_pr_uses_pr_branch(
settings: Settings, tmp_path: Path, stub_run_task, monkeypatch
) -> None:
from robomp import tasks
from robomp.github_client import IssueInfo, PullRequestInfo, RepoInfo
from robomp.github_client import CommentInfo, IssueInfo, PullRequestInfo, RepoInfo
sandbox = _RecordingSandbox(tmp_path)
db = get_database(settings.sqlite_path)
@@ -1652,9 +1652,27 @@ async def test_handle_pr_conversation_unmapped_bot_pr_uses_pr_branch(
assert number == 900
return pr_issue
async def _list_comments(self, repo_full: str, number: int):
assert repo_full == "octo/widget"
assert number == 900
return [CommentInfo(id=77, author="can1357", body="prior PR context", created_at="2026-05-14T00:00:00Z")]
async def _list_review_comments(self, repo_full: str, number: int):
assert repo_full == "octo/widget"
assert number == 900
return []
async def _list_pr_reviews(self, repo_full: str, number: int):
assert repo_full == "octo/widget"
assert number == 900
return []
monkeypatch.setattr(GitHubClient, "get_pull_request", _get_pull_request)
monkeypatch.setattr(GitHubClient, "get_repo", _get_repo)
monkeypatch.setattr(GitHubClient, "get_issue", _get_issue)
monkeypatch.setattr(GitHubClient, "list_comments", _list_comments)
monkeypatch.setattr(GitHubClient, "list_review_comments", _list_review_comments)
monkeypatch.setattr(GitHubClient, "list_pr_reviews", _list_pr_reviews)
payload = {
"action": "created",
@@ -1677,6 +1695,10 @@ async def test_handle_pr_conversation_unmapped_bot_pr_uses_pr_branch(
assert call["task_kind"] == "handle_comment"
assert call["pr_number"] == 900
assert call["inputs"].issue.is_pull_request is True
assert [(m.kind, m.author, m.body) for m in call["thread"]] == [
("pr_body", settings.bot_login, "PR body"),
("comment", "can1357", "prior PR context"),
]
assert sandbox.ensure_calls[0]["number"] == 900
assert sandbox.ensure_calls[0]["existing_branch"] == "farm/abc12345/fix-flaky-parser"
row = db.get_issue("octo/widget#900")
@@ -1690,7 +1712,7 @@ async def test_handle_pr_conversation_repairs_missing_pr_mapping_from_branch(
settings: Settings, tmp_path: Path, stub_run_task, monkeypatch
) -> None:
from robomp import tasks
from robomp.github_client import IssueInfo, PullRequestInfo, RepoInfo
from robomp.github_client import CommentInfo, IssueInfo, PullRequestInfo, RepoInfo
sandbox = _RecordingSandbox(tmp_path)
db = get_database(settings.sqlite_path)
@@ -1709,6 +1731,16 @@ async def test_handle_pr_conversation_repairs_missing_pr_mapping_from_branch(
labels=(),
is_pull_request=False,
)
pr_issue = IssueInfo(
repo="octo/widget",
number=900,
title="Fix flaky parser",
body="PR body",
state="open",
author=settings.bot_login,
labels=(),
is_pull_request=True,
)
pr_info = PullRequestInfo(
repo="octo/widget",
number=900,
@@ -1731,12 +1763,33 @@ async def test_handle_pr_conversation_repairs_missing_pr_mapping_from_branch(
async def _get_issue(self, repo_full: str, number: int):
assert repo_full == "octo/widget"
assert number == 42
return issue
if number == 42:
return issue
if number == 900:
return pr_issue
raise AssertionError(number)
async def _list_comments(self, repo_full: str, number: int):
assert repo_full == "octo/widget"
assert number == 900
return [CommentInfo(id=78, author="can1357", body="prior PR context", created_at="2026-05-14T00:00:00Z")]
async def _list_review_comments(self, repo_full: str, number: int):
assert repo_full == "octo/widget"
assert number == 900
return []
async def _list_pr_reviews(self, repo_full: str, number: int):
assert repo_full == "octo/widget"
assert number == 900
return []
monkeypatch.setattr(GitHubClient, "get_pull_request", _get_pull_request)
monkeypatch.setattr(GitHubClient, "get_repo", _get_repo)
monkeypatch.setattr(GitHubClient, "get_issue", _get_issue)
monkeypatch.setattr(GitHubClient, "list_comments", _list_comments)
monkeypatch.setattr(GitHubClient, "list_review_comments", _list_review_comments)
monkeypatch.setattr(GitHubClient, "list_pr_reviews", _list_pr_reviews)
payload = {
"action": "created",
@@ -1758,6 +1811,10 @@ async def test_handle_pr_conversation_repairs_missing_pr_mapping_from_branch(
call = stub_run_task[0]
assert call["inputs"].issue.number == 42
assert call["pr_number"] == 900
assert [(m.kind, m.author, m.body) for m in call["thread"]] == [
("pr_body", settings.bot_login, "PR body"),
("comment", "can1357", "prior PR context"),
]
assert sandbox.ensure_calls[0]["number"] == 42
assert sandbox.ensure_calls[0]["existing_branch"] == branch
row = db.get_issue("octo/widget#42")