FEAT: mr discussion with code diff (#93)
issue: #90 Made it possible to select multiple lines of diff when creating MR discussions. The API is difficult to use, so there is a possibility that AI will not be able to create appropriate payloads.
This commit is contained in:
225
index.ts
225
index.ts
@ -174,6 +174,13 @@ import {
|
||||
GitLabCompareResultSchema,
|
||||
GetBranchDiffsSchema,
|
||||
ListWikiPagesOptions,
|
||||
ListCommitsSchema,
|
||||
GetCommitSchema,
|
||||
GetCommitDiffSchema,
|
||||
type ListCommitsOptions,
|
||||
type GetCommitOptions,
|
||||
type GetCommitDiffOptions,
|
||||
ListMergeRequestDiffsSchema,
|
||||
} from "./schemas.js";
|
||||
|
||||
/**
|
||||
@ -411,6 +418,12 @@ const allTools = [
|
||||
"Get the changes/diffs of a merge request (Either mergeRequestIid or branchName must be provided)",
|
||||
inputSchema: zodToJsonSchema(GetMergeRequestDiffsSchema),
|
||||
},
|
||||
{
|
||||
name: "list_merge_request_diffs",
|
||||
description:
|
||||
"List merge request diffs with pagination support (Either mergeRequestIid or branchName must be provided)",
|
||||
inputSchema: zodToJsonSchema(ListMergeRequestDiffsSchema),
|
||||
},
|
||||
{
|
||||
name: "get_branch_diffs",
|
||||
description: "Get the changes/diffs between two branches or commits in a GitLab project",
|
||||
@ -681,6 +694,21 @@ const allTools = [
|
||||
description: "Get GitLab user details by usernames",
|
||||
inputSchema: zodToJsonSchema(GetUsersSchema),
|
||||
},
|
||||
{
|
||||
name: "list_commits",
|
||||
description: "List repository commits with filtering options",
|
||||
inputSchema: zodToJsonSchema(ListCommitsSchema),
|
||||
},
|
||||
{
|
||||
name: "get_commit",
|
||||
description: "Get details of a specific commit",
|
||||
inputSchema: zodToJsonSchema(GetCommitSchema),
|
||||
},
|
||||
{
|
||||
name: "get_commit_diff",
|
||||
description: "Get changes/diffs of a specific commit",
|
||||
inputSchema: zodToJsonSchema(GetCommitDiffSchema),
|
||||
},
|
||||
];
|
||||
|
||||
// Define which tools are read-only
|
||||
@ -719,6 +747,9 @@ const readOnlyTools = [
|
||||
"list_wiki_pages",
|
||||
"get_wiki_page",
|
||||
"get_users",
|
||||
"list_commits",
|
||||
"get_commit",
|
||||
"get_commit_diff",
|
||||
];
|
||||
|
||||
// Define which tools are related to wiki and can be toggled by USE_GITLAB_WIKI
|
||||
@ -1922,6 +1953,60 @@ async function getMergeRequestDiffs(
|
||||
return z.array(GitLabDiffSchema).parse(data.changes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get merge request changes with detailed information including commits, diff_refs, and more
|
||||
* 마지막으로 추가된 상세한 MR 변경사항 조회 함수 (Detailed merge request changes retrieval function)
|
||||
*
|
||||
* @param {string} projectId - The ID or URL-encoded path of the project
|
||||
* @param {number} mergeRequestIid - The internal ID of the merge request (Either mergeRequestIid or branchName must be provided)
|
||||
* @param {string} [branchName] - The name of the branch to search for merge request by branch name (Either mergeRequestIid or branchName must be provided)
|
||||
* @param {boolean} [unidiff] - Return diff in unidiff format
|
||||
* @returns {Promise<any>} The complete merge request changes response
|
||||
*/
|
||||
async function listMergeRequestDiffs(
|
||||
projectId: string,
|
||||
mergeRequestIid?: number,
|
||||
branchName?: string,
|
||||
page?: number,
|
||||
perPage?: number,
|
||||
unidiff?: boolean
|
||||
): Promise<any> {
|
||||
projectId = decodeURIComponent(projectId); // Decode project ID
|
||||
if (!mergeRequestIid && !branchName) {
|
||||
throw new Error("Either mergeRequestIid or branchName must be provided");
|
||||
}
|
||||
|
||||
if (branchName && !mergeRequestIid) {
|
||||
const mergeRequest = await getMergeRequest(projectId, undefined, branchName);
|
||||
mergeRequestIid = mergeRequest.iid;
|
||||
}
|
||||
|
||||
const url = new URL(
|
||||
`${GITLAB_API_URL}/projects/${encodeURIComponent(
|
||||
projectId
|
||||
)}/merge_requests/${mergeRequestIid}/diffs`
|
||||
);
|
||||
|
||||
if (page) {
|
||||
url.searchParams.append("page", page.toString());
|
||||
}
|
||||
|
||||
if (perPage) {
|
||||
url.searchParams.append("per_page", perPage.toString());
|
||||
}
|
||||
|
||||
if (unidiff) {
|
||||
url.searchParams.append("unidiff", "true");
|
||||
}
|
||||
|
||||
const response = await fetch(url.toString(), {
|
||||
...DEFAULT_FETCH_CONFIG,
|
||||
});
|
||||
|
||||
await handleGitLabError(response);
|
||||
return await response.json(); // Return full response including commits, diff_refs, changes, etc.
|
||||
}
|
||||
|
||||
/**
|
||||
* Get branch comparison diffs
|
||||
*
|
||||
@ -3154,6 +3239,107 @@ async function getUsers(usernames: string[]): Promise<GitLabUsersResponse> {
|
||||
return GitLabUsersResponseSchema.parse(users);
|
||||
}
|
||||
|
||||
/**
|
||||
* List repository commits
|
||||
* 저장소 커밋 목록 조회
|
||||
*
|
||||
* @param {string} projectId - Project ID or URL-encoded path
|
||||
* @param {ListCommitsOptions} options - List commits options
|
||||
* @returns {Promise<GitLabCommit[]>} List of commits
|
||||
*/
|
||||
async function listCommits(
|
||||
projectId: string,
|
||||
options: Omit<ListCommitsOptions, "project_id"> = {}
|
||||
): Promise<GitLabCommit[]> {
|
||||
projectId = decodeURIComponent(projectId);
|
||||
const url = new URL(
|
||||
`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/repository/commits`
|
||||
);
|
||||
|
||||
// Add query parameters
|
||||
if (options.ref_name) url.searchParams.append("ref_name", options.ref_name);
|
||||
if (options.since) url.searchParams.append("since", options.since);
|
||||
if (options.until) url.searchParams.append("until", options.until);
|
||||
if (options.path) url.searchParams.append("path", options.path);
|
||||
if (options.author) url.searchParams.append("author", options.author);
|
||||
if (options.all) url.searchParams.append("all", options.all.toString());
|
||||
if (options.with_stats) url.searchParams.append("with_stats", options.with_stats.toString());
|
||||
if (options.first_parent) url.searchParams.append("first_parent", options.first_parent.toString());
|
||||
if (options.order) url.searchParams.append("order", options.order);
|
||||
if (options.trailers) url.searchParams.append("trailers", options.trailers.toString());
|
||||
if (options.page) url.searchParams.append("page", options.page.toString());
|
||||
if (options.per_page) url.searchParams.append("per_page", options.per_page.toString());
|
||||
|
||||
const response = await fetch(url.toString(), {
|
||||
...DEFAULT_FETCH_CONFIG,
|
||||
});
|
||||
|
||||
await handleGitLabError(response);
|
||||
|
||||
const data = await response.json();
|
||||
return z.array(GitLabCommitSchema).parse(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single commit
|
||||
* 단일 커밋 정보 조회
|
||||
*
|
||||
* @param {string} projectId - Project ID or URL-encoded path
|
||||
* @param {string} sha - The commit hash or name of a repository branch or tag
|
||||
* @param {boolean} [stats] - Include commit stats
|
||||
* @returns {Promise<GitLabCommit>} The commit details
|
||||
*/
|
||||
async function getCommit(
|
||||
projectId: string,
|
||||
sha: string,
|
||||
stats?: boolean
|
||||
): Promise<GitLabCommit> {
|
||||
projectId = decodeURIComponent(projectId);
|
||||
const url = new URL(
|
||||
`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/repository/commits/${encodeURIComponent(sha)}`
|
||||
);
|
||||
|
||||
if (stats) {
|
||||
url.searchParams.append("stats", "true");
|
||||
}
|
||||
|
||||
const response = await fetch(url.toString(), {
|
||||
...DEFAULT_FETCH_CONFIG,
|
||||
});
|
||||
|
||||
await handleGitLabError(response);
|
||||
|
||||
const data = await response.json();
|
||||
return GitLabCommitSchema.parse(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get commit diff
|
||||
* 커밋 변경사항 조회
|
||||
*
|
||||
* @param {string} projectId - Project ID or URL-encoded path
|
||||
* @param {string} sha - The commit hash or name of a repository branch or tag
|
||||
* @returns {Promise<GitLabMergeRequestDiff[]>} The commit diffs
|
||||
*/
|
||||
async function getCommitDiff(
|
||||
projectId: string,
|
||||
sha: string
|
||||
): Promise<GitLabMergeRequestDiff[]> {
|
||||
projectId = decodeURIComponent(projectId);
|
||||
const url = new URL(
|
||||
`${GITLAB_API_URL}/projects/${encodeURIComponent(projectId)}/repository/commits/${encodeURIComponent(sha)}/diff`
|
||||
);
|
||||
|
||||
const response = await fetch(url.toString(), {
|
||||
...DEFAULT_FETCH_CONFIG,
|
||||
});
|
||||
|
||||
await handleGitLabError(response);
|
||||
|
||||
const data = await response.json();
|
||||
return z.array(GitLabDiffSchema).parse(data);
|
||||
}
|
||||
|
||||
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
// Apply read-only filter first
|
||||
const tools0 = GITLAB_READ_ONLY_MODE
|
||||
@ -3420,6 +3606,21 @@ server.setRequestHandler(CallToolRequestSchema, async request => {
|
||||
};
|
||||
}
|
||||
|
||||
case "list_merge_request_diffs": {
|
||||
const args = ListMergeRequestDiffsSchema.parse(request.params.arguments);
|
||||
const changes = await listMergeRequestDiffs(
|
||||
args.project_id,
|
||||
args.merge_request_iid,
|
||||
args.source_branch,
|
||||
args.page,
|
||||
args.per_page,
|
||||
args.unidiff
|
||||
);
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify(changes, null, 2) }],
|
||||
};
|
||||
}
|
||||
|
||||
case "update_merge_request": {
|
||||
const args = UpdateMergeRequestSchema.parse(request.params.arguments);
|
||||
const { project_id, merge_request_iid, source_branch, ...options } = args;
|
||||
@ -4053,6 +4254,30 @@ server.setRequestHandler(CallToolRequestSchema, async request => {
|
||||
};
|
||||
}
|
||||
|
||||
case "list_commits": {
|
||||
const args = ListCommitsSchema.parse(request.params.arguments);
|
||||
const commits = await listCommits(args.project_id, args);
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify(commits, null, 2) }],
|
||||
};
|
||||
}
|
||||
|
||||
case "get_commit": {
|
||||
const args = GetCommitSchema.parse(request.params.arguments);
|
||||
const commit = await getCommit(args.project_id, args.sha, args.stats);
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify(commit, null, 2) }],
|
||||
};
|
||||
}
|
||||
|
||||
case "get_commit_diff": {
|
||||
const args = GetCommitDiffSchema.parse(request.params.arguments);
|
||||
const diff = await getCommitDiff(args.project_id, args.sha);
|
||||
return {
|
||||
content: [{ type: "text", text: JSON.stringify(diff, null, 2) }],
|
||||
};
|
||||
}
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown tool: ${request.params.name}`);
|
||||
}
|
||||
|
Reference in New Issue
Block a user