112 lines
3.5 KiB
TypeScript
112 lines
3.5 KiB
TypeScript
import { writeFileSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import { type } from "arktype";
|
|
import type { PullReviewComment } from "@go-gitea/sdk.js";
|
|
import { stripExistingFooter } from "../utils/buildShockbotFooter.ts";
|
|
import { log } from "../utils/log.ts";
|
|
import type { ToolContext } from "./server.ts";
|
|
import { execute, tool } from "./shared.ts";
|
|
|
|
export const GetReviewComments = type({
|
|
pull_number: type.number.describe("The pull request number to get review comments for"),
|
|
});
|
|
|
|
export function GetReviewCommentsTool(ctx: ToolContext) {
|
|
return tool({
|
|
name: "get_review_comments",
|
|
description:
|
|
"Get all inline review comments for a pull request. " +
|
|
"Example: `get_review_comments({ pull_number: 1234 })`.",
|
|
parameters: GetReviewComments,
|
|
execute: execute(async ({ pull_number }) => {
|
|
ctx.toolState.issueNumber = pull_number;
|
|
|
|
// Get all reviews, then collect their comments
|
|
const reviews = await ctx.gitea.paginate(ctx.gitea.rest.repository.repoListPullReviews, {
|
|
owner: ctx.repo.owner,
|
|
repo: ctx.repo.name,
|
|
index: pull_number,
|
|
});
|
|
|
|
const allComments: PullReviewComment[] = [];
|
|
for (const review of reviews) {
|
|
if (!review.id) continue;
|
|
try {
|
|
const commentsResult = await ctx.gitea.rest.repository.repoGetPullReviewComments({
|
|
owner: ctx.repo.owner,
|
|
repo: ctx.repo.name,
|
|
index: pull_number,
|
|
id: review.id,
|
|
});
|
|
allComments.push(...commentsResult.data);
|
|
} catch {
|
|
// best-effort
|
|
}
|
|
}
|
|
|
|
const tempDir = process.env.SHOCKBOT_TEMP_DIR;
|
|
let filePath: string | undefined;
|
|
|
|
const rendered = allComments.map((c) => ({
|
|
id: c.id,
|
|
path: c.path,
|
|
// PullReviewComment uses `position` for the diff offset; Gitea doesn't
|
|
// expose separate new_position/old_position on GET — use original_position as fallback
|
|
line: c.original_position ?? c.position,
|
|
side: "RIGHT" as const,
|
|
body: stripExistingFooter(c.body ?? ""),
|
|
author: c.user?.login,
|
|
diffHunk: c.diff_hunk,
|
|
reviewId: c.pull_request_review_id,
|
|
}));
|
|
|
|
if (tempDir && rendered.length > 0) {
|
|
filePath = join(tempDir, `pr-${pull_number}-review-comments.json`);
|
|
writeFileSync(filePath, JSON.stringify(rendered, null, 2));
|
|
log.debug(`wrote review comments to ${filePath}`);
|
|
}
|
|
|
|
return {
|
|
pull_number,
|
|
comments: rendered,
|
|
count: rendered.length,
|
|
...(filePath ? { filePath } : {}),
|
|
};
|
|
}),
|
|
});
|
|
}
|
|
|
|
export const ListPullRequestReviews = type({
|
|
pull_number: type.number.describe("The pull request number"),
|
|
});
|
|
|
|
export function ListPullRequestReviewsTool(ctx: ToolContext) {
|
|
return tool({
|
|
name: "list_pull_request_reviews",
|
|
description:
|
|
"List all reviews submitted on a pull request. " +
|
|
"Example: `list_pull_request_reviews({ pull_number: 1234 })`.",
|
|
parameters: ListPullRequestReviews,
|
|
execute: execute(async ({ pull_number }) => {
|
|
const reviews = await ctx.gitea.paginate(ctx.gitea.rest.repository.repoListPullReviews, {
|
|
owner: ctx.repo.owner,
|
|
repo: ctx.repo.name,
|
|
index: pull_number,
|
|
});
|
|
|
|
return {
|
|
pull_number,
|
|
reviews: reviews.map((r) => ({
|
|
id: r.id,
|
|
user: r.user?.login,
|
|
state: r.state,
|
|
body: r.body,
|
|
submitted_at: r.submitted_at,
|
|
commit_id: r.commit_id,
|
|
})),
|
|
count: reviews.length,
|
|
};
|
|
}),
|
|
});
|
|
}
|