import { Gitea } from "@go-gitea/sdk.js"; import type { Comment, ChangedFile, PullReview, Reaction } from "@go-gitea/sdk.js"; import type { PRContext } from "./types.ts"; const client = new Gitea({ baseUrl: process.env.GITEA_URL, auth: process.env.BOT_TOKEN, }); export async function getPRDiff(pr: PRContext): Promise { const res = await client.rest.repository.repoDownloadPullDiffOrPatch({ owner: pr.owner, repo: pr.repo, index: pr.prNumber, diffType: "diff", }); return res.data; } export async function getPRFiles(pr: PRContext): Promise { const res = await client.rest.repository.repoGetPullRequestFiles({ owner: pr.owner, repo: pr.repo, index: pr.prNumber, }); return res.data; } export async function postReviewComment(pr: PRContext, body: string): Promise { const res = await client.rest.issue.issueCreateComment({ owner: pr.owner, repo: pr.repo, index: pr.prNumber, body: { body }, }); return res.data; } export async function postInlineComment( pr: PRContext, file: string, line: number, body: string, ): Promise { const res = await client.rest.repository.repoCreatePullReview({ owner: pr.owner, repo: pr.repo, index: pr.prNumber, body: { event: "COMMENT", commit_id: pr.headSha, comments: [{ path: file, new_position: line, body }], }, }); return res.data; } export async function addReaction( pr: PRContext, commentId: number, reaction: string, ): Promise { const res = await client.rest.issue.issuePostCommentReaction({ owner: pr.owner, repo: pr.repo, id: commentId, content: { content: reaction }, }); return res.data; } export async function removeReaction( pr: PRContext, commentId: number, reaction: string, ): Promise { await client.rest.issue.issueDeleteCommentReaction({ owner: pr.owner, repo: pr.repo, id: commentId, content: { content: reaction }, }); } export async function getPR(owner: string, repo: string, prNumber: number) { const res = await client.rest.repository.repoGetPullRequest({ owner, repo, index: prNumber, }); return res.data; } export async function getFileContents(pr: PRContext, filePath: string): Promise { const res = await client.rest.repository.repoGetContents({ owner: pr.owner, repo: pr.repo, filepath: filePath, ref: pr.headSha, }); const entry = Array.isArray(res.data) ? res.data[0] : res.data; if (!entry?.content || entry.type !== "file") return ""; // content is base64-encoded; Buffer handles embedded newlines return Buffer.from(entry.content, "base64").toString("utf8"); } export async function listDir(pr: PRContext, dirPath: string): Promise { const res = await client.rest.repository.repoGetContents({ owner: pr.owner, repo: pr.repo, filepath: dirPath, ref: pr.headSha, }); const entries = Array.isArray(res.data) ? res.data : [res.data]; return entries.map((e) => e.name ?? "").filter(Boolean); } // Gitea REST API v1 has no code search endpoint — returns repo names matching the query. // mcp.ts should strongly prefer disk grep (find_symbol) when workspace is available. export async function searchCode(pr: PRContext, query: string): Promise { const res = await client.rest.repository.repoSearch({ q: query, limit: 20, }); return (res.data.data ?? []).map((r) => r.full_name ?? "").filter(Boolean); }