import { z } from "zod";
import { AdoClient } from "../../ado-client.js";
import * as GitInterfaces from "azure-devops-node-api/interfaces/GitInterfaces";
export const getPullRequestCommentsSchema = z.object({
project: z.string().optional().describe("Project name, defaults to ADO_PROJECT env var"),
repository: z.string().describe("Repository name or ID"),
pullRequestId: z.number().describe("Pull request ID"),
});
export const getPullRequestCommentsTool = {
name: "get_pull_request_comments",
description: "Retrieve all comment threads and replies on a pull request. Returns thread status, file path and line number for inline comments, comment content, author, and date. Use this to review feedback, check for unresolved comments, or see discussion history.",
inputSchema: {
type: "object" as const,
properties: {
project: {
type: "string",
description: "Project name, defaults to ADO_PROJECT env var",
},
repository: {
type: "string",
description: "Repository name or ID",
},
pullRequestId: {
type: "number",
description: "Pull request ID",
},
},
required: ["repository", "pullRequestId"],
},
};
export interface CommentThread {
id: number;
status: string;
filePath?: string;
lineNumber?: number;
comments: Array<{
id: number;
content: string;
author: string;
createdDate: string;
isDeleted: boolean;
}>;
}
export async function getPullRequestComments(
client: AdoClient,
params: z.infer<typeof getPullRequestCommentsSchema>
): Promise<CommentThread[]> {
const validatedParams = getPullRequestCommentsSchema.parse(params);
const project = client.resolveProject(validatedParams.project);
const gitApi = await client.getGitApi();
const threads = await gitApi.getThreads(
validatedParams.repository,
validatedParams.pullRequestId,
project
);
if (!threads) {
return [];
}
return threads.map((thread) => ({
id: thread.id || 0,
status: getThreadStatusString(thread.status),
filePath: thread.threadContext?.filePath,
lineNumber: thread.threadContext?.rightFileStart?.line,
comments: (thread.comments || []).map((comment) => ({
id: comment.id || 0,
content: comment.content || "",
author: comment.author?.displayName || "",
createdDate: comment.publishedDate?.toISOString() || "",
isDeleted: comment.isDeleted || false,
})),
}));
}
function getThreadStatusString(
status?: GitInterfaces.CommentThreadStatus
): string {
switch (status) {
case GitInterfaces.CommentThreadStatus.Active:
return "active";
case GitInterfaces.CommentThreadStatus.Fixed:
return "fixed";
case GitInterfaces.CommentThreadStatus.WontFix:
return "wontFix";
case GitInterfaces.CommentThreadStatus.Closed:
return "closed";
case GitInterfaces.CommentThreadStatus.Pending:
return "pending";
case GitInterfaces.CommentThreadStatus.ByDesign:
return "byDesign";
default:
return "unknown";
}
}