Files
coding-agent-gitea/gitea/tools/issue_tools.py
T
Michael bf13a979c2 feat: add output truncation and offset paging to all large-output tools
- coding_tools: list_files (max_entries=200, sorted), run_command
  (max_chars=8000, output_offset), grep_search (max_lines=100, offset);
  added _truncate_output helper for run_command paging
- pr_tools: get_pull_request_diff / get_pull_request_patch now truncate
  at 15k chars with hunk-boundary awareness and char_offset paging;
  get_pull_request_comments gains limit/offset paging
- issue_tools: get_issue_comments gains limit/offset paging
- file_tools: get_file_content / get_file_content_with_ref now paginate
  by line (offset=1, limit=250), matching existing read_file convention;
  added _paginate_lines helper
- research_tools: fetch_url gains char_offset parameter; _smart_truncate
  now slices from an offset and embeds next char_offset in the footer
- gitea_tools facade: all new params threaded through
2026-06-28 19:57:14 +02:00

119 lines
4.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""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)}"