Initial commit: MCP Hub Community Edition v3.0.0

Community edition generated from private repo via sync pipeline.
Includes 9 plugins (WordPress, WooCommerce, WP Advanced, Gitea, n8n,
Supabase, OpenPanel, Appwrite, Directus) with ~587 tools.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
airano
2026-02-17 08:34:44 +03:30
commit cf62e65c55
237 changed files with 87596 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
"""
Gitea Plugin Handlers
All tool handlers for Gitea operations.
"""
from . import issues, pull_requests, repositories, users, webhooks
__all__ = [
"repositories",
"issues",
"pull_requests",
"users",
"webhooks",
]

View File

@@ -0,0 +1,516 @@
"""Issue Handler - manages Gitea issues, labels, milestones, and comments"""
import json
from typing import Any
from plugins.gitea.client import GiteaClient
def get_tool_specifications() -> list[dict[str, Any]]:
"""Return tool specifications for ToolGenerator"""
return [
# === ISSUES ===
{
"name": "list_issues",
"method_name": "list_issues",
"description": "List issues in a Gitea repository with filters. Returns paginated list of issues.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"state": {
"type": "string",
"description": "Filter by state",
"enum": ["open", "closed", "all"],
"default": "open",
},
"labels": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Comma-separated label IDs",
},
"q": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Search query",
},
"page": {
"type": "integer",
"description": "Page number",
"default": 1,
"minimum": 1,
},
"limit": {
"type": "integer",
"description": "Items per page (1-100)",
"default": 30,
"minimum": 1,
"maximum": 100,
},
},
"required": ["owner", "repo"],
},
"scope": "read",
},
{
"name": "get_issue",
"method_name": "get_issue",
"description": "Get details of a specific issue by number.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"issue_number": {
"type": "integer",
"description": "Issue number",
"minimum": 1,
},
},
"required": ["owner", "repo", "issue_number"],
},
"scope": "read",
},
{
"name": "create_issue",
"method_name": "create_issue",
"description": "Create a new issue in a Gitea repository with optional labels, assignees, and milestone.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"title": {
"type": "string",
"description": "Issue title",
"minLength": 1,
"maxLength": 255,
},
"body": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Issue description (supports Markdown)",
},
"assignee": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Assignee username",
},
"assignees": {
"anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
"description": "List of assignee usernames",
},
"labels": {
"anyOf": [
{"type": "array", "items": {"type": "integer"}},
{"type": "null"},
],
"description": "List of label IDs",
},
"milestone": {
"anyOf": [{"type": "integer"}, {"type": "null"}],
"description": "Milestone ID",
},
"closed": {
"type": "boolean",
"description": "Create as closed",
"default": False,
},
},
"required": ["owner", "repo", "title"],
},
"scope": "write",
},
{
"name": "update_issue",
"method_name": "update_issue",
"description": "Update an existing issue. Can modify title, body, state, assignees, labels, and milestone.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"issue_number": {
"type": "integer",
"description": "Issue number",
"minimum": 1,
},
"title": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Issue title",
},
"body": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Issue description",
},
"state": {
"anyOf": [{"type": "string", "enum": ["open", "closed"]}, {"type": "null"}],
"description": "Issue state",
},
"assignee": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Assignee username",
},
"assignees": {
"anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
"description": "List of assignee usernames",
},
"labels": {
"anyOf": [
{"type": "array", "items": {"type": "integer"}},
{"type": "null"},
],
"description": "List of label IDs",
},
"milestone": {
"anyOf": [{"type": "integer"}, {"type": "null"}],
"description": "Milestone ID",
},
},
"required": ["owner", "repo", "issue_number"],
},
"scope": "write",
},
{
"name": "close_issue",
"method_name": "close_issue",
"description": "Close an issue.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"issue_number": {
"type": "integer",
"description": "Issue number",
"minimum": 1,
},
},
"required": ["owner", "repo", "issue_number"],
},
"scope": "write",
},
{
"name": "reopen_issue",
"method_name": "reopen_issue",
"description": "Reopen a closed issue.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"issue_number": {
"type": "integer",
"description": "Issue number",
"minimum": 1,
},
},
"required": ["owner", "repo", "issue_number"],
},
"scope": "write",
},
# === COMMENTS ===
{
"name": "list_issue_comments",
"method_name": "list_issue_comments",
"description": "List all comments on an issue.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"issue_number": {
"type": "integer",
"description": "Issue number",
"minimum": 1,
},
},
"required": ["owner", "repo", "issue_number"],
},
"scope": "read",
},
{
"name": "create_issue_comment",
"method_name": "create_issue_comment",
"description": "Add a comment to an issue.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"issue_number": {
"type": "integer",
"description": "Issue number",
"minimum": 1,
},
"body": {
"type": "string",
"description": "Comment body (supports Markdown)",
"minLength": 1,
},
},
"required": ["owner", "repo", "issue_number", "body"],
},
"scope": "write",
},
# === LABELS ===
{
"name": "list_labels",
"method_name": "list_labels",
"description": "List all labels in a repository.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
},
"required": ["owner", "repo"],
},
"scope": "read",
},
{
"name": "create_label",
"method_name": "create_label",
"description": "Create a new label in a repository.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"name": {
"type": "string",
"description": "Label name",
"minLength": 1,
"maxLength": 50,
},
"color": {
"type": "string",
"description": "Label color (hex without #, e.g., 'ff0000')",
"pattern": "^[0-9A-Fa-f]{6}$",
},
"description": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Label description",
"maxLength": 200,
},
},
"required": ["owner", "repo", "name", "color"],
},
"scope": "write",
},
# === MILESTONES ===
{
"name": "list_milestones",
"method_name": "list_milestones",
"description": "List all milestones in a repository.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"state": {
"anyOf": [
{"type": "string", "enum": ["open", "closed", "all"]},
{"type": "null"},
],
"description": "Filter by state",
"default": "open",
},
},
"required": ["owner", "repo"],
},
"scope": "read",
},
{
"name": "create_milestone",
"method_name": "create_milestone",
"description": "Create a new milestone in a repository.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"title": {
"type": "string",
"description": "Milestone title",
"minLength": 1,
"maxLength": 255,
},
"description": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Milestone description",
},
"due_on": {
"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}],
"description": "Due date (ISO 8601 format)",
},
"state": {
"type": "string",
"description": "State",
"enum": ["open", "closed"],
"default": "open",
},
},
"required": ["owner", "repo", "title"],
},
"scope": "write",
},
]
async def list_issues(
client: GiteaClient,
owner: str,
repo: str,
state: str = "open",
labels: str | None = None,
q: str | None = None,
page: int = 1,
limit: int = 30,
) -> str:
"""List repository issues"""
params = {"state": state, "labels": labels, "q": q, "page": page, "limit": limit}
issues = await client.list_issues(owner, repo, params)
result = {"success": True, "count": len(issues), "issues": issues}
return json.dumps(result, indent=2)
async def get_issue(client: GiteaClient, owner: str, repo: str, issue_number: int) -> str:
"""Get issue details"""
issue = await client.get_issue(owner, repo, issue_number)
result = {"success": True, "issue": issue}
return json.dumps(result, indent=2)
async def create_issue(
client: GiteaClient,
owner: str,
repo: str,
title: str,
body: str | None = None,
assignee: str | None = None,
assignees: list[str] | None = None,
labels: list[int] | None = None,
milestone: int | None = None,
closed: bool = False,
) -> str:
"""Create a new issue"""
data = {
"title": title,
"body": body,
"assignee": assignee,
"assignees": assignees,
"labels": labels,
"milestone": milestone,
"closed": closed,
}
issue = await client.create_issue(owner, repo, data)
result = {
"success": True,
"message": f"Issue #{issue['number']} created successfully",
"issue": issue,
}
return json.dumps(result, indent=2)
async def update_issue(
client: GiteaClient, owner: str, repo: str, issue_number: int, **kwargs
) -> str:
"""Update an issue"""
# Build update data from kwargs
data = {
k: v
for k, v in kwargs.items()
if v is not None and k not in ["owner", "repo", "issue_number"]
}
issue = await client.update_issue(owner, repo, issue_number, data)
result = {
"success": True,
"message": f"Issue #{issue_number} updated successfully",
"issue": issue,
}
return json.dumps(result, indent=2)
async def close_issue(client: GiteaClient, owner: str, repo: str, issue_number: int) -> str:
"""Close an issue"""
data = {"state": "closed"}
issue = await client.update_issue(owner, repo, issue_number, data)
result = {
"success": True,
"message": f"Issue #{issue_number} closed successfully",
"issue": issue,
}
return json.dumps(result, indent=2)
async def reopen_issue(client: GiteaClient, owner: str, repo: str, issue_number: int) -> str:
"""Reopen an issue"""
data = {"state": "open"}
issue = await client.update_issue(owner, repo, issue_number, data)
result = {
"success": True,
"message": f"Issue #{issue_number} reopened successfully",
"issue": issue,
}
return json.dumps(result, indent=2)
# Comment operations
async def list_issue_comments(client: GiteaClient, owner: str, repo: str, issue_number: int) -> str:
"""List issue comments"""
comments = await client.list_issue_comments(owner, repo, issue_number)
result = {"success": True, "count": len(comments), "comments": comments}
return json.dumps(result, indent=2)
async def create_issue_comment(
client: GiteaClient, owner: str, repo: str, issue_number: int, body: str
) -> str:
"""Create issue comment"""
data = {"body": body}
comment = await client.create_issue_comment(owner, repo, issue_number, data)
result = {
"success": True,
"message": f"Comment added to issue #{issue_number}",
"comment": comment,
}
return json.dumps(result, indent=2)
# Label operations
async def list_labels(client: GiteaClient, owner: str, repo: str) -> str:
"""List repository labels"""
labels = await client.list_labels(owner, repo)
result = {"success": True, "count": len(labels), "labels": labels}
return json.dumps(result, indent=2)
async def create_label(
client: GiteaClient,
owner: str,
repo: str,
name: str,
color: str,
description: str | None = None,
) -> str:
"""Create a label"""
data = {"name": name, "color": color, "description": description}
label = await client.create_label(owner, repo, data)
result = {"success": True, "message": f"Label '{name}' created successfully", "label": label}
return json.dumps(result, indent=2)
# Milestone operations
async def list_milestones(
client: GiteaClient, owner: str, repo: str, state: str | None = None
) -> str:
"""List repository milestones"""
milestones = await client.list_milestones(owner, repo, state=state)
result = {"success": True, "count": len(milestones), "milestones": milestones}
return json.dumps(result, indent=2)
async def create_milestone(
client: GiteaClient,
owner: str,
repo: str,
title: str,
description: str | None = None,
due_on: str | None = None,
state: str = "open",
) -> str:
"""Create a milestone"""
data = {"title": title, "description": description, "due_on": due_on, "state": state}
milestone = await client.create_milestone(owner, repo, data)
result = {
"success": True,
"message": f"Milestone '{title}' created successfully",
"milestone": milestone,
}
return json.dumps(result, indent=2)

