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:11:03 +02:00
parent 7a867a5e85
commit 4cd86383c0
8 changed files with 117 additions and 11 deletions
+8 -3
View File
@@ -157,11 +157,16 @@ def route(
return issue_key(repo, pr_number) # type: ignore[arg-type]
def _reviewer_bot_login(user: Mapping[str, Any] | None) -> str | None:
"""Return the lowercased login if this user is a configured reviewer bot."""
"""Return the normalized login if this user is a configured reviewer bot."""
if not isinstance(user, Mapping):
return None
login = str(user.get("login") or "").lower()
return login if login and login in reviewer_bots else None
raw_login = str(user.get("login") or "").lower()
if not raw_login:
return None
login = raw_login.removesuffix("[bot]")
if login in reviewer_bots:
return login
return raw_login if raw_login in reviewer_bots else None
def _directive_kwargs(comment: Mapping[str, Any] | None, login: str | None, assoc: str | None) -> dict[str, Any]:
"""Decide whether this comment is a directive (reviewer-bot OR maintainer-mention)."""
+2
View File
@@ -263,6 +263,7 @@ def followup_comment(
workspace: Workspace,
pr_status: str,
pr_number: int | None = None,
thread: tuple = (),
) -> str:
return render(
_load("followup_comment.md"),
@@ -271,6 +272,7 @@ def followup_comment(
"issue": issue,
"workspace": workspace,
"comment": comment,
"thread": _render_thread(thread),
"state": {"pr_status": pr_status},
"inbound": _inbound_scope(issue, pr_number),
"origin": _origin_scope(issue),
@@ -2,6 +2,12 @@
Thread context: {{origin.description}}. PR state: `{{state.pr_status}}`.
## Prior conversation
{{thread}}
---
## New comment by @{{comment.author}} ({{comment.created_at}})
{{comment.body}}
+13 -2
View File
@@ -666,8 +666,19 @@ async def handle_pr_conversation(
slot_uid=slot_uid,
natives_cache=sandbox.natives_cache,
)
directive = await _attach_thread(github, directive, repo_full, pr_number, is_pr=True)
await run_task(task_kind="handle_comment", inputs=inputs, comment=comment, pr_number=pr_number, directive=directive)
thread: tuple[ThreadMessage, ...] = ()
if directive is None:
thread = await _fetch_thread(github, repo_full, pr_number, is_pr=True)
else:
directive = await _attach_thread(github, directive, repo_full, pr_number, is_pr=True)
await run_task(
task_kind="handle_comment",
inputs=inputs,
comment=comment,
pr_number=pr_number,
directive=directive,
thread=thread,
)
async def cleanup_workspace(
+4
View File
@@ -369,6 +369,7 @@ def _build_prompt(
pr_number: int | None,
review_payload: dict[str, Any] | None,
directive: DirectiveInfo | None = None,
thread: tuple[ThreadMessage, ...] = (),
resuming: bool = False,
) -> str:
if task_kind == "triage_issue":
@@ -412,6 +413,7 @@ def _build_prompt(
comment=comment,
pr_status=pr_status,
pr_number=pr_number,
thread=thread,
)
if task_kind == "handle_review":
assert review_payload is not None
@@ -652,6 +654,7 @@ async def run_task(
pr_number: int | None = None,
review_payload: dict[str, Any] | None = None,
directive: DirectiveInfo | None = None,
thread: tuple[ThreadMessage, ...] = (),
) -> str | None:
"""Async wrapper that runs the synchronous RPC driver on a worker thread."""
loop = asyncio.get_running_loop()
@@ -679,6 +682,7 @@ async def run_task(
pr_number=pr_number,
review_payload=review_payload,
directive=directive,
thread=thread,
resuming=resuming,
)
try: