@gitlab/opencode-gitlab-plugin 1.5.1 → 1.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -59
- package/README.md +97 -37
- package/dist/gitlab-opencode-gitlab-plugin-1.5.3.tgz +0 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.js +304 -572
- package/package.json +1 -1
- package/dist/gitlab-opencode-gitlab-plugin-1.5.1.tgz +0 -0
package/dist/index.js
CHANGED
|
@@ -2086,29 +2086,6 @@ Returns the list of files changed with their diffs.`,
|
|
|
2086
2086
|
return JSON.stringify(changes, null, 2);
|
|
2087
2087
|
}
|
|
2088
2088
|
}),
|
|
2089
|
-
gitlab_list_mr_discussions: tool({
|
|
2090
|
-
description: `List discussions (comment threads) on a merge request.
|
|
2091
|
-
Returns all discussion threads with nested notes. Each discussion contains a 'notes' array with individual comments.
|
|
2092
|
-
Note: For a flattened list of all comments, use gitlab_list_mr_notes instead.`,
|
|
2093
|
-
args: {
|
|
2094
|
-
project_id: z.string().describe("The project ID or URL-encoded path"),
|
|
2095
|
-
mr_iid: z.number().describe("The internal ID of the merge request"),
|
|
2096
|
-
first: z.number().optional().describe("Number of discussions to fetch from the beginning (default: 20)"),
|
|
2097
|
-
after: z.string().optional().describe("Cursor for forward pagination (from pageInfo.endCursor)"),
|
|
2098
|
-
last: z.number().optional().describe("Number of discussions to fetch from the end"),
|
|
2099
|
-
before: z.string().optional().describe("Cursor for backward pagination (from pageInfo.startCursor)")
|
|
2100
|
-
},
|
|
2101
|
-
execute: async (args, _ctx) => {
|
|
2102
|
-
const client = getGitLabClient();
|
|
2103
|
-
const discussions = await client.listMrDiscussions(args.project_id, args.mr_iid, {
|
|
2104
|
-
first: args.first,
|
|
2105
|
-
after: args.after,
|
|
2106
|
-
last: args.last,
|
|
2107
|
-
before: args.before
|
|
2108
|
-
});
|
|
2109
|
-
return JSON.stringify(discussions, null, 2);
|
|
2110
|
-
}
|
|
2111
|
-
}),
|
|
2112
2089
|
gitlab_list_mr_notes: tool({
|
|
2113
2090
|
description: `List all notes/comments on a merge request using GraphQL API with pagination support.
|
|
2114
2091
|
Returns all comments including system notes, code review comments, and general discussion.
|
|
@@ -2136,117 +2113,6 @@ Use 'before' with the 'startCursor' from pageInfo to get the previous page.`,
|
|
|
2136
2113
|
return JSON.stringify(result, null, 2);
|
|
2137
2114
|
}
|
|
2138
2115
|
}),
|
|
2139
|
-
gitlab_create_mr_note: tool({
|
|
2140
|
-
description: `Add a comment/note to a merge request.
|
|
2141
|
-
If discussion_id is provided, the note will be added as a reply to an existing discussion thread.
|
|
2142
|
-
Use gitlab_list_mr_discussions to find discussion IDs for existing threads.`,
|
|
2143
|
-
args: {
|
|
2144
|
-
project_id: z.string().describe("The project ID or URL-encoded path"),
|
|
2145
|
-
mr_iid: z.number().describe("The internal ID of the merge request"),
|
|
2146
|
-
body: z.string().describe("The content of the note/comment (supports Markdown)"),
|
|
2147
|
-
discussion_id: z.string().optional().describe(
|
|
2148
|
-
"The ID of a discussion thread to reply to. If provided, the note will be added as a reply to that discussion."
|
|
2149
|
-
)
|
|
2150
|
-
},
|
|
2151
|
-
execute: async (args, _ctx) => {
|
|
2152
|
-
const client = getGitLabClient();
|
|
2153
|
-
const note = await client.createMrNote(
|
|
2154
|
-
args.project_id,
|
|
2155
|
-
args.mr_iid,
|
|
2156
|
-
args.body,
|
|
2157
|
-
args.discussion_id
|
|
2158
|
-
);
|
|
2159
|
-
return JSON.stringify(note, null, 2);
|
|
2160
|
-
}
|
|
2161
|
-
}),
|
|
2162
|
-
gitlab_get_mr_discussion: tool({
|
|
2163
|
-
description: `Get a specific discussion thread from a merge request with all its replies.
|
|
2164
|
-
Returns the discussion with its 'notes' array containing all comments in the thread.
|
|
2165
|
-
Use this to get the full context of a specific conversation.`,
|
|
2166
|
-
args: {
|
|
2167
|
-
project_id: z.string().describe("The project ID or URL-encoded path"),
|
|
2168
|
-
mr_iid: z.number().describe("The internal ID of the merge request"),
|
|
2169
|
-
discussion_id: z.string().describe("The ID of the discussion thread")
|
|
2170
|
-
},
|
|
2171
|
-
execute: async (args, _ctx) => {
|
|
2172
|
-
const client = getGitLabClient();
|
|
2173
|
-
const discussion = await client.getMrDiscussion(
|
|
2174
|
-
args.project_id,
|
|
2175
|
-
args.mr_iid,
|
|
2176
|
-
args.discussion_id
|
|
2177
|
-
);
|
|
2178
|
-
return JSON.stringify(discussion, null, 2);
|
|
2179
|
-
}
|
|
2180
|
-
}),
|
|
2181
|
-
gitlab_resolve_mr_discussion: tool({
|
|
2182
|
-
description: `Mark a merge request discussion thread as resolved.
|
|
2183
|
-
Use this after addressing feedback in a code review to indicate the discussion is complete.
|
|
2184
|
-
Only works for resolvable discussions (typically code review comments).`,
|
|
2185
|
-
args: {
|
|
2186
|
-
project_id: z.string().describe("The project ID or URL-encoded path"),
|
|
2187
|
-
mr_iid: z.number().describe("The internal ID of the merge request"),
|
|
2188
|
-
discussion_id: z.string().describe("The ID of the discussion thread to resolve")
|
|
2189
|
-
},
|
|
2190
|
-
execute: async (args, _ctx) => {
|
|
2191
|
-
const client = getGitLabClient();
|
|
2192
|
-
const discussion = await client.resolveMrDiscussion(
|
|
2193
|
-
args.project_id,
|
|
2194
|
-
args.mr_iid,
|
|
2195
|
-
args.discussion_id
|
|
2196
|
-
);
|
|
2197
|
-
return JSON.stringify(discussion, null, 2);
|
|
2198
|
-
}
|
|
2199
|
-
}),
|
|
2200
|
-
gitlab_unresolve_mr_discussion: tool({
|
|
2201
|
-
description: `Reopen a resolved merge request discussion thread.
|
|
2202
|
-
Use this to indicate that a previously resolved discussion needs more attention.`,
|
|
2203
|
-
args: {
|
|
2204
|
-
project_id: z.string().describe("The project ID or URL-encoded path"),
|
|
2205
|
-
mr_iid: z.number().describe("The internal ID of the merge request"),
|
|
2206
|
-
discussion_id: z.string().describe("The ID of the discussion thread to unresolve")
|
|
2207
|
-
},
|
|
2208
|
-
execute: async (args, _ctx) => {
|
|
2209
|
-
const client = getGitLabClient();
|
|
2210
|
-
const discussion = await client.unresolveMrDiscussion(
|
|
2211
|
-
args.project_id,
|
|
2212
|
-
args.mr_iid,
|
|
2213
|
-
args.discussion_id
|
|
2214
|
-
);
|
|
2215
|
-
return JSON.stringify(discussion, null, 2);
|
|
2216
|
-
}
|
|
2217
|
-
}),
|
|
2218
|
-
gitlab_create_mr_discussion: tool({
|
|
2219
|
-
description: `Start a new discussion thread on a merge request.
|
|
2220
|
-
Creates a new discussion with an initial comment. Optionally can be positioned on specific code.
|
|
2221
|
-
For general comments, just provide the body. For code comments, provide position information.`,
|
|
2222
|
-
args: {
|
|
2223
|
-
project_id: z.string().describe("The project ID or URL-encoded path"),
|
|
2224
|
-
mr_iid: z.number().describe("The internal ID of the merge request"),
|
|
2225
|
-
body: z.string().describe("The content of the initial comment (supports Markdown)"),
|
|
2226
|
-
position: z.object({
|
|
2227
|
-
base_sha: z.string().describe("SHA of the base commit (merge base)"),
|
|
2228
|
-
start_sha: z.string().describe("SHA of the commit when the MR was created"),
|
|
2229
|
-
head_sha: z.string().describe("SHA of the HEAD commit"),
|
|
2230
|
-
position_type: z.enum(["text", "image"]).describe("Type of position (text or image)"),
|
|
2231
|
-
new_path: z.string().optional().describe("Path of the file after changes"),
|
|
2232
|
-
old_path: z.string().optional().describe("Path of the file before changes"),
|
|
2233
|
-
new_line: z.number().optional().describe("Line number in the new version"),
|
|
2234
|
-
old_line: z.number().optional().describe("Line number in the old version")
|
|
2235
|
-
}).optional().describe(
|
|
2236
|
-
"Position information for code comments. Required fields: base_sha, start_sha, head_sha, position_type. For line comments also provide new_path/old_path and new_line/old_line."
|
|
2237
|
-
)
|
|
2238
|
-
},
|
|
2239
|
-
execute: async (args, _ctx) => {
|
|
2240
|
-
const client = getGitLabClient();
|
|
2241
|
-
const discussion = await client.createMrDiscussion(
|
|
2242
|
-
args.project_id,
|
|
2243
|
-
args.mr_iid,
|
|
2244
|
-
args.body,
|
|
2245
|
-
args.position
|
|
2246
|
-
);
|
|
2247
|
-
return JSON.stringify(discussion, null, 2);
|
|
2248
|
-
}
|
|
2249
|
-
}),
|
|
2250
2116
|
gitlab_create_merge_request: tool({
|
|
2251
2117
|
description: `Create a new merge request.
|
|
2252
2118
|
Returns the created merge request with all details.`,
|
|
@@ -2491,108 +2357,6 @@ Use 'before' with the 'startCursor' from pageInfo to get the previous page.`,
|
|
|
2491
2357
|
return JSON.stringify(result, null, 2);
|
|
2492
2358
|
}
|
|
2493
2359
|
}),
|
|
2494
|
-
gitlab_list_issue_discussions: tool2({
|
|
2495
|
-
description: `List discussions (comment threads) on an issue.
|
|
2496
|
-
Returns all discussion threads with nested notes. Each discussion contains a 'notes' array with individual comments.
|
|
2497
|
-
Use the discussion 'id' field to reply to a specific thread with gitlab_create_issue_note.`,
|
|
2498
|
-
args: {
|
|
2499
|
-
project_id: z2.string().describe("The project ID or URL-encoded path"),
|
|
2500
|
-
issue_iid: z2.number().describe("The internal ID of the issue"),
|
|
2501
|
-
first: z2.number().optional().describe("Number of discussions to fetch from the beginning (default: 20)"),
|
|
2502
|
-
after: z2.string().optional().describe("Cursor for forward pagination (from pageInfo.endCursor)"),
|
|
2503
|
-
last: z2.number().optional().describe("Number of discussions to fetch from the end"),
|
|
2504
|
-
before: z2.string().optional().describe("Cursor for backward pagination (from pageInfo.startCursor)")
|
|
2505
|
-
},
|
|
2506
|
-
execute: async (args, _ctx) => {
|
|
2507
|
-
const client = getGitLabClient();
|
|
2508
|
-
const discussions = await client.listIssueDiscussions(args.project_id, args.issue_iid, {
|
|
2509
|
-
first: args.first,
|
|
2510
|
-
after: args.after,
|
|
2511
|
-
last: args.last,
|
|
2512
|
-
before: args.before
|
|
2513
|
-
});
|
|
2514
|
-
return JSON.stringify(discussions, null, 2);
|
|
2515
|
-
}
|
|
2516
|
-
}),
|
|
2517
|
-
gitlab_create_issue_note: tool2({
|
|
2518
|
-
description: `Add a comment/note to an issue.
|
|
2519
|
-
If discussion_id is provided, the note will be added as a reply to an existing discussion thread.
|
|
2520
|
-
Use gitlab_list_issue_discussions to find discussion IDs for existing threads.`,
|
|
2521
|
-
args: {
|
|
2522
|
-
project_id: z2.string().describe("The project ID or URL-encoded path"),
|
|
2523
|
-
issue_iid: z2.number().describe("The internal ID of the issue"),
|
|
2524
|
-
body: z2.string().describe("The content of the note/comment (supports Markdown)"),
|
|
2525
|
-
discussion_id: z2.string().optional().describe(
|
|
2526
|
-
"The ID of a discussion thread to reply to. If provided, the note will be added as a reply to that discussion."
|
|
2527
|
-
)
|
|
2528
|
-
},
|
|
2529
|
-
execute: async (args, _ctx) => {
|
|
2530
|
-
const client = getGitLabClient();
|
|
2531
|
-
const note = await client.createIssueNote(
|
|
2532
|
-
args.project_id,
|
|
2533
|
-
args.issue_iid,
|
|
2534
|
-
args.body,
|
|
2535
|
-
args.discussion_id
|
|
2536
|
-
);
|
|
2537
|
-
return JSON.stringify(note, null, 2);
|
|
2538
|
-
}
|
|
2539
|
-
}),
|
|
2540
|
-
gitlab_get_issue_discussion: tool2({
|
|
2541
|
-
description: `Get a specific discussion thread from an issue with all its replies.
|
|
2542
|
-
Returns the discussion with its 'notes' array containing all comments in the thread.
|
|
2543
|
-
Use this to get the full context of a specific conversation.`,
|
|
2544
|
-
args: {
|
|
2545
|
-
project_id: z2.string().describe("The project ID or URL-encoded path"),
|
|
2546
|
-
issue_iid: z2.number().describe("The internal ID of the issue"),
|
|
2547
|
-
discussion_id: z2.string().describe("The ID of the discussion thread")
|
|
2548
|
-
},
|
|
2549
|
-
execute: async (args, _ctx) => {
|
|
2550
|
-
const client = getGitLabClient();
|
|
2551
|
-
const discussion = await client.getIssueDiscussion(
|
|
2552
|
-
args.project_id,
|
|
2553
|
-
args.issue_iid,
|
|
2554
|
-
args.discussion_id
|
|
2555
|
-
);
|
|
2556
|
-
return JSON.stringify(discussion, null, 2);
|
|
2557
|
-
}
|
|
2558
|
-
}),
|
|
2559
|
-
gitlab_resolve_issue_discussion: tool2({
|
|
2560
|
-
description: `Mark an issue discussion thread as resolved.
|
|
2561
|
-
Use this after addressing feedback in a code review or issue discussion to indicate the discussion is complete.
|
|
2562
|
-
Only works for resolvable discussions (typically multi-note threads, not individual notes).`,
|
|
2563
|
-
args: {
|
|
2564
|
-
project_id: z2.string().describe("The project ID or URL-encoded path"),
|
|
2565
|
-
issue_iid: z2.number().describe("The internal ID of the issue"),
|
|
2566
|
-
discussion_id: z2.string().describe("The ID of the discussion thread to resolve")
|
|
2567
|
-
},
|
|
2568
|
-
execute: async (args, _ctx) => {
|
|
2569
|
-
const client = getGitLabClient();
|
|
2570
|
-
const discussion = await client.resolveIssueDiscussion(
|
|
2571
|
-
args.project_id,
|
|
2572
|
-
args.issue_iid,
|
|
2573
|
-
args.discussion_id
|
|
2574
|
-
);
|
|
2575
|
-
return JSON.stringify(discussion, null, 2);
|
|
2576
|
-
}
|
|
2577
|
-
}),
|
|
2578
|
-
gitlab_unresolve_issue_discussion: tool2({
|
|
2579
|
-
description: `Reopen a resolved issue discussion thread.
|
|
2580
|
-
Use this to indicate that a previously resolved discussion needs more attention or further discussion.`,
|
|
2581
|
-
args: {
|
|
2582
|
-
project_id: z2.string().describe("The project ID or URL-encoded path"),
|
|
2583
|
-
issue_iid: z2.number().describe("The internal ID of the issue"),
|
|
2584
|
-
discussion_id: z2.string().describe("The ID of the discussion thread to unresolve")
|
|
2585
|
-
},
|
|
2586
|
-
execute: async (args, _ctx) => {
|
|
2587
|
-
const client = getGitLabClient();
|
|
2588
|
-
const discussion = await client.unresolveIssueDiscussion(
|
|
2589
|
-
args.project_id,
|
|
2590
|
-
args.issue_iid,
|
|
2591
|
-
args.discussion_id
|
|
2592
|
-
);
|
|
2593
|
-
return JSON.stringify(discussion, null, 2);
|
|
2594
|
-
}
|
|
2595
|
-
}),
|
|
2596
2360
|
gitlab_get_issue_note: tool2({
|
|
2597
2361
|
description: `Get a single note/comment from an issue by its ID.
|
|
2598
2362
|
Returns the full details of a specific note including author, body, timestamps, and metadata.
|
|
@@ -2777,71 +2541,6 @@ Use 'before' with the 'startCursor' from pageInfo to get the previous page.`,
|
|
|
2777
2541
|
return JSON.stringify(result, null, 2);
|
|
2778
2542
|
}
|
|
2779
2543
|
}),
|
|
2780
|
-
gitlab_list_epic_discussions: tool3({
|
|
2781
|
-
description: `List discussions (comment threads) on an epic.
|
|
2782
|
-
Returns all discussion threads with nested notes. Each discussion contains a 'notes' array with individual comments.
|
|
2783
|
-
Use the discussion 'id' field to reply to a specific thread with gitlab_create_epic_note.`,
|
|
2784
|
-
args: {
|
|
2785
|
-
group_id: z3.string().describe("The group ID or URL-encoded path"),
|
|
2786
|
-
epic_iid: z3.number().describe("The internal ID of the epic"),
|
|
2787
|
-
first: z3.number().optional().describe("Number of discussions to fetch from the beginning (default: 20)"),
|
|
2788
|
-
after: z3.string().optional().describe("Cursor for forward pagination (from pageInfo.endCursor)"),
|
|
2789
|
-
last: z3.number().optional().describe("Number of discussions to fetch from the end"),
|
|
2790
|
-
before: z3.string().optional().describe("Cursor for backward pagination (from pageInfo.startCursor)")
|
|
2791
|
-
},
|
|
2792
|
-
execute: async (args, _ctx) => {
|
|
2793
|
-
const client = getGitLabClient();
|
|
2794
|
-
const discussions = await client.listEpicDiscussions(args.group_id, args.epic_iid, {
|
|
2795
|
-
first: args.first,
|
|
2796
|
-
after: args.after,
|
|
2797
|
-
last: args.last,
|
|
2798
|
-
before: args.before
|
|
2799
|
-
});
|
|
2800
|
-
return JSON.stringify(discussions, null, 2);
|
|
2801
|
-
}
|
|
2802
|
-
}),
|
|
2803
|
-
gitlab_create_epic_note: tool3({
|
|
2804
|
-
description: `Add a comment/note to an epic.
|
|
2805
|
-
If discussion_id is provided, the note will be added as a reply to an existing discussion thread.
|
|
2806
|
-
Use gitlab_list_epic_discussions to find discussion IDs for existing threads.`,
|
|
2807
|
-
args: {
|
|
2808
|
-
group_id: z3.string().describe("The group ID or URL-encoded path"),
|
|
2809
|
-
epic_iid: z3.number().describe("The internal ID of the epic"),
|
|
2810
|
-
body: z3.string().describe("The content of the note/comment (supports Markdown)"),
|
|
2811
|
-
discussion_id: z3.string().optional().describe(
|
|
2812
|
-
"The ID of a discussion thread to reply to. If provided, the note will be added as a reply to that discussion."
|
|
2813
|
-
)
|
|
2814
|
-
},
|
|
2815
|
-
execute: async (args, _ctx) => {
|
|
2816
|
-
const client = getGitLabClient();
|
|
2817
|
-
const note = await client.createEpicNote(
|
|
2818
|
-
args.group_id,
|
|
2819
|
-
args.epic_iid,
|
|
2820
|
-
args.body,
|
|
2821
|
-
args.discussion_id
|
|
2822
|
-
);
|
|
2823
|
-
return JSON.stringify(note, null, 2);
|
|
2824
|
-
}
|
|
2825
|
-
}),
|
|
2826
|
-
gitlab_get_epic_discussion: tool3({
|
|
2827
|
-
description: `Get a specific discussion thread from an epic with all its replies.
|
|
2828
|
-
Returns the discussion with its 'notes' array containing all comments in the thread.
|
|
2829
|
-
Use this to get the full context of a specific conversation.`,
|
|
2830
|
-
args: {
|
|
2831
|
-
group_id: z3.string().describe("The group ID or URL-encoded path"),
|
|
2832
|
-
epic_iid: z3.number().describe("The internal ID of the epic"),
|
|
2833
|
-
discussion_id: z3.string().describe("The ID of the discussion thread")
|
|
2834
|
-
},
|
|
2835
|
-
execute: async (args, _ctx) => {
|
|
2836
|
-
const client = getGitLabClient();
|
|
2837
|
-
const discussion = await client.getEpicDiscussion(
|
|
2838
|
-
args.group_id,
|
|
2839
|
-
args.epic_iid,
|
|
2840
|
-
args.discussion_id
|
|
2841
|
-
);
|
|
2842
|
-
return JSON.stringify(discussion, null, 2);
|
|
2843
|
-
}
|
|
2844
|
-
}),
|
|
2845
2544
|
gitlab_get_epic_note: tool3({
|
|
2846
2545
|
description: `Get a single note/comment from an epic by its ID.
|
|
2847
2546
|
Returns the full details of a specific note including author, body, timestamps, and metadata.
|
|
@@ -3092,40 +2791,6 @@ Returns commit metadata including author, message, stats, and parent commits.`,
|
|
|
3092
2791
|
return JSON.stringify(diff, null, 2);
|
|
3093
2792
|
}
|
|
3094
2793
|
}),
|
|
3095
|
-
gitlab_create_commit: tool5({
|
|
3096
|
-
description: `Create a commit with multiple file actions.
|
|
3097
|
-
Supports creating, updating, deleting, moving files, and changing permissions.`,
|
|
3098
|
-
args: {
|
|
3099
|
-
project_id: z5.string().describe("The project ID or URL-encoded path"),
|
|
3100
|
-
branch: z5.string().describe("Name of the branch to commit into"),
|
|
3101
|
-
commit_message: z5.string().describe("Commit message"),
|
|
3102
|
-
actions: z5.array(
|
|
3103
|
-
z5.object({
|
|
3104
|
-
action: z5.enum(["create", "delete", "move", "update", "chmod"]).describe("The action to perform"),
|
|
3105
|
-
file_path: z5.string().describe("Full path to the file"),
|
|
3106
|
-
content: z5.string().optional().describe("File content (required for create/update)"),
|
|
3107
|
-
encoding: z5.enum(["text", "base64"]).optional().describe("Encoding of content (default: text)"),
|
|
3108
|
-
previous_path: z5.string().optional().describe("Original path (required for move)"),
|
|
3109
|
-
execute_filemode: z5.boolean().optional().describe("Enable/disable execute flag (for chmod)")
|
|
3110
|
-
})
|
|
3111
|
-
).describe("Array of file actions to perform"),
|
|
3112
|
-
author_email: z5.string().optional().describe("Author email address"),
|
|
3113
|
-
author_name: z5.string().optional().describe("Author name"),
|
|
3114
|
-
start_branch: z5.string().optional().describe("Name of the branch to start from (if different from target branch)")
|
|
3115
|
-
},
|
|
3116
|
-
execute: async (args, _ctx) => {
|
|
3117
|
-
const client = getGitLabClient();
|
|
3118
|
-
const commit = await client.createCommit(args.project_id, {
|
|
3119
|
-
branch: args.branch,
|
|
3120
|
-
commit_message: args.commit_message,
|
|
3121
|
-
actions: args.actions,
|
|
3122
|
-
author_email: args.author_email,
|
|
3123
|
-
author_name: args.author_name,
|
|
3124
|
-
start_branch: args.start_branch
|
|
3125
|
-
});
|
|
3126
|
-
return JSON.stringify(commit, null, 2);
|
|
3127
|
-
}
|
|
3128
|
-
}),
|
|
3129
2794
|
gitlab_list_repository_tree: tool5({
|
|
3130
2795
|
description: `List files and directories in a repository.
|
|
3131
2796
|
Returns the tree structure of the repository at a given path and ref.`,
|
|
@@ -3159,101 +2824,6 @@ Returns the tree structure of the repository at a given path and ref.`,
|
|
|
3159
2824
|
return JSON.stringify(branches, null, 2);
|
|
3160
2825
|
}
|
|
3161
2826
|
}),
|
|
3162
|
-
// ========== Commit Discussion Tools ==========
|
|
3163
|
-
gitlab_list_commit_discussions: tool5({
|
|
3164
|
-
description: `List discussions (comment threads) on a commit.
|
|
3165
|
-
Returns all discussion threads with nested notes. Each discussion contains a 'notes' array with individual comments.
|
|
3166
|
-
Use the discussion 'id' field to reply to a specific thread with gitlab_create_commit_note.`,
|
|
3167
|
-
args: {
|
|
3168
|
-
project_id: z5.string().describe("The project ID or URL-encoded path"),
|
|
3169
|
-
sha: z5.string().describe("The commit SHA")
|
|
3170
|
-
},
|
|
3171
|
-
execute: async (args, _ctx) => {
|
|
3172
|
-
const client = getGitLabClient();
|
|
3173
|
-
const discussions = await client.listCommitDiscussions(args.project_id, args.sha);
|
|
3174
|
-
return JSON.stringify(discussions, null, 2);
|
|
3175
|
-
}
|
|
3176
|
-
}),
|
|
3177
|
-
gitlab_get_commit_discussion: tool5({
|
|
3178
|
-
description: `Get a specific discussion thread from a commit with all its replies.
|
|
3179
|
-
Returns the discussion with its 'notes' array containing all comments in the thread.
|
|
3180
|
-
Use this to get the full context of a specific conversation.`,
|
|
3181
|
-
args: {
|
|
3182
|
-
project_id: z5.string().describe("The project ID or URL-encoded path"),
|
|
3183
|
-
sha: z5.string().describe("The commit SHA"),
|
|
3184
|
-
discussion_id: z5.string().describe("The ID of the discussion thread")
|
|
3185
|
-
},
|
|
3186
|
-
execute: async (args, _ctx) => {
|
|
3187
|
-
const client = getGitLabClient();
|
|
3188
|
-
const discussion = await client.getCommitDiscussion(
|
|
3189
|
-
args.project_id,
|
|
3190
|
-
args.sha,
|
|
3191
|
-
args.discussion_id
|
|
3192
|
-
);
|
|
3193
|
-
return JSON.stringify(discussion, null, 2);
|
|
3194
|
-
}
|
|
3195
|
-
}),
|
|
3196
|
-
gitlab_create_commit_note: tool5({
|
|
3197
|
-
description: `Add a comment/note to a commit.
|
|
3198
|
-
If discussion_id is provided, the note will be added as a reply to an existing discussion thread.
|
|
3199
|
-
Optionally, you can create a line-specific comment by providing path, line, and line_type.
|
|
3200
|
-
Use gitlab_list_commit_discussions to find discussion IDs for existing threads.`,
|
|
3201
|
-
args: {
|
|
3202
|
-
project_id: z5.string().describe("The project ID or URL-encoded path"),
|
|
3203
|
-
sha: z5.string().describe("The commit SHA"),
|
|
3204
|
-
body: z5.string().describe("The content of the note/comment (supports Markdown)"),
|
|
3205
|
-
discussion_id: z5.string().optional().describe(
|
|
3206
|
-
"The ID of a discussion thread to reply to. If provided, the note will be added as a reply to that discussion."
|
|
3207
|
-
),
|
|
3208
|
-
path: z5.string().optional().describe("The file path to comment on (for line-specific comments)"),
|
|
3209
|
-
line: z5.number().optional().describe("The line number to comment on (for line-specific comments)"),
|
|
3210
|
-
line_type: z5.enum(["new", "old"]).optional().describe(
|
|
3211
|
-
'The type of line being commented on: "new" for added lines, "old" for removed lines'
|
|
3212
|
-
)
|
|
3213
|
-
},
|
|
3214
|
-
execute: async (args, _ctx) => {
|
|
3215
|
-
const client = getGitLabClient();
|
|
3216
|
-
const note = await client.createCommitNote(args.project_id, args.sha, args.body, {
|
|
3217
|
-
discussion_id: args.discussion_id,
|
|
3218
|
-
path: args.path,
|
|
3219
|
-
line: args.line,
|
|
3220
|
-
line_type: args.line_type
|
|
3221
|
-
});
|
|
3222
|
-
return JSON.stringify(note, null, 2);
|
|
3223
|
-
}
|
|
3224
|
-
}),
|
|
3225
|
-
gitlab_create_commit_discussion: tool5({
|
|
3226
|
-
description: `Start a new discussion thread on a commit.
|
|
3227
|
-
Creates a new discussion with an initial comment. Optionally can be positioned on specific code.
|
|
3228
|
-
For general comments, just provide the body. For code comments, provide position information.`,
|
|
3229
|
-
args: {
|
|
3230
|
-
project_id: z5.string().describe("The project ID or URL-encoded path"),
|
|
3231
|
-
sha: z5.string().describe("The commit SHA"),
|
|
3232
|
-
body: z5.string().describe("The content of the initial comment (supports Markdown)"),
|
|
3233
|
-
position: z5.object({
|
|
3234
|
-
base_sha: z5.string().describe("SHA of the base commit"),
|
|
3235
|
-
start_sha: z5.string().describe("SHA of the start commit"),
|
|
3236
|
-
head_sha: z5.string().describe("SHA of the HEAD commit"),
|
|
3237
|
-
position_type: z5.enum(["text", "image"]).describe("Type of position (text or image)"),
|
|
3238
|
-
new_path: z5.string().optional().describe("Path of the file after changes"),
|
|
3239
|
-
old_path: z5.string().optional().describe("Path of the file before changes"),
|
|
3240
|
-
new_line: z5.number().optional().describe("Line number in the new version"),
|
|
3241
|
-
old_line: z5.number().optional().describe("Line number in the old version")
|
|
3242
|
-
}).optional().describe(
|
|
3243
|
-
"Position information for code comments. Required fields: base_sha, start_sha, head_sha, position_type. For line comments also provide new_path/old_path and new_line/old_line."
|
|
3244
|
-
)
|
|
3245
|
-
},
|
|
3246
|
-
execute: async (args, _ctx) => {
|
|
3247
|
-
const client = getGitLabClient();
|
|
3248
|
-
const discussion = await client.createCommitDiscussion(
|
|
3249
|
-
args.project_id,
|
|
3250
|
-
args.sha,
|
|
3251
|
-
args.body,
|
|
3252
|
-
args.position
|
|
3253
|
-
);
|
|
3254
|
-
return JSON.stringify(discussion, null, 2);
|
|
3255
|
-
}
|
|
3256
|
-
}),
|
|
3257
2827
|
gitlab_get_commit_comments: tool5({
|
|
3258
2828
|
description: `Get all comments on a specific commit.
|
|
3259
2829
|
Returns all comments (notes) that have been added to a commit, including line-specific comments.
|
|
@@ -3269,12 +2839,6 @@ This is different from discussions - it returns individual comments in a flat st
|
|
|
3269
2839
|
}
|
|
3270
2840
|
})
|
|
3271
2841
|
};
|
|
3272
|
-
var commitDiscussionTools = {
|
|
3273
|
-
gitlab_list_commit_discussions: repositoryTools.gitlab_list_commit_discussions,
|
|
3274
|
-
gitlab_get_commit_discussion: repositoryTools.gitlab_get_commit_discussion,
|
|
3275
|
-
gitlab_create_commit_note: repositoryTools.gitlab_create_commit_note,
|
|
3276
|
-
gitlab_create_commit_discussion: repositoryTools.gitlab_create_commit_discussion
|
|
3277
|
-
};
|
|
3278
2842
|
|
|
3279
2843
|
// src/tools/search.ts
|
|
3280
2844
|
import { tool as tool6 } from "@opencode-ai/plugin";
|
|
@@ -3760,48 +3324,6 @@ Requires Developer role or higher.`,
|
|
|
3760
3324
|
import { tool as tool9 } from "@opencode-ai/plugin";
|
|
3761
3325
|
var z9 = tool9.schema;
|
|
3762
3326
|
var snippetTools = {
|
|
3763
|
-
gitlab_list_snippet_discussions: tool9({
|
|
3764
|
-
description: `List discussions (comment threads) on a project snippet.
|
|
3765
|
-
Returns all discussion threads with nested notes. Each discussion contains a 'notes' array with individual comments.
|
|
3766
|
-
Use the discussion 'id' field to reply to a specific thread with gitlab_create_snippet_note.`,
|
|
3767
|
-
args: {
|
|
3768
|
-
project_id: z9.string().describe("The project ID or URL-encoded path"),
|
|
3769
|
-
snippet_id: z9.number().describe("The ID of the snippet"),
|
|
3770
|
-
first: z9.number().optional().describe("Number of discussions to fetch from the beginning (default: 20)"),
|
|
3771
|
-
after: z9.string().optional().describe("Cursor for forward pagination (from pageInfo.endCursor)"),
|
|
3772
|
-
last: z9.number().optional().describe("Number of discussions to fetch from the end"),
|
|
3773
|
-
before: z9.string().optional().describe("Cursor for backward pagination (from pageInfo.startCursor)")
|
|
3774
|
-
},
|
|
3775
|
-
execute: async (args, _ctx) => {
|
|
3776
|
-
const client = getGitLabClient();
|
|
3777
|
-
const discussions = await client.listSnippetDiscussions(args.project_id, args.snippet_id, {
|
|
3778
|
-
first: args.first,
|
|
3779
|
-
after: args.after,
|
|
3780
|
-
last: args.last,
|
|
3781
|
-
before: args.before
|
|
3782
|
-
});
|
|
3783
|
-
return JSON.stringify(discussions, null, 2);
|
|
3784
|
-
}
|
|
3785
|
-
}),
|
|
3786
|
-
gitlab_get_snippet_discussion: tool9({
|
|
3787
|
-
description: `Get a specific discussion thread from a snippet with all its replies.
|
|
3788
|
-
Returns the discussion with its 'notes' array containing all comments in the thread.
|
|
3789
|
-
Use this to get the full context of a specific conversation.`,
|
|
3790
|
-
args: {
|
|
3791
|
-
project_id: z9.string().describe("The project ID or URL-encoded path"),
|
|
3792
|
-
snippet_id: z9.number().describe("The ID of the snippet"),
|
|
3793
|
-
discussion_id: z9.string().describe("The ID of the discussion thread")
|
|
3794
|
-
},
|
|
3795
|
-
execute: async (args, _ctx) => {
|
|
3796
|
-
const client = getGitLabClient();
|
|
3797
|
-
const discussion = await client.getSnippetDiscussion(
|
|
3798
|
-
args.project_id,
|
|
3799
|
-
args.snippet_id,
|
|
3800
|
-
args.discussion_id
|
|
3801
|
-
);
|
|
3802
|
-
return JSON.stringify(discussion, null, 2);
|
|
3803
|
-
}
|
|
3804
|
-
}),
|
|
3805
3327
|
gitlab_list_snippet_notes: tool9({
|
|
3806
3328
|
description: `List all notes/comments on a project snippet using GraphQL API with pagination support.
|
|
3807
3329
|
Returns all comments including system notes in chronological order.
|
|
@@ -3827,47 +3349,6 @@ Use 'before' with the 'startCursor' from pageInfo to get the previous page.`,
|
|
|
3827
3349
|
});
|
|
3828
3350
|
return JSON.stringify(result, null, 2);
|
|
3829
3351
|
}
|
|
3830
|
-
}),
|
|
3831
|
-
gitlab_create_snippet_note: tool9({
|
|
3832
|
-
description: `Add a comment/note to a project snippet.
|
|
3833
|
-
If discussion_id is provided, the note will be added as a reply to an existing discussion thread.
|
|
3834
|
-
Use gitlab_list_snippet_discussions to find discussion IDs for existing threads.`,
|
|
3835
|
-
args: {
|
|
3836
|
-
project_id: z9.string().describe("The project ID or URL-encoded path"),
|
|
3837
|
-
snippet_id: z9.number().describe("The ID of the snippet"),
|
|
3838
|
-
body: z9.string().describe("The content of the note/comment (supports Markdown)"),
|
|
3839
|
-
discussion_id: z9.string().optional().describe(
|
|
3840
|
-
"The ID of a discussion thread to reply to. If provided, the note will be added as a reply to that discussion."
|
|
3841
|
-
)
|
|
3842
|
-
},
|
|
3843
|
-
execute: async (args, _ctx) => {
|
|
3844
|
-
const client = getGitLabClient();
|
|
3845
|
-
const note = await client.createSnippetNote(
|
|
3846
|
-
args.project_id,
|
|
3847
|
-
args.snippet_id,
|
|
3848
|
-
args.body,
|
|
3849
|
-
args.discussion_id
|
|
3850
|
-
);
|
|
3851
|
-
return JSON.stringify(note, null, 2);
|
|
3852
|
-
}
|
|
3853
|
-
}),
|
|
3854
|
-
gitlab_create_snippet_discussion: tool9({
|
|
3855
|
-
description: `Start a new discussion thread on a project snippet.
|
|
3856
|
-
Creates a new discussion with an initial comment.`,
|
|
3857
|
-
args: {
|
|
3858
|
-
project_id: z9.string().describe("The project ID or URL-encoded path"),
|
|
3859
|
-
snippet_id: z9.number().describe("The ID of the snippet"),
|
|
3860
|
-
body: z9.string().describe("The content of the initial comment (supports Markdown)")
|
|
3861
|
-
},
|
|
3862
|
-
execute: async (args, _ctx) => {
|
|
3863
|
-
const client = getGitLabClient();
|
|
3864
|
-
const discussion = await client.createSnippetDiscussion(
|
|
3865
|
-
args.project_id,
|
|
3866
|
-
args.snippet_id,
|
|
3867
|
-
args.body
|
|
3868
|
-
);
|
|
3869
|
-
return JSON.stringify(discussion, null, 2);
|
|
3870
|
-
}
|
|
3871
3352
|
})
|
|
3872
3353
|
};
|
|
3873
3354
|
|
|
@@ -4093,68 +3574,321 @@ Can update title, description, state, labels, and assignees.`,
|
|
|
4093
3574
|
})
|
|
4094
3575
|
};
|
|
4095
3576
|
|
|
4096
|
-
// src/tools/discussions.ts
|
|
3577
|
+
// src/tools/discussions-unified.ts
|
|
4097
3578
|
import { tool as tool13 } from "@opencode-ai/plugin";
|
|
4098
3579
|
var z13 = tool13.schema;
|
|
4099
|
-
var
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
3580
|
+
var positionSchema = z13.object({
|
|
3581
|
+
base_sha: z13.string().describe("SHA of the base commit"),
|
|
3582
|
+
start_sha: z13.string().describe("SHA of the start commit"),
|
|
3583
|
+
head_sha: z13.string().describe("SHA of the head commit"),
|
|
3584
|
+
position_type: z13.enum(["text", "image"]).describe("Type of position"),
|
|
3585
|
+
old_path: z13.string().optional().describe("Path of the file before changes"),
|
|
3586
|
+
new_path: z13.string().optional().describe("Path of the file after changes"),
|
|
3587
|
+
old_line: z13.number().optional().describe("Line number in the old version"),
|
|
3588
|
+
new_line: z13.number().optional().describe("Line number in the new version")
|
|
3589
|
+
});
|
|
3590
|
+
function validateResourceParams(resourceType, args) {
|
|
3591
|
+
switch (resourceType) {
|
|
3592
|
+
case "merge_request":
|
|
3593
|
+
case "issue":
|
|
3594
|
+
if (!args.project_id) throw new Error(`project_id is required for ${resourceType}`);
|
|
3595
|
+
if (args.iid == null) throw new Error(`iid is required for ${resourceType}`);
|
|
3596
|
+
break;
|
|
3597
|
+
case "epic":
|
|
3598
|
+
if (!args.group_id) throw new Error("group_id is required for epic");
|
|
3599
|
+
if (args.iid == null) throw new Error("iid is required for epic");
|
|
3600
|
+
break;
|
|
3601
|
+
case "commit":
|
|
3602
|
+
if (!args.project_id) throw new Error("project_id is required for commit");
|
|
3603
|
+
if (!args.sha) throw new Error("sha is required for commit");
|
|
3604
|
+
break;
|
|
3605
|
+
case "snippet":
|
|
3606
|
+
if (!args.project_id) throw new Error("project_id is required for snippet");
|
|
3607
|
+
if (args.snippet_id == null) throw new Error("snippet_id is required for snippet");
|
|
3608
|
+
break;
|
|
3609
|
+
}
|
|
3610
|
+
}
|
|
3611
|
+
var discussionsUnifiedTools = {
|
|
3612
|
+
/**
|
|
3613
|
+
* List discussions for any GitLab resource type
|
|
3614
|
+
*/
|
|
3615
|
+
gitlab_list_discussions: tool13({
|
|
3616
|
+
description: `List discussions (comment threads) on any GitLab resource.
|
|
3617
|
+
Supports: merge_requests, issues, epics, commits, snippets.
|
|
3618
|
+
|
|
3619
|
+
Returns discussion threads with nested notes. Each discussion contains
|
|
3620
|
+
a 'notes' array with individual comments.
|
|
3621
|
+
|
|
3622
|
+
For pagination, use 'after' with the 'endCursor' from pageInfo to get the next page.
|
|
3623
|
+
|
|
3624
|
+
Examples:
|
|
3625
|
+
- MR: resource_type="merge_request", project_id="group/project", iid=123
|
|
3626
|
+
- Issue: resource_type="issue", project_id="group/project", iid=456
|
|
3627
|
+
- Epic: resource_type="epic", group_id="my-group", iid=1
|
|
3628
|
+
- Commit: resource_type="commit", project_id="group/project", sha="abc123"
|
|
3629
|
+
- Snippet: resource_type="snippet", project_id="group/project", snippet_id=789`,
|
|
4104
3630
|
args: {
|
|
4105
|
-
resource_type: z13.enum(["merge_request", "issue", "epic", "commit", "snippet"]).describe("
|
|
4106
|
-
project_id: z13.string().optional().describe("
|
|
4107
|
-
group_id: z13.string().optional().describe("
|
|
4108
|
-
iid: z13.number().optional().describe("
|
|
4109
|
-
sha: z13.string().optional().describe("
|
|
4110
|
-
snippet_id: z13.number().optional().describe("
|
|
4111
|
-
|
|
4112
|
-
|
|
3631
|
+
resource_type: z13.enum(["merge_request", "issue", "epic", "commit", "snippet"]).describe("Type of GitLab resource"),
|
|
3632
|
+
project_id: z13.string().optional().describe("Project ID or path. Required for merge_request, issue, commit, snippet"),
|
|
3633
|
+
group_id: z13.string().optional().describe("Group ID or path. Required for epic"),
|
|
3634
|
+
iid: z13.number().optional().describe("Internal ID of the resource (for merge_request, issue, epic)"),
|
|
3635
|
+
sha: z13.string().optional().describe("Commit SHA (required for commit)"),
|
|
3636
|
+
snippet_id: z13.number().optional().describe("Snippet ID (required for snippet)"),
|
|
3637
|
+
// Pagination
|
|
3638
|
+
first: z13.number().optional().describe("Number of items to return (default: 20)"),
|
|
3639
|
+
after: z13.string().optional().describe("Cursor for pagination - use endCursor from previous response"),
|
|
3640
|
+
before: z13.string().optional().describe("Cursor for backward pagination"),
|
|
3641
|
+
last: z13.number().optional().describe("Number of items from the end")
|
|
4113
3642
|
},
|
|
4114
3643
|
execute: async (args, _ctx) => {
|
|
3644
|
+
validateResourceParams(args.resource_type, args);
|
|
4115
3645
|
const client = getGitLabClient();
|
|
4116
|
-
const
|
|
4117
|
-
args.
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
3646
|
+
const paginationOptions = {
|
|
3647
|
+
first: args.first,
|
|
3648
|
+
after: args.after,
|
|
3649
|
+
before: args.before,
|
|
3650
|
+
last: args.last
|
|
3651
|
+
};
|
|
3652
|
+
switch (args.resource_type) {
|
|
3653
|
+
case "merge_request":
|
|
3654
|
+
return JSON.stringify(
|
|
3655
|
+
await client.listMrDiscussions(args.project_id, args.iid, paginationOptions),
|
|
3656
|
+
null,
|
|
3657
|
+
2
|
|
3658
|
+
);
|
|
3659
|
+
case "issue":
|
|
3660
|
+
return JSON.stringify(
|
|
3661
|
+
await client.listIssueDiscussions(args.project_id, args.iid, paginationOptions),
|
|
3662
|
+
null,
|
|
3663
|
+
2
|
|
3664
|
+
);
|
|
3665
|
+
case "epic":
|
|
3666
|
+
return JSON.stringify(
|
|
3667
|
+
await client.listEpicDiscussions(args.group_id, args.iid, paginationOptions),
|
|
3668
|
+
null,
|
|
3669
|
+
2
|
|
3670
|
+
);
|
|
3671
|
+
case "commit":
|
|
3672
|
+
return JSON.stringify(
|
|
3673
|
+
await client.listCommitDiscussions(args.project_id, args.sha),
|
|
3674
|
+
null,
|
|
3675
|
+
2
|
|
3676
|
+
);
|
|
3677
|
+
case "snippet":
|
|
3678
|
+
return JSON.stringify(
|
|
3679
|
+
await client.listSnippetDiscussions(
|
|
3680
|
+
args.project_id,
|
|
3681
|
+
args.snippet_id,
|
|
3682
|
+
paginationOptions
|
|
3683
|
+
),
|
|
3684
|
+
null,
|
|
3685
|
+
2
|
|
3686
|
+
);
|
|
3687
|
+
default:
|
|
3688
|
+
throw new Error(`Unsupported resource type: ${args.resource_type}`);
|
|
3689
|
+
}
|
|
4129
3690
|
}
|
|
4130
3691
|
}),
|
|
3692
|
+
/**
|
|
3693
|
+
* Get a specific discussion thread from any GitLab resource
|
|
3694
|
+
*/
|
|
4131
3695
|
gitlab_get_discussion: tool13({
|
|
4132
|
-
description: `
|
|
4133
|
-
|
|
4134
|
-
|
|
3696
|
+
description: `Get a specific discussion thread with all its replies.
|
|
3697
|
+
Returns the discussion with its 'notes' array containing all comments.
|
|
3698
|
+
|
|
3699
|
+
Use this to get full context of a specific conversation.
|
|
3700
|
+
|
|
3701
|
+
Required parameters vary by resource type:
|
|
3702
|
+
- merge_request: project_id, iid, discussion_id
|
|
3703
|
+
- issue: project_id, iid, discussion_id
|
|
3704
|
+
- epic: group_id, iid, discussion_id
|
|
3705
|
+
- commit: project_id, sha, discussion_id
|
|
3706
|
+
- snippet: project_id, snippet_id, discussion_id`,
|
|
4135
3707
|
args: {
|
|
4136
|
-
resource_type: z13.enum(["merge_request", "issue", "epic", "commit", "snippet"]).describe("
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
3708
|
+
resource_type: z13.enum(["merge_request", "issue", "epic", "commit", "snippet"]).describe("Type of GitLab resource"),
|
|
3709
|
+
discussion_id: z13.string().describe("The ID of the discussion thread"),
|
|
3710
|
+
project_id: z13.string().optional().describe("Project ID or path"),
|
|
3711
|
+
group_id: z13.string().optional().describe("Group ID or path (for epic)"),
|
|
3712
|
+
iid: z13.number().optional().describe("Internal ID (for merge_request, issue, epic)"),
|
|
3713
|
+
sha: z13.string().optional().describe("Commit SHA (for commit)"),
|
|
3714
|
+
snippet_id: z13.number().optional().describe("Snippet ID (for snippet)")
|
|
4143
3715
|
},
|
|
4144
3716
|
execute: async (args, _ctx) => {
|
|
3717
|
+
validateResourceParams(args.resource_type, args);
|
|
4145
3718
|
const client = getGitLabClient();
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
3719
|
+
switch (args.resource_type) {
|
|
3720
|
+
case "merge_request":
|
|
3721
|
+
return JSON.stringify(
|
|
3722
|
+
await client.getMrDiscussion(args.project_id, args.iid, args.discussion_id),
|
|
3723
|
+
null,
|
|
3724
|
+
2
|
|
3725
|
+
);
|
|
3726
|
+
case "issue":
|
|
3727
|
+
return JSON.stringify(
|
|
3728
|
+
await client.getIssueDiscussion(args.project_id, args.iid, args.discussion_id),
|
|
3729
|
+
null,
|
|
3730
|
+
2
|
|
3731
|
+
);
|
|
3732
|
+
case "epic":
|
|
3733
|
+
return JSON.stringify(
|
|
3734
|
+
await client.getEpicDiscussion(args.group_id, args.iid, args.discussion_id),
|
|
3735
|
+
null,
|
|
3736
|
+
2
|
|
3737
|
+
);
|
|
3738
|
+
case "commit":
|
|
3739
|
+
return JSON.stringify(
|
|
3740
|
+
await client.getCommitDiscussion(args.project_id, args.sha, args.discussion_id),
|
|
3741
|
+
null,
|
|
3742
|
+
2
|
|
3743
|
+
);
|
|
3744
|
+
case "snippet":
|
|
3745
|
+
return JSON.stringify(
|
|
3746
|
+
await client.getSnippetDiscussion(
|
|
3747
|
+
args.project_id,
|
|
3748
|
+
args.snippet_id,
|
|
3749
|
+
args.discussion_id
|
|
3750
|
+
),
|
|
3751
|
+
null,
|
|
3752
|
+
2
|
|
3753
|
+
);
|
|
3754
|
+
default:
|
|
3755
|
+
throw new Error(`Unsupported resource type: ${args.resource_type}`);
|
|
3756
|
+
}
|
|
3757
|
+
}
|
|
3758
|
+
}),
|
|
3759
|
+
/**
|
|
3760
|
+
* Create a new discussion thread or reply to an existing one
|
|
3761
|
+
*/
|
|
3762
|
+
gitlab_create_discussion: tool13({
|
|
3763
|
+
description: `Create a new discussion thread or reply to an existing one.
|
|
3764
|
+
|
|
3765
|
+
For NEW discussion: Omit discussion_id
|
|
3766
|
+
For REPLY to existing thread: Include discussion_id (preferred over gitlab_create_note for threaded conversations)
|
|
3767
|
+
|
|
3768
|
+
For code-specific comments on MRs/commits, provide position information.
|
|
3769
|
+
|
|
3770
|
+
Examples:
|
|
3771
|
+
- New MR comment: resource_type="merge_request", project_id="...", iid=123, body="..."
|
|
3772
|
+
- Reply to thread: resource_type="merge_request", ..., discussion_id="...", body="..."
|
|
3773
|
+
- Code comment: resource_type="merge_request", ..., body="...", position={base_sha, head_sha, ...}`,
|
|
3774
|
+
args: {
|
|
3775
|
+
resource_type: z13.enum(["merge_request", "issue", "epic", "commit", "snippet"]).describe("Type of GitLab resource"),
|
|
3776
|
+
body: z13.string().describe("The comment text (Markdown supported)"),
|
|
3777
|
+
project_id: z13.string().optional().describe("Project ID or path"),
|
|
3778
|
+
group_id: z13.string().optional().describe("Group ID or path (for epic)"),
|
|
3779
|
+
iid: z13.number().optional().describe("Internal ID (for merge_request, issue, epic)"),
|
|
3780
|
+
sha: z13.string().optional().describe("Commit SHA (for commit)"),
|
|
3781
|
+
snippet_id: z13.number().optional().describe("Snippet ID (for snippet)"),
|
|
3782
|
+
discussion_id: z13.string().optional().describe("If provided, replies to existing discussion. If omitted, creates new thread"),
|
|
3783
|
+
position: positionSchema.optional().describe("Position for code-specific comments (MR/commit only)")
|
|
3784
|
+
},
|
|
3785
|
+
execute: async (args, _ctx) => {
|
|
3786
|
+
validateResourceParams(args.resource_type, args);
|
|
3787
|
+
const client = getGitLabClient();
|
|
3788
|
+
if (args.discussion_id) {
|
|
3789
|
+
const note = await client.replyToDiscussion(
|
|
3790
|
+
args.resource_type,
|
|
3791
|
+
{
|
|
3792
|
+
projectId: args.project_id,
|
|
3793
|
+
groupId: args.group_id,
|
|
3794
|
+
iid: args.iid,
|
|
3795
|
+
sha: args.sha,
|
|
3796
|
+
snippetId: args.snippet_id
|
|
3797
|
+
},
|
|
3798
|
+
args.discussion_id,
|
|
3799
|
+
args.body
|
|
3800
|
+
);
|
|
3801
|
+
return JSON.stringify(note, null, 2);
|
|
3802
|
+
}
|
|
3803
|
+
switch (args.resource_type) {
|
|
3804
|
+
case "merge_request":
|
|
3805
|
+
return JSON.stringify(
|
|
3806
|
+
await client.createMrDiscussion(args.project_id, args.iid, args.body, args.position),
|
|
3807
|
+
null,
|
|
3808
|
+
2
|
|
3809
|
+
);
|
|
3810
|
+
case "issue":
|
|
3811
|
+
return JSON.stringify(
|
|
3812
|
+
await client.createIssueNote(args.project_id, args.iid, args.body),
|
|
3813
|
+
null,
|
|
3814
|
+
2
|
|
3815
|
+
);
|
|
3816
|
+
case "epic":
|
|
3817
|
+
return JSON.stringify(
|
|
3818
|
+
await client.createEpicNote(args.group_id, args.iid, args.body),
|
|
3819
|
+
null,
|
|
3820
|
+
2
|
|
3821
|
+
);
|
|
3822
|
+
case "commit":
|
|
3823
|
+
return JSON.stringify(
|
|
3824
|
+
await client.createCommitDiscussion(
|
|
3825
|
+
args.project_id,
|
|
3826
|
+
args.sha,
|
|
3827
|
+
args.body,
|
|
3828
|
+
args.position
|
|
3829
|
+
),
|
|
3830
|
+
null,
|
|
3831
|
+
2
|
|
3832
|
+
);
|
|
3833
|
+
case "snippet":
|
|
3834
|
+
return JSON.stringify(
|
|
3835
|
+
await client.createSnippetDiscussion(args.project_id, args.snippet_id, args.body),
|
|
3836
|
+
null,
|
|
3837
|
+
2
|
|
3838
|
+
);
|
|
3839
|
+
default:
|
|
3840
|
+
throw new Error(`Unsupported resource type: ${args.resource_type}`);
|
|
3841
|
+
}
|
|
3842
|
+
}
|
|
3843
|
+
}),
|
|
3844
|
+
/**
|
|
3845
|
+
* Resolve or unresolve a discussion thread
|
|
3846
|
+
*/
|
|
3847
|
+
gitlab_resolve_discussion: tool13({
|
|
3848
|
+
description: `Mark a discussion thread as resolved or unresolve it.
|
|
3849
|
+
Only works for resolvable discussions (MRs and issues only).
|
|
3850
|
+
|
|
3851
|
+
Use after addressing feedback to indicate the discussion is complete.`,
|
|
3852
|
+
args: {
|
|
3853
|
+
resource_type: z13.enum(["merge_request", "issue"]).describe("Type of resource (only MR and issue discussions can be resolved)"),
|
|
3854
|
+
action: z13.enum(["resolve", "unresolve"]).describe("Whether to resolve or unresolve"),
|
|
3855
|
+
discussion_id: z13.string().describe("The ID of the discussion thread"),
|
|
3856
|
+
project_id: z13.string().describe("Project ID or path"),
|
|
3857
|
+
iid: z13.number().describe("Internal ID of the MR or issue")
|
|
3858
|
+
},
|
|
3859
|
+
execute: async (args, _ctx) => {
|
|
3860
|
+
const client = getGitLabClient();
|
|
3861
|
+
if (args.action === "resolve") {
|
|
3862
|
+
switch (args.resource_type) {
|
|
3863
|
+
case "merge_request":
|
|
3864
|
+
return JSON.stringify(
|
|
3865
|
+
await client.resolveMrDiscussion(args.project_id, args.iid, args.discussion_id),
|
|
3866
|
+
null,
|
|
3867
|
+
2
|
|
3868
|
+
);
|
|
3869
|
+
case "issue":
|
|
3870
|
+
return JSON.stringify(
|
|
3871
|
+
await client.resolveIssueDiscussion(args.project_id, args.iid, args.discussion_id),
|
|
3872
|
+
null,
|
|
3873
|
+
2
|
|
3874
|
+
);
|
|
3875
|
+
}
|
|
3876
|
+
} else {
|
|
3877
|
+
switch (args.resource_type) {
|
|
3878
|
+
case "merge_request":
|
|
3879
|
+
return JSON.stringify(
|
|
3880
|
+
await client.unresolveMrDiscussion(args.project_id, args.iid, args.discussion_id),
|
|
3881
|
+
null,
|
|
3882
|
+
2
|
|
3883
|
+
);
|
|
3884
|
+
case "issue":
|
|
3885
|
+
return JSON.stringify(
|
|
3886
|
+
await client.unresolveIssueDiscussion(args.project_id, args.iid, args.discussion_id),
|
|
3887
|
+
null,
|
|
3888
|
+
2
|
|
3889
|
+
);
|
|
3890
|
+
}
|
|
3891
|
+
}
|
|
4158
3892
|
}
|
|
4159
3893
|
})
|
|
4160
3894
|
};
|
|
@@ -4523,10 +4257,8 @@ var gitlabPlugin = async (_input) => {
|
|
|
4523
4257
|
...wikiTools,
|
|
4524
4258
|
// Work Item Tools
|
|
4525
4259
|
...workItemTools,
|
|
4526
|
-
//
|
|
4527
|
-
...
|
|
4528
|
-
// Universal Discussion Tools
|
|
4529
|
-
...discussionTools,
|
|
4260
|
+
// Unified Discussion Tools (covers MR, issue, epic, commit, snippet discussions)
|
|
4261
|
+
...discussionsUnifiedTools,
|
|
4530
4262
|
// Git Tools
|
|
4531
4263
|
...gitTools,
|
|
4532
4264
|
// Audit Tools
|