View File

@@ -0,0 +1,629 @@
"""Pull Request Handler - manages Gitea pull requests, reviews, and merges"""
import json
from typing import Any
from plugins.gitea.client import GiteaClient
def get_tool_specifications() -> list[dict[str, Any]]:
"""Return tool specifications for ToolGenerator"""
return [
# === PULL REQUESTS ===
{
"name": "list_pull_requests",
"method_name": "list_pull_requests",
"description": "List pull requests in a Gitea repository with filters.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"state": {
"type": "string",
"description": "Filter by state",
"enum": ["open", "closed", "all"],
"default": "open",
},
"sort": {
"type": "string",
"description": "Sort by",
"enum": ["created", "updated", "comments", "recentupdate"],
"default": "created",
},
"labels": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Comma-separated label IDs",
},
"milestone": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Milestone name",
},
"page": {
"type": "integer",
"description": "Page number",
"default": 1,
"minimum": 1,
},
"limit": {
"type": "integer",
"description": "Items per page (1-100)",
"default": 30,
"minimum": 1,
"maximum": 100,
},
},
"required": ["owner", "repo"],
},
"scope": "read",
},
{
"name": "get_pull_request",
"method_name": "get_pull_request",
"description": "Get details of a specific pull request by number.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"pr_number": {
"type": "integer",
"description": "Pull request number",
"minimum": 1,
},
},
"required": ["owner", "repo", "pr_number"],
},
"scope": "read",
},
{
"name": "create_pull_request",
"method_name": "create_pull_request",
"description": "Create a new pull request in a Gitea repository.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"title": {
"type": "string",
"description": "Pull request title",
"minLength": 1,
"maxLength": 255,
},
"head": {
"type": "string",
"description": "Source branch (head branch)",
"minLength": 1,
},
"base": {
"type": "string",
"description": "Target branch (base branch)",
"minLength": 1,
},
"body": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Pull request description (supports Markdown)",
},
"assignee": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Assignee username",
},
"assignees": {
"anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
"description": "List of assignee usernames",
},
"labels": {
"anyOf": [
{"type": "array", "items": {"type": "integer"}},
{"type": "null"},
],
"description": "List of label IDs",
},
"milestone": {
"anyOf": [{"type": "integer"}, {"type": "null"}],
"description": "Milestone ID",
},
},
"required": ["owner", "repo", "title", "head", "base"],
},
"scope": "write",
},
{
"name": "update_pull_request",
"method_name": "update_pull_request",
"description": "Update an existing pull request. Can modify title, body, state, assignees, labels, and milestone.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"pr_number": {
"type": "integer",
"description": "Pull request number",
"minimum": 1,
},
"title": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Pull request title",
},
"body": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Pull request description",
},
"state": {
"anyOf": [{"type": "string", "enum": ["open", "closed"]}, {"type": "null"}],
"description": "Pull request state",
},
"assignee": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Assignee username",
},
"assignees": {
"anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}],
"description": "List of assignee usernames",
},
"labels": {
"anyOf": [
{"type": "array", "items": {"type": "integer"}},
{"type": "null"},
],
"description": "List of label IDs",
},
"milestone": {
"anyOf": [{"type": "integer"}, {"type": "null"}],
"description": "Milestone ID",
},
},
"required": ["owner", "repo", "pr_number"],
},
"scope": "write",
},
{
"name": "merge_pull_request",
"method_name": "merge_pull_request",
"description": "Merge a pull request using specified merge method.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"pr_number": {
"type": "integer",
"description": "Pull request number",
"minimum": 1,
},
"method": {
"type": "string",
"description": "Merge method",
"enum": ["merge", "rebase", "rebase-merge", "squash"],
"default": "merge",
},
"title": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Merge commit title",
},
"message": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Merge commit message",
},
"delete_branch_after_merge": {
"type": "boolean",
"description": "Delete source branch after merge",
"default": False,
},
},
"required": ["owner", "repo", "pr_number"],
},
"scope": "write",
},
{
"name": "close_pull_request",
"method_name": "close_pull_request",
"description": "Close a pull request without merging.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"pr_number": {
"type": "integer",
"description": "Pull request number",
"minimum": 1,
},
},
"required": ["owner", "repo", "pr_number"],
},
"scope": "write",
},
{
"name": "reopen_pull_request",
"method_name": "reopen_pull_request",
"description": "Reopen a closed pull request.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"pr_number": {
"type": "integer",
"description": "Pull request number",
"minimum": 1,
},
},
"required": ["owner", "repo", "pr_number"],
},
"scope": "write",
},
# === PR DETAILS ===
{
"name": "list_pr_commits",
"method_name": "list_pr_commits",
"description": "List all commits in a pull request.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"pr_number": {
"type": "integer",
"description": "Pull request number",
"minimum": 1,
},
},
"required": ["owner", "repo", "pr_number"],
},
"scope": "read",
},
{
"name": "list_pr_files",
"method_name": "list_pr_files",
"description": "List all changed files in a pull request with additions/deletions count.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"pr_number": {
"type": "integer",
"description": "Pull request number",
"minimum": 1,
},
},
"required": ["owner", "repo", "pr_number"],
},
"scope": "read",
},
{
"name": "get_pr_diff",
"method_name": "get_pr_diff",
"description": "Get the unified diff of a pull request.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"pr_number": {
"type": "integer",
"description": "Pull request number",
"minimum": 1,
},
},
"required": ["owner", "repo", "pr_number"],
},
"scope": "read",
},
{
"name": "list_pr_comments",
"method_name": "list_pr_comments",
"description": "List all comments on a pull request.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"pr_number": {
"type": "integer",
"description": "Pull request number",
"minimum": 1,
},
},
"required": ["owner", "repo", "pr_number"],
},
"scope": "read",
},
{
"name": "create_pr_comment",
"method_name": "create_pr_comment",
"description": "Add a comment to a pull request.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"pr_number": {
"type": "integer",
"description": "Pull request number",
"minimum": 1,
},
"body": {
"type": "string",
"description": "Comment body (supports Markdown)",
"minLength": 1,
},
},
"required": ["owner", "repo", "pr_number", "body"],
},
"scope": "write",
},
# === PR REVIEWS ===
{
"name": "list_pr_reviews",
"method_name": "list_pr_reviews",
"description": "List all reviews on a pull request.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"pr_number": {
"type": "integer",
"description": "Pull request number",
"minimum": 1,
},
},
"required": ["owner", "repo", "pr_number"],
},
"scope": "read",
},
{
"name": "create_pr_review",
"method_name": "create_pr_review",
"description": "Create a review for a pull request (approve, request changes, or comment).",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"pr_number": {
"type": "integer",
"description": "Pull request number",
"minimum": 1,
},
"event": {
"type": "string",
"description": "Review event type",
"enum": ["APPROVED", "REQUEST_CHANGES", "COMMENT"],
},
"body": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Review comment (optional for APPROVED)",
},
},
"required": ["owner", "repo", "pr_number", "event"],
},
"scope": "write",
},
{
"name": "request_pr_reviewers",
"method_name": "request_pr_reviewers",
"description": "Request reviewers for a pull request.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"pr_number": {
"type": "integer",
"description": "Pull request number",
"minimum": 1,
},
"reviewers": {
"type": "array",
"items": {"type": "string"},
"description": "List of reviewer usernames",
"minItems": 1,
},
},
"required": ["owner", "repo", "pr_number", "reviewers"],
},
"scope": "write",
},
]
async def list_pull_requests(
client: GiteaClient,
owner: str,
repo: str,
state: str = "open",
sort: str = "created",
labels: str | None = None,
milestone: str | None = None,
page: int = 1,
limit: int = 30,
) -> str:
"""List repository pull requests"""
params = {
"state": state,
"sort": sort,
"labels": labels,
"milestone": milestone,
"page": page,
"limit": limit,
}
prs = await client.list_pull_requests(owner, repo, params)
result = {"success": True, "count": len(prs), "pull_requests": prs}
return json.dumps(result, indent=2)
async def get_pull_request(client: GiteaClient, owner: str, repo: str, pr_number: int) -> str:
"""Get pull request details"""
pr = await client.get_pull_request(owner, repo, pr_number)
result = {"success": True, "pull_request": pr}
return json.dumps(result, indent=2)
async def create_pull_request(
client: GiteaClient,
owner: str,
repo: str,
title: str,
head: str,
base: str,
body: str | None = None,
assignee: str | None = None,
assignees: list[str] | None = None,
labels: list[int] | None = None,
milestone: int | None = None,
) -> str:
"""Create a new pull request"""
data = {
"title": title,
"head": head,
"base": base,
"body": body,
"assignee": assignee,
"assignees": assignees,
"labels": labels,
"milestone": milestone,
}
pr = await client.create_pull_request(owner, repo, data)
result = {
"success": True,
"message": f"Pull request #{pr['number']} created successfully",
"pull_request": pr,
}
return json.dumps(result, indent=2)
async def update_pull_request(
client: GiteaClient, owner: str, repo: str, pr_number: int, **kwargs
) -> str:
"""Update a pull request"""
# Build update data from kwargs
data = {
k: v for k, v in kwargs.items() if v is not None and k not in ["owner", "repo", "pr_number"]
}
pr = await client.update_pull_request(owner, repo, pr_number, data)
result = {
"success": True,
"message": f"Pull request #{pr_number} updated successfully",
"pull_request": pr,
}
return json.dumps(result, indent=2)
async def merge_pull_request(
client: GiteaClient,
owner: str,
repo: str,
pr_number: int,
method: str = "merge",
title: str | None = None,
message: str | None = None,
delete_branch_after_merge: bool = False,
) -> str:
"""Merge a pull request"""
data = {
"Do": method,
"MergeTitleField": title,
"MergeMessageField": message,
"delete_branch_after_merge": delete_branch_after_merge,
}
merge_result = await client.merge_pull_request(owner, repo, pr_number, data)
result = {
"success": True,
"message": f"Pull request #{pr_number} merged successfully using {method}",
"result": merge_result,
}
return json.dumps(result, indent=2)
async def close_pull_request(client: GiteaClient, owner: str, repo: str, pr_number: int) -> str:
"""Close a pull request"""
data = {"state": "closed"}
pr = await client.update_pull_request(owner, repo, pr_number, data)
result = {
"success": True,
"message": f"Pull request #{pr_number} closed successfully",
"pull_request": pr,
}
return json.dumps(result, indent=2)
async def reopen_pull_request(client: GiteaClient, owner: str, repo: str, pr_number: int) -> str:
"""Reopen a pull request"""
data = {"state": "open"}
pr = await client.update_pull_request(owner, repo, pr_number, data)
result = {
"success": True,
"message": f"Pull request #{pr_number} reopened successfully",
"pull_request": pr,
}
return json.dumps(result, indent=2)
# PR Details
async def list_pr_commits(client: GiteaClient, owner: str, repo: str, pr_number: int) -> str:
"""List pull request commits"""
commits = await client.list_pr_commits(owner, repo, pr_number)
result = {"success": True, "count": len(commits), "commits": commits}
return json.dumps(result, indent=2)
async def list_pr_files(client: GiteaClient, owner: str, repo: str, pr_number: int) -> str:
"""List pull request files"""
files = await client.list_pr_files(owner, repo, pr_number)
result = {"success": True, "count": len(files), "files": files}
return json.dumps(result, indent=2)
async def get_pr_diff(client: GiteaClient, owner: str, repo: str, pr_number: int) -> str:
"""Get pull request diff"""
diff = await client.get_pr_diff(owner, repo, pr_number)
result = {"success": True, "diff": diff}
return json.dumps(result, indent=2)
async def list_pr_comments(client: GiteaClient, owner: str, repo: str, pr_number: int) -> str:
"""List pull request comments"""
# PR comments are same as issue comments in Gitea API
comments = await client.list_issue_comments(owner, repo, pr_number)
result = {"success": True, "count": len(comments), "comments": comments}
return json.dumps(result, indent=2)
async def create_pr_comment(
client: GiteaClient, owner: str, repo: str, pr_number: int, body: str
) -> str:
"""Create pull request comment"""
data = {"body": body}
comment = await client.create_issue_comment(owner, repo, pr_number, data)
result = {
"success": True,
"message": f"Comment added to pull request #{pr_number}",
"comment": comment,
}
return json.dumps(result, indent=2)
# PR Reviews
async def list_pr_reviews(client: GiteaClient, owner: str, repo: str, pr_number: int) -> str:
"""List pull request reviews"""
reviews = await client.list_pr_reviews(owner, repo, pr_number)
result = {"success": True, "count": len(reviews), "reviews": reviews}
return json.dumps(result, indent=2)
async def create_pr_review(
client: GiteaClient, owner: str, repo: str, pr_number: int, event: str, body: str | None = None
) -> str:
"""Create pull request review"""
data = {"event": event, "body": body}
review = await client.create_pr_review(owner, repo, pr_number, data)
result = {
"success": True,
"message": f"Review {event} added to pull request #{pr_number}",
"review": review,
}
return json.dumps(result, indent=2)
async def request_pr_reviewers(
client: GiteaClient, owner: str, repo: str, pr_number: int, reviewers: list[str]
) -> str:
"""Request pull request reviewers"""
data = {"reviewers": reviewers}
reviewers_result = await client.request_pr_reviewers(owner, repo, pr_number, data)
result = {
"success": True,
"message": f"Reviewers requested for pull request #{pr_number}",
"result": reviewers_result,
}
return json.dumps(result, indent=2)

View File

@@ -0,0 +1,709 @@
"""Repository Handler - manages Gitea repositories, branches, tags, and files"""
import json
from typing import Any
from plugins.gitea.client import GiteaClient
def get_tool_specifications() -> list[dict[str, Any]]:
"""Return tool specifications for ToolGenerator"""
return [
# === REPOSITORIES ===
{
"name": "list_repositories",
"method_name": "list_repositories",
"description": "List Gitea repositories for a user/organization or current user. Returns repository list with metadata.",
"schema": {
"type": "object",
"properties": {
"owner": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Repository owner username/org (null for current user repos)",
},
"type": {
"type": "string",
"description": "Filter by repository type",
"enum": ["all", "owner", "collaborative", "member"],
"default": "all",
},
"page": {
"type": "integer",
"description": "Page number",
"default": 1,
"minimum": 1,
},
"limit": {
"type": "integer",
"description": "Items per page (1-100)",
"default": 30,
"minimum": 1,
"maximum": 100,
},
},
},
"scope": "read",
},
{
"name": "get_repository",
"method_name": "get_repository",
"description": "Get details of a specific Gitea repository. Returns complete repository information.",
"schema": {
"type": "object",
"properties": {
"owner": {
"type": "string",
"description": "Repository owner username/org",
"minLength": 1,
},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
},
"required": ["owner", "repo"],
},
"scope": "read",
},
{
"name": "create_repository",
"method_name": "create_repository",
"description": "Create a new Gitea repository. Can create user or organization repository with optional auto-initialization.",
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Repository name",
"minLength": 1,
"maxLength": 100,
},
"description": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Repository description",
"maxLength": 500,
},
"private": {
"type": "boolean",
"description": "Make repository private",
"default": False,
},
"auto_init": {
"type": "boolean",
"description": "Initialize with README",
"default": False,
},
"gitignores": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Gitignore template name",
},
"license": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "License template name",
},
"readme": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Readme template",
},
"default_branch": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Default branch name",
},
"org": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Create under organization (null for user repo)",
},
},
"required": ["name"],
},
"scope": "write",
},
{
"name": "update_repository",
"method_name": "update_repository",
"description": "Update Gitea repository settings like name, description, visibility, and features.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"name": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "New repository name",
},
"description": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Repository description",
},
"website": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Repository website",
},
"private": {
"anyOf": [{"type": "boolean"}, {"type": "null"}],
"description": "Make repository private",
},
"archived": {
"anyOf": [{"type": "boolean"}, {"type": "null"}],
"description": "Archive repository",
},
"has_issues": {
"anyOf": [{"type": "boolean"}, {"type": "null"}],
"description": "Enable issues",
},
"has_wiki": {
"anyOf": [{"type": "boolean"}, {"type": "null"}],
"description": "Enable wiki",
},
"default_branch": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Default branch",
},
"allow_merge_commits": {
"anyOf": [{"type": "boolean"}, {"type": "null"}],
"description": "Allow merge commits",
},
"allow_rebase": {
"anyOf": [{"type": "boolean"}, {"type": "null"}],
"description": "Allow rebase",
},
"allow_squash_merge": {
"anyOf": [{"type": "boolean"}, {"type": "null"}],
"description": "Allow squash merge",
},
},
"required": ["owner", "repo"],
},
"scope": "write",
},
{
"name": "delete_repository",
"method_name": "delete_repository",
"description": "Delete a Gitea repository permanently. This action cannot be undone!",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
},
"required": ["owner", "repo"],
},
"scope": "admin",
},
# === BRANCHES ===
{
"name": "list_branches",
"method_name": "list_branches",
"description": "List all branches in a Gitea repository with commit information and protection status.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"page": {
"type": "integer",
"description": "Page number",
"default": 1,
"minimum": 1,
},
"limit": {
"type": "integer",
"description": "Items per page (1-100)",
"default": 30,
"minimum": 1,
"maximum": 100,
},
},
"required": ["owner", "repo"],
},
"scope": "read",
},
{
"name": "get_branch",
"method_name": "get_branch",
"description": "Get details of a specific branch including latest commit and protection settings.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"branch": {"type": "string", "description": "Branch name", "minLength": 1},
},
"required": ["owner", "repo", "branch"],
},
"scope": "read",
},
{
"name": "create_branch",
"method_name": "create_branch",
"description": "Create a new branch in a Gitea repository from existing branch or commit.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"new_branch_name": {
"type": "string",
"description": "New branch name",
"minLength": 1,
},
"old_branch_name": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Source branch (default: default branch)",
},
"old_ref_name": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Source commit SHA or ref",
},
},
"required": ["owner", "repo", "new_branch_name"],
},
"scope": "write",
},
{
"name": "delete_branch",
"method_name": "delete_branch",
"description": "Delete a branch from a Gitea repository. Cannot delete default branch.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"branch": {
"type": "string",
"description": "Branch name to delete",
"minLength": 1,
},
},
"required": ["owner", "repo", "branch"],
},
"scope": "write",
},
# === TAGS ===
{
"name": "list_tags",
"method_name": "list_tags",
"description": "List all tags in a Gitea repository with commit information.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"page": {
"type": "integer",
"description": "Page number",
"default": 1,
"minimum": 1,
},
"limit": {
"type": "integer",
"description": "Items per page (1-100)",
"default": 30,
"minimum": 1,
"maximum": 100,
},
},
"required": ["owner", "repo"],
},
"scope": "read",
},
{
"name": "create_tag",
"method_name": "create_tag",
"description": "Create a new tag in a Gitea repository at specific commit.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"tag_name": {"type": "string", "description": "Tag name", "minLength": 1},
"message": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Tag message (annotated tag)",
},
"target": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Target commit SHA (default: latest)",
},
},
"required": ["owner", "repo", "tag_name"],
},
"scope": "write",
},
{
"name": "delete_tag",
"method_name": "delete_tag",
"description": "Delete a tag from a Gitea repository.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"tag": {"type": "string", "description": "Tag name to delete", "minLength": 1},
},
"required": ["owner", "repo", "tag"],
},
"scope": "write",
},
# === FILES ===
{
"name": "get_file",
"method_name": "get_file",
"description": "Get file contents from a Gitea repository. Returns file content (Base64 encoded) and metadata.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"path": {
"type": "string",
"description": "File path in repository",
"minLength": 1,
},
"ref": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Branch/tag/commit (default: default branch)",
},
},
"required": ["owner", "repo", "path"],
},
"scope": "read",
},
{
"name": "create_file",
"method_name": "create_file",
"description": "Create a new file in a Gitea repository with commit message.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"path": {
"type": "string",
"description": "File path to create",
"minLength": 1,
},
"content": {
"type": "string",
"description": "File content (will be Base64 encoded automatically unless content_is_base64=true)",
},
"message": {"type": "string", "description": "Commit message", "minLength": 1},
"branch": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Target branch (default: default branch)",
},
"new_branch": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Create new branch for this commit",
},
"author_name": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Author name",
},
"author_email": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Author email",
},
"content_is_base64": {
"type": "boolean",
"description": "Set to true if content is already Base64 encoded (skip automatic encoding)",
"default": False,
},
},
"required": ["owner", "repo", "path", "content", "message"],
},
"scope": "write",
},
{
"name": "update_file",
"method_name": "update_file",
"description": "Update an existing file in a Gitea repository. Requires current file SHA for conflict detection.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"path": {
"type": "string",
"description": "File path to update",
"minLength": 1,
},
"content": {
"type": "string",
"description": "New file content (will be Base64 encoded automatically)",
},
"sha": {
"type": "string",
"description": "Current file SHA (for conflict detection)",
"minLength": 1,
},
"message": {"type": "string", "description": "Commit message", "minLength": 1},
"branch": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Target branch (default: default branch)",
},
"new_branch": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Create new branch for this commit",
},
"content_is_base64": {
"type": "boolean",
"description": "Set to true if content is already Base64 encoded (skip automatic encoding)",
"default": False,
},
},
"required": ["owner", "repo", "path", "content", "sha", "message"],
},
"scope": "write",
},
{
"name": "delete_file",
"method_name": "delete_file",
"description": "Delete a file from a Gitea repository. Requires current file SHA for conflict detection.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"path": {
"type": "string",
"description": "File path to delete",
"minLength": 1,
},
"sha": {
"type": "string",
"description": "Current file SHA (for conflict detection)",
"minLength": 1,
},
"message": {"type": "string", "description": "Commit message", "minLength": 1},
"branch": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Target branch (default: default branch)",
},
},
"required": ["owner", "repo", "path", "sha", "message"],
},
"scope": "write",
},
]
async def list_repositories(
client: GiteaClient, owner: str | None = None, type: str = "all", page: int = 1, limit: int = 30
) -> str:
"""List Gitea repositories"""
repos = await client.list_repositories(owner=owner, page=page, limit=limit)
result = {"success": True, "count": len(repos), "repositories": repos}
return json.dumps(result, indent=2)
async def get_repository(client: GiteaClient, owner: str, repo: str) -> str:
"""Get repository details"""
repository = await client.get_repository(owner, repo)
result = {"success": True, "repository": repository}
return json.dumps(result, indent=2)
async def create_repository(
client: GiteaClient,
name: str,
description: str | None = None,
private: bool = False,
auto_init: bool = False,
gitignores: str | None = None,
license: str | None = None,
readme: str | None = None,
default_branch: str | None = None,
org: str | None = None,
) -> str:
"""Create a new repository"""
data = {
"name": name,
"description": description,
"private": private,
"auto_init": auto_init,
"gitignores": gitignores,
"license": license,
"readme": readme,
"default_branch": default_branch,
}
repository = await client.create_repository(data, org=org)
result = {
"success": True,
"message": f"Repository '{name}' created successfully",
"repository": repository,
}
return json.dumps(result, indent=2)
async def update_repository(client: GiteaClient, owner: str, repo: str, **kwargs) -> str:
"""Update repository settings"""
# Build update data from kwargs
data = {k: v for k, v in kwargs.items() if v is not None and k not in ["owner", "repo"]}
repository = await client.update_repository(owner, repo, data)
result = {
"success": True,
"message": f"Repository '{owner}/{repo}' updated successfully",
"repository": repository,
}
return json.dumps(result, indent=2)
async def delete_repository(client: GiteaClient, owner: str, repo: str) -> str:
"""Delete a repository"""
await client.delete_repository(owner, repo)
result = {"success": True, "message": f"Repository '{owner}/{repo}' deleted successfully"}
return json.dumps(result, indent=2)
# Branch operations
async def list_branches(
client: GiteaClient, owner: str, repo: str, page: int = 1, limit: int = 30
) -> str:
"""List repository branches"""
branches = await client.list_branches(owner, repo, page=page, limit=limit)
result = {"success": True, "count": len(branches), "branches": branches}
return json.dumps(result, indent=2)
async def get_branch(client: GiteaClient, owner: str, repo: str, branch: str) -> str:
"""Get branch details"""
branch_info = await client.get_branch(owner, repo, branch)
result = {"success": True, "branch": branch_info}
return json.dumps(result, indent=2)
async def create_branch(
client: GiteaClient,
owner: str,
repo: str,
new_branch_name: str,
old_branch_name: str | None = None,
old_ref_name: str | None = None,
) -> str:
"""Create a new branch"""
data = {
"new_branch_name": new_branch_name,
"old_branch_name": old_branch_name,
"old_ref_name": old_ref_name,
}
branch = await client.create_branch(owner, repo, data)
result = {
"success": True,
"message": f"Branch '{new_branch_name}' created successfully",
"branch": branch,
}
return json.dumps(result, indent=2)
async def delete_branch(client: GiteaClient, owner: str, repo: str, branch: str) -> str:
"""Delete a branch"""
await client.delete_branch(owner, repo, branch)
result = {"success": True, "message": f"Branch '{branch}' deleted successfully"}
return json.dumps(result, indent=2)
# Tag operations
async def list_tags(
client: GiteaClient, owner: str, repo: str, page: int = 1, limit: int = 30
) -> str:
"""List repository tags"""
tags = await client.list_tags(owner, repo, page=page, limit=limit)
result = {"success": True, "count": len(tags), "tags": tags}
return json.dumps(result, indent=2)
async def create_tag(
client: GiteaClient,
owner: str,
repo: str,
tag_name: str,
message: str | None = None,
target: str | None = None,
) -> str:
"""Create a new tag"""
data = {"tag_name": tag_name, "message": message, "target": target}
tag = await client.create_tag(owner, repo, data)
result = {"success": True, "message": f"Tag '{tag_name}' created successfully", "tag": tag}
return json.dumps(result, indent=2)
async def delete_tag(client: GiteaClient, owner: str, repo: str, tag: str) -> str:
"""Delete a tag"""
await client.delete_tag(owner, repo, tag)
result = {"success": True, "message": f"Tag '{tag}' deleted successfully"}
return json.dumps(result, indent=2)
# File operations
async def get_file(
client: GiteaClient, owner: str, repo: str, path: str, ref: str | None = None
) -> str:
"""Get file contents"""
file_data = await client.get_file(owner, repo, path, ref=ref)
result = {"success": True, "file": file_data}
return json.dumps(result, indent=2)
async def create_file(
client: GiteaClient,
owner: str,
repo: str,
path: str,
content: str,
message: str,
branch: str | None = None,
new_branch: str | None = None,
author_name: str | None = None,
author_email: str | None = None,
content_is_base64: bool = False,
) -> str:
"""Create a new file"""
data = {
"content": content,
"message": message,
"branch": branch,
"new_branch": new_branch,
"content_is_base64": content_is_base64,
"author": {},
}
if author_name:
data["author"]["name"] = author_name
if author_email:
data["author"]["email"] = author_email
file_result = await client.create_file(owner, repo, path, data)
result = {
"success": True,
"message": f"File '{path}' created successfully",
"file": file_result,
}
return json.dumps(result, indent=2)
async def update_file(
client: GiteaClient,
owner: str,
repo: str,
path: str,
content: str,
sha: str,
message: str,
branch: str | None = None,
new_branch: str | None = None,
content_is_base64: bool = False,
) -> str:
"""Update an existing file"""
data = {
"content": content,
"sha": sha,
"message": message,
"branch": branch,
"new_branch": new_branch,
"content_is_base64": content_is_base64,
}
file_result = await client.update_file(owner, repo, path, data)
result = {
"success": True,
"message": f"File '{path}' updated successfully",
"file": file_result,
}
return json.dumps(result, indent=2)
async def delete_file(
client: GiteaClient,
owner: str,
repo: str,
path: str,
sha: str,
message: str,
branch: str | None = None,
) -> str:
"""Delete a file from repository"""
await client.delete_file(owner, repo, path, sha, message, branch)
result = {"success": True, "message": f"File '{path}' deleted successfully"}
return json.dumps(result, indent=2)

