feat: add file attachment support to issue tracker with Gitea mirroring

Implement full attachment CRUD for issues and comments, restricted to open issues only. Attachments are stored locally and mirrored to the Gitea tracker via new `mirror_attachment_to_gitea` and `set_gitea_asset_id` functions. Add `gitea_asset_id` column to the attachments table, extend `IssueForm` and `IssueCommentForm` with `attachment_uids` field, and expose new API endpoints for listing, adding, and deleting issue attachments. Update agent configuration to include web research tools, and document the new capability in README, AGENTS.md, and CLAUDE.md.
This commit is contained in:
2026-06-19 11:22:05 +00:00
parent a6cc83bfd2
commit 7bbaf51450
28 changed files with 1191 additions and 21 deletions
@@ -1016,6 +1016,62 @@ ACTIONS: tuple[Action, ...] = (
body("status", "New status: open or closed.", required=True),
),
),
Action(
name="list_issue_attachments",
method="GET",
path="/issues/{number}/attachments",
summary="List the files attached to an issue ticket",
requires_auth=False,
params=(path("number", "The issue ticket number."),),
),
Action(
name="add_issue_attachment",
method="POST",
path="/issues/{number}/attachments",
summary="Attach already-uploaded files to an open issue ticket",
description=(
"Upload files first with upload_file, then pass their uids here. Only works while "
"the issue is open; the files are mirrored to the tracker."
),
params=(
path("number", "The issue ticket number."),
body("attachment_uids", ATTACHMENTS, required=True),
),
),
Action(
name="delete_issue_attachment",
method="DELETE",
path="/issues/{number}/attachments/{uid}",
summary="Delete a file from an open issue ticket (your own, or any when administrator). Soft delete, confirmation required",
params=(
path("number", "The issue ticket number."),
path("uid", "The attachment uid."),
confirm(),
),
),
Action(
name="add_comment_attachment",
method="POST",
path="/issues/{number}/comments/{cid}/attachments",
summary="Attach already-uploaded files to an issue comment (issue must be open)",
params=(
path("number", "The issue ticket number."),
path("cid", "The Gitea comment id."),
body("attachment_uids", ATTACHMENTS, required=True),
),
),
Action(
name="delete_comment_attachment",
method="DELETE",
path="/issues/{number}/comments/{cid}/attachments/{uid}",
summary="Delete a file from an issue comment (your own, or any when administrator). Soft delete, confirmation required",
params=(
path("number", "The issue ticket number."),
path("cid", "The Gitea comment id."),
path("uid", "The attachment uid."),
confirm(),
),
),
Action(
name="list_gists",
method="GET",
@@ -45,6 +45,8 @@ CONFIRM_REQUIRED = {
"delete_comment",
"delete_gist",
"delete_attachment",
"delete_issue_attachment",
"delete_comment_attachment",
"admin_media_purge",
"admin_delete_news",
"admin_reset_all_ai_quota",