| 120 | |
| 121 | |
| 122 | def fetch_comments(pr: int) -> list[Comment]: |
| 123 | # Returns ALL review comments on the PR (both CodeRabbit and human), |
| 124 | # because _is_resolved needs to see human replies to detect that a |
| 125 | # CodeRabbit thread has been addressed. Top-level filtering to |
| 126 | # CodeRabbit-authored threads happens in plan(). |
| 127 | repo = _repo_slug() |
| 128 | out = _run_gh(["api", f"repos/{repo}/pulls/{pr}/comments", "--paginate"]) |
| 129 | raw = cast(list[dict[str, Any]], json.loads(out)) |
| 130 | comments: list[Comment] = [] |
| 131 | for c in raw: |
| 132 | user = cast(dict[str, Any], c.get("user") or {}) |
| 133 | author = cast(str, user.get("login", "")) |
| 134 | comments.append( |
| 135 | Comment( |
| 136 | id=int(c["id"]), |
| 137 | author=author, |
| 138 | body=cast(str, c.get("body", "")), |
| 139 | path=cast(str, c.get("path", "")), |
| 140 | line=cast( |
| 141 | Optional[int], |
| 142 | c.get("line") or c.get("original_line"), |
| 143 | ), |
| 144 | in_reply_to=cast(Optional[int], c.get("in_reply_to_id")), |
| 145 | ) |
| 146 | ) |
| 147 | return comments |
| 148 | |
| 149 | |
| 150 | def _is_resolved(comment: Comment, all_comments: list[Comment]) -> bool: |