View File

@@ -0,0 +1,245 @@
"""User & Organization Handler - manages Gitea users, organizations, and teams"""
import json
from typing import Any
from plugins.gitea.client import GiteaClient
def get_tool_specifications() -> list[dict[str, Any]]:
"""Return tool specifications for ToolGenerator"""
return [
# === USERS ===
{
"name": "get_user",
"method_name": "get_user",
"description": "Get information about a Gitea user by username.",
"schema": {
"type": "object",
"properties": {
"username": {
"type": "string",
"description": "Username to look up",
"minLength": 1,
}
},
"required": ["username"],
},
"scope": "read",
},
{
"name": "list_user_repos",
"method_name": "list_user_repos",
"description": "List all public repositories of a Gitea user.",
"schema": {
"type": "object",
"properties": {
"username": {"type": "string", "description": "Username", "minLength": 1},
"page": {
"type": "integer",
"description": "Page number",
"default": 1,
"minimum": 1,
},
"limit": {
"type": "integer",
"description": "Items per page (1-100)",
"default": 30,
"minimum": 1,
"maximum": 100,
},
},
"required": ["username"],
},
"scope": "read",
},
{
"name": "search_users",
"method_name": "search_users",
"description": "Search for Gitea users by query or user ID.",
"schema": {
"type": "object",
"properties": {
"q": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Search query (username or full name)",
},
"uid": {
"anyOf": [{"type": "integer"}, {"type": "null"}],
"description": "User ID to search for",
},
},
},
"scope": "read",
},
# === ORGANIZATIONS ===
{
"name": "list_organizations",
"method_name": "list_organizations",
"description": "List organizations for the current authenticated user.",
"schema": {
"type": "object",
"properties": {
"page": {
"type": "integer",
"description": "Page number",
"default": 1,
"minimum": 1,
},
"limit": {
"type": "integer",
"description": "Items per page (1-100)",
"default": 30,
"minimum": 1,
"maximum": 100,
},
},
},
"scope": "read",
},
{
"name": "get_organization",
"method_name": "get_organization",
"description": "Get information about a Gitea organization by name.",
"schema": {
"type": "object",
"properties": {
"org": {"type": "string", "description": "Organization name", "minLength": 1}
},
"required": ["org"],
},
"scope": "read",
},
{
"name": "list_org_repos",
"method_name": "list_org_repos",
"description": "List all repositories of an organization.",
"schema": {
"type": "object",
"properties": {
"org": {"type": "string", "description": "Organization name", "minLength": 1},
"page": {
"type": "integer",
"description": "Page number",
"default": 1,
"minimum": 1,
},
"limit": {
"type": "integer",
"description": "Items per page (1-100)",
"default": 30,
"minimum": 1,
"maximum": 100,
},
},
"required": ["org"],
},
"scope": "read",
},
# === TEAMS ===
{
"name": "list_org_teams",
"method_name": "list_org_teams",
"description": "List all teams in an organization.",
"schema": {
"type": "object",
"properties": {
"org": {"type": "string", "description": "Organization name", "minLength": 1},
"page": {
"type": "integer",
"description": "Page number",
"default": 1,
"minimum": 1,
},
"limit": {
"type": "integer",
"description": "Items per page (1-100)",
"default": 30,
"minimum": 1,
"maximum": 100,
},
},
"required": ["org"],
},
"scope": "read",
},
{
"name": "list_team_members",
"method_name": "list_team_members",
"description": "List all members of a team.",
"schema": {
"type": "object",
"properties": {
"team_id": {"type": "integer", "description": "Team ID", "minimum": 1},
"page": {
"type": "integer",
"description": "Page number",
"default": 1,
"minimum": 1,
},
"limit": {
"type": "integer",
"description": "Items per page (1-100)",
"default": 30,
"minimum": 1,
"maximum": 100,
},
},
"required": ["team_id"],
},
"scope": "read",
},
]
async def get_user(client: GiteaClient, username: str) -> str:
"""Get user information"""
user = await client.get_user(username)
result = {"success": True, "user": user}
return json.dumps(result, indent=2)
async def list_user_repos(
client: GiteaClient, username: str, page: int = 1, limit: int = 30
) -> str:
"""List user repositories"""
repos = await client.list_user_repos(username, page=page, limit=limit)
result = {"success": True, "count": len(repos), "repositories": repos}
return json.dumps(result, indent=2)
async def search_users(client: GiteaClient, q: str | None = None, uid: int | None = None) -> str:
"""Search users"""
users = await client.search_users(query=q, uid=uid)
result = {"success": True, "count": len(users), "users": users}
return json.dumps(result, indent=2)
# Organization operations
async def list_organizations(client: GiteaClient, page: int = 1, limit: int = 30) -> str:
"""List organizations"""
orgs = await client.list_organizations(page=page, limit=limit)
result = {"success": True, "count": len(orgs), "organizations": orgs}
return json.dumps(result, indent=2)
async def get_organization(client: GiteaClient, org: str) -> str:
"""Get organization information"""
organization = await client.get_organization(org)
result = {"success": True, "organization": organization}
return json.dumps(result, indent=2)
async def list_org_repos(client: GiteaClient, org: str, page: int = 1, limit: int = 30) -> str:
"""List organization repositories"""
repos = await client.list_org_repos(org, page=page, limit=limit)
result = {"success": True, "count": len(repos), "repositories": repos}
return json.dumps(result, indent=2)
# Team operations
async def list_org_teams(client: GiteaClient, org: str, page: int = 1, limit: int = 30) -> str:
"""List organization teams"""
teams = await client.list_org_teams(org, page=page, limit=limit)
result = {"success": True, "count": len(teams), "teams": teams}
return json.dumps(result, indent=2)
async def list_team_members(
client: GiteaClient, team_id: int, page: int = 1, limit: int = 30
) -> str:
"""List team members"""
members = await client.list_team_members(team_id, page=page, limit=limit)
result = {"success": True, "count": len(members), "members": members}
return json.dumps(result, indent=2)

