"""Tools for Gitea issue operations.""" import json from typing import Any from gitea.client import GiteaClient from gitea.models import IssueModel, CommentModel, LabelModel class IssueTools: """Tools for Gitea issue operations.""" def __init__(self, client: GiteaClient) -> None: self._client = client def get_issue(self, owner: str, repo: str, issue_number: int) -> str: try: issue: IssueModel = self._client.get_issue(owner, repo, issue_number) return issue.model_dump_json(indent=2) except Exception as e: return f"Error getting issue: {str(e)}" def close_issue(self, owner: str, repo: str, issue_number: int) -> str: try: self._client.close_issue(owner, repo, issue_number) return f"Issue #{issue_number} closed successfully." except Exception as e: return f"Error closing issue: {str(e)}" def get_issue_comments( self, owner: str, repo: str, issue_number: int, limit: int = 20, offset: int = 0, ) -> str: """Get comments on an issue with optional paging. Args: limit: Maximum number of comments to return (default 20). offset: Zero-based comment index to start from (default 0). """ try: comments: list[CommentModel] = self._client.get_issue_comments( owner, repo, issue_number ) total: int = len(comments) page: list[CommentModel] = comments[offset : offset + limit] result: str = json.dumps([c.model_dump() for c in page], indent=2) if total > offset + limit: next_offset: int = offset + limit result += ( f"\n\n[{total} comments total — showing {offset}–{offset + len(page)}. " f"Re-call with offset={next_offset} to see more.]" ) return result except Exception as e: return f"Error getting issue comments: {str(e)}" def list_assigned_issues(self) -> list[dict[str, Any]]: try: repos = self._client.list_all_user_repos() all_issues: list[dict[str, Any]] = [] for repo in repos: owner = repo.owner repo_name = repo.name issues = self._client.list_assigned_issues(owner, repo_name) if issues: all_issues.extend([issue.model_dump() if hasattr(issue, 'model_dump') else issue for issue in issues]) return all_issues except Exception as e: print(f"DEBUG: list_assigned_issues error: {e}") return [] def list_issues(self, owner: str, repo: str, state: str = "open") -> str: try: issues = self._client.list_repo_issues(owner, repo, state) if not issues: return f"No issues in {owner}/{repo}." summary = [f"#{issue.number}: {issue.title}" for issue in issues] return "\n".join(summary) except Exception as e: return f"Error listing issues: {str(e)}" def create_issue(self, owner: str, repo: str, title: str, body: str, labels: list[str] | None = None, assignees: list[str] | None = None) -> str: try: issue = self._client.create_issue(owner, repo, title, body, labels, assignees) return f"Issue #{issue.number} created successfully in {owner}/{repo}." except Exception as e: return f"Error creating issue: {str(e)}" def add_label_to_issue(self, owner: str, repo: str, issue_number: int, label: str) -> str: try: self._client.add_label(owner, repo, issue_number, label) return f"Label '{label}' added to issue #{issue_number}." except Exception as e: return f"Error adding label to issue #{issue_number}: {e}" def add_comment_to_issue(self, owner: str, repo: str, issue_number: int, body: str) -> str: try: self._client.add_comment(owner, repo, issue_number, body) return f"Comment added to issue #{issue_number}." except Exception as e: return f"Error adding comment to issue #{issue_number}: {e}" def add_comment(self, owner: str, repo: str, issue_number: int, body: str) -> str: try: comment = self._client.add_comment(owner, repo, issue_number, body) return f"Comment added to #{issue_number}." except Exception as e: return f"Error adding comment: {str(e)}" def add_label(self, owner: str, repo: str, issue_number: int, label: str) -> str: try: self._client.add_label(owner, repo, issue_number, label) return f"Label '{label}' added to #{issue_number}." except Exception as e: return f"Error adding label: {str(e)}"