View File

@@ -0,0 +1,216 @@
"""Webhook Handler - manages Gitea webhooks for repositories"""
import json
from typing import Any
from plugins.gitea.client import GiteaClient
def get_tool_specifications() -> list[dict[str, Any]]:
"""Return tool specifications for ToolGenerator"""
return [
# === WEBHOOKS ===
{
"name": "list_webhooks",
"method_name": "list_webhooks",
"description": "List all webhooks configured for a repository.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
},
"required": ["owner", "repo"],
},
"scope": "read",
},
{
"name": "create_webhook",
"method_name": "create_webhook",
"description": "Create a new webhook for a repository to receive event notifications.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"url": {
"type": "string",
"description": "Webhook URL to send events to",
"format": "uri",
},
"events": {
"type": "array",
"items": {
"type": "string",
"enum": [
"create",
"delete",
"fork",
"push",
"issues",
"issue_assign",
"issue_label",
"issue_milestone",
"issue_comment",
"pull_request",
"pull_request_assign",
"pull_request_label",
"pull_request_milestone",
"pull_request_comment",
"pull_request_review_approved",
"pull_request_review_rejected",
"pull_request_review_comment",
"pull_request_sync",
"wiki",
"repository",
"release",
],
},
"description": "List of events to trigger webhook",
"minItems": 1,
},
"content_type": {
"type": "string",
"description": "Content type for webhook payload",
"enum": ["json", "form"],
"default": "json",
},
"secret": {
"anyOf": [{"type": "string"}, {"type": "null"}],
"description": "Secret for webhook signature verification",
},
"active": {
"type": "boolean",
"description": "Activate webhook immediately",
"default": True,
},
"type": {
"type": "string",
"description": "Webhook type",
"enum": [
"gitea",
"gogs",
"slack",
"discord",
"dingtalk",
"telegram",
"msteams",
"feishu",
"wechatwork",
"packagist",
],
"default": "gitea",
},
},
"required": ["owner", "repo", "url", "events"],
},
"scope": "admin",
},
{
"name": "delete_webhook",
"method_name": "delete_webhook",
"description": "Delete a webhook from a repository.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"webhook_id": {
"type": "integer",
"description": "Webhook ID to delete",
"minimum": 1,
},
},
"required": ["owner", "repo", "webhook_id"],
},
"scope": "admin",
},
{
"name": "test_webhook",
"method_name": "test_webhook",
"description": "Send a test payload to a webhook to verify it's working.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"webhook_id": {
"type": "integer",
"description": "Webhook ID to test",
"minimum": 1,
},
},
"required": ["owner", "repo", "webhook_id"],
},
"scope": "admin",
},
{
"name": "get_webhook",
"method_name": "get_webhook",
"description": "Get details of a specific webhook.",
"schema": {
"type": "object",
"properties": {
"owner": {"type": "string", "description": "Repository owner", "minLength": 1},
"repo": {"type": "string", "description": "Repository name", "minLength": 1},
"webhook_id": {"type": "integer", "description": "Webhook ID", "minimum": 1},
},
"required": ["owner", "repo", "webhook_id"],
},
"scope": "read",
},
]
async def list_webhooks(client: GiteaClient, owner: str, repo: str) -> str:
"""List repository webhooks"""
webhooks = await client.list_webhooks(owner, repo)
result = {"success": True, "count": len(webhooks), "webhooks": webhooks}
return json.dumps(result, indent=2)
async def create_webhook(
client: GiteaClient,
owner: str,
repo: str,
url: str,
events: list[str],
content_type: str = "json",
secret: str | None = None,
active: bool = True,
type: str = "gitea",
) -> str:
"""Create a webhook"""
# Build webhook configuration
config = {"url": url, "content_type": content_type}
if secret:
config["secret"] = secret
data = {"type": type, "config": config, "events": events, "active": active}
webhook = await client.create_webhook(owner, repo, data)
result = {
"success": True,
"message": f"Webhook created successfully for {owner}/{repo}",
"webhook": webhook,
}
return json.dumps(result, indent=2)
async def delete_webhook(client: GiteaClient, owner: str, repo: str, webhook_id: int) -> str:
"""Delete a webhook"""
await client.delete_webhook(owner, repo, webhook_id)
result = {"success": True, "message": f"Webhook {webhook_id} deleted successfully"}
return json.dumps(result, indent=2)
async def test_webhook(client: GiteaClient, owner: str, repo: str, webhook_id: int) -> str:
"""Test a webhook"""
test_result = await client.test_webhook(owner, repo, webhook_id)
result = {
"success": True,
"message": f"Test payload sent to webhook {webhook_id}",
"result": test_result,
}
return json.dumps(result, indent=2)
async def get_webhook(client: GiteaClient, owner: str, repo: str, webhook_id: int) -> str:
"""Get webhook details"""
webhook = await client.get_webhook(owner, repo, webhook_id)
result = {"success": True, "webhook": webhook}
return json.dumps(result, indent=2)