@gitlab/opencode-gitlab-plugin 1.1.0 → 1.3.0
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
CHANGED
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [1.3.0](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin/compare/v1.2.0...v1.3.0) (2026-01-30)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### ✨ Features
|
|
9
|
+
|
|
10
|
+
* **notes:** migrate notes listing to GraphQL API with pagination support ([2ec5d65](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin/commit/2ec5d6528b27b86a08f5c747f38762f90eb1f297))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### 🐛 Bug Fixes
|
|
14
|
+
|
|
15
|
+
* address review feedback for notes GraphQL migration ([fcb1a35](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin/commit/fcb1a355f3ecbddf2429b0e2fecaeb1f02d29ffe))
|
|
16
|
+
|
|
17
|
+
## [1.2.0](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin/compare/v1.1.0...v1.2.0) (2026-01-29)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### ✨ Features
|
|
21
|
+
|
|
22
|
+
* **merge-requests:** add auto-merge (MWPS) tool using GraphQL API ([2bb3a21](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin/commit/2bb3a2123058616cd27003f885ad4d4082e4b3a0))
|
|
23
|
+
|
|
5
24
|
## [1.1.0](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin/compare/v1.0.6...v1.1.0) (2026-01-13)
|
|
6
25
|
|
|
7
26
|
|
|
Binary file
|
package/dist/index.js
CHANGED
|
@@ -82,7 +82,110 @@ var GitLabApiClient = class {
|
|
|
82
82
|
}
|
|
83
83
|
};
|
|
84
84
|
|
|
85
|
+
// src/client/notes-types.ts
|
|
86
|
+
function buildPaginationVariables(options) {
|
|
87
|
+
const variables = {};
|
|
88
|
+
if (options?.first !== void 0) {
|
|
89
|
+
variables.first = options.first;
|
|
90
|
+
} else if (options?.last == null) {
|
|
91
|
+
variables.first = 20;
|
|
92
|
+
}
|
|
93
|
+
if (options?.after) variables.after = options.after;
|
|
94
|
+
if (options?.last !== void 0) variables.last = options.last;
|
|
95
|
+
if (options?.before) variables.before = options.before;
|
|
96
|
+
if (options?.filter) variables.filter = options.filter;
|
|
97
|
+
return variables;
|
|
98
|
+
}
|
|
99
|
+
var NOTES_FRAGMENT = `
|
|
100
|
+
fragment NoteFields on Note {
|
|
101
|
+
id
|
|
102
|
+
body
|
|
103
|
+
bodyHtml
|
|
104
|
+
createdAt
|
|
105
|
+
updatedAt
|
|
106
|
+
system
|
|
107
|
+
internal
|
|
108
|
+
resolvable
|
|
109
|
+
resolved
|
|
110
|
+
resolvedAt
|
|
111
|
+
url
|
|
112
|
+
author {
|
|
113
|
+
id
|
|
114
|
+
username
|
|
115
|
+
name
|
|
116
|
+
avatarUrl
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
`;
|
|
120
|
+
var NOTES_CONNECTION_FRAGMENT = `
|
|
121
|
+
fragment NotesConnectionFields on NoteConnection {
|
|
122
|
+
count
|
|
123
|
+
pageInfo {
|
|
124
|
+
hasNextPage
|
|
125
|
+
hasPreviousPage
|
|
126
|
+
startCursor
|
|
127
|
+
endCursor
|
|
128
|
+
}
|
|
129
|
+
nodes {
|
|
130
|
+
...NoteFields
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
`;
|
|
134
|
+
|
|
85
135
|
// src/client/merge-requests.ts
|
|
136
|
+
var LIST_MR_NOTES_QUERY = `
|
|
137
|
+
${NOTES_FRAGMENT}
|
|
138
|
+
${NOTES_CONNECTION_FRAGMENT}
|
|
139
|
+
query listMrNotes(
|
|
140
|
+
$projectPath: ID!
|
|
141
|
+
$mrIid: String!
|
|
142
|
+
$first: Int
|
|
143
|
+
$after: String
|
|
144
|
+
$last: Int
|
|
145
|
+
$before: String
|
|
146
|
+
$filter: WorkItemNotesFilterType
|
|
147
|
+
) {
|
|
148
|
+
project(fullPath: $projectPath) {
|
|
149
|
+
mergeRequest(iid: $mrIid) {
|
|
150
|
+
notes(
|
|
151
|
+
first: $first
|
|
152
|
+
after: $after
|
|
153
|
+
last: $last
|
|
154
|
+
before: $before
|
|
155
|
+
filter: $filter
|
|
156
|
+
) {
|
|
157
|
+
...NotesConnectionFields
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
`;
|
|
163
|
+
var SET_AUTO_MERGE_MUTATION = `
|
|
164
|
+
mutation setAutoMerge(
|
|
165
|
+
$projectPath: ID!
|
|
166
|
+
$iid: String!
|
|
167
|
+
$sha: String!
|
|
168
|
+
$strategy: MergeStrategyEnum
|
|
169
|
+
) {
|
|
170
|
+
mergeRequestAccept(
|
|
171
|
+
input: {
|
|
172
|
+
projectPath: $projectPath
|
|
173
|
+
iid: $iid
|
|
174
|
+
sha: $sha
|
|
175
|
+
strategy: $strategy
|
|
176
|
+
}
|
|
177
|
+
) {
|
|
178
|
+
mergeRequest {
|
|
179
|
+
id
|
|
180
|
+
iid
|
|
181
|
+
title
|
|
182
|
+
autoMergeEnabled
|
|
183
|
+
autoMergeStrategy
|
|
184
|
+
}
|
|
185
|
+
errors
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
`;
|
|
86
189
|
var MergeRequestsClient = class extends GitLabApiClient {
|
|
87
190
|
async getMergeRequest(projectId, mrIid, includeChanges) {
|
|
88
191
|
const encodedProject = this.encodeProjectId(projectId);
|
|
@@ -157,12 +260,25 @@ var MergeRequestsClient = class extends GitLabApiClient {
|
|
|
157
260
|
requestBody
|
|
158
261
|
);
|
|
159
262
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
263
|
+
/**
|
|
264
|
+
* List notes on a merge request using GraphQL API with pagination support
|
|
265
|
+
*/
|
|
266
|
+
async listMrNotes(projectId, mrIid, options) {
|
|
267
|
+
const variables = {
|
|
268
|
+
projectPath: projectId,
|
|
269
|
+
mrIid: String(mrIid),
|
|
270
|
+
...buildPaginationVariables(options)
|
|
271
|
+
};
|
|
272
|
+
const result = await this.fetchGraphQL(LIST_MR_NOTES_QUERY, variables);
|
|
273
|
+
const notes = result.project?.mergeRequest?.notes;
|
|
274
|
+
if (!notes) {
|
|
275
|
+
throw new Error("Merge request not found or access denied");
|
|
276
|
+
}
|
|
277
|
+
return {
|
|
278
|
+
notes,
|
|
279
|
+
pageInfo: notes.pageInfo,
|
|
280
|
+
totalCount: notes.count
|
|
281
|
+
};
|
|
166
282
|
}
|
|
167
283
|
async createMrNote(projectId, mrIid, body, discussionId) {
|
|
168
284
|
const encodedProject = this.encodeProjectId(projectId);
|
|
@@ -209,10 +325,6 @@ var MergeRequestsClient = class extends GitLabApiClient {
|
|
|
209
325
|
`/projects/${encodedProject}/merge_requests/${mrIid}/pipelines`
|
|
210
326
|
);
|
|
211
327
|
}
|
|
212
|
-
/**
|
|
213
|
-
* List merge request diffs with pagination support
|
|
214
|
-
* API: GET /projects/:id/merge_requests/:merge_request_iid/diffs
|
|
215
|
-
*/
|
|
216
328
|
async listMergeRequestDiffs(projectId, mrIid, options = {}) {
|
|
217
329
|
const encodedProject = this.encodeProjectId(projectId);
|
|
218
330
|
const params = new URLSearchParams();
|
|
@@ -222,9 +334,55 @@ var MergeRequestsClient = class extends GitLabApiClient {
|
|
|
222
334
|
const path2 = `/projects/${encodedProject}/merge_requests/${mrIid}/diffs${query ? `?${query}` : ""}`;
|
|
223
335
|
return this.fetch("GET", path2);
|
|
224
336
|
}
|
|
337
|
+
/**
|
|
338
|
+
* Set auto-merge (MWPS) on a merge request using GraphQL API
|
|
339
|
+
* Uses the mergeRequestAccept mutation with a merge strategy
|
|
340
|
+
*/
|
|
341
|
+
async setAutoMerge(projectId, mrIid, sha, strategy = "MERGE_WHEN_CHECKS_PASS") {
|
|
342
|
+
const result = await this.fetchGraphQL(SET_AUTO_MERGE_MUTATION, {
|
|
343
|
+
projectPath: projectId,
|
|
344
|
+
iid: String(mrIid),
|
|
345
|
+
sha,
|
|
346
|
+
strategy
|
|
347
|
+
});
|
|
348
|
+
if (result.mergeRequestAccept.errors.length > 0) {
|
|
349
|
+
throw new Error(`Failed to set auto-merge: ${result.mergeRequestAccept.errors.join(", ")}`);
|
|
350
|
+
}
|
|
351
|
+
if (!result.mergeRequestAccept.mergeRequest) {
|
|
352
|
+
throw new Error("Failed to set auto-merge: No merge request returned");
|
|
353
|
+
}
|
|
354
|
+
return result.mergeRequestAccept.mergeRequest;
|
|
355
|
+
}
|
|
225
356
|
};
|
|
226
357
|
|
|
227
358
|
// src/client/issues.ts
|
|
359
|
+
var LIST_ISSUE_NOTES_QUERY = `
|
|
360
|
+
${NOTES_FRAGMENT}
|
|
361
|
+
${NOTES_CONNECTION_FRAGMENT}
|
|
362
|
+
query listIssueNotes(
|
|
363
|
+
$projectPath: ID!
|
|
364
|
+
$issueIid: String!
|
|
365
|
+
$first: Int
|
|
366
|
+
$after: String
|
|
367
|
+
$last: Int
|
|
368
|
+
$before: String
|
|
369
|
+
$filter: WorkItemNotesFilterType
|
|
370
|
+
) {
|
|
371
|
+
project(fullPath: $projectPath) {
|
|
372
|
+
issue(iid: $issueIid) {
|
|
373
|
+
notes(
|
|
374
|
+
first: $first
|
|
375
|
+
after: $after
|
|
376
|
+
last: $last
|
|
377
|
+
before: $before
|
|
378
|
+
filter: $filter
|
|
379
|
+
) {
|
|
380
|
+
...NotesConnectionFields
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
`;
|
|
228
386
|
var IssuesClient = class extends GitLabApiClient {
|
|
229
387
|
async createIssue(projectId, title, options) {
|
|
230
388
|
const encodedProject = this.encodeProjectId(projectId);
|
|
@@ -260,12 +418,25 @@ var IssuesClient = class extends GitLabApiClient {
|
|
|
260
418
|
}
|
|
261
419
|
return this.fetch("GET", path2);
|
|
262
420
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
421
|
+
/**
|
|
422
|
+
* List notes on an issue using GraphQL API with pagination support
|
|
423
|
+
*/
|
|
424
|
+
async listIssueNotes(projectId, issueIid, options) {
|
|
425
|
+
const variables = {
|
|
426
|
+
projectPath: projectId,
|
|
427
|
+
issueIid: String(issueIid),
|
|
428
|
+
...buildPaginationVariables(options)
|
|
429
|
+
};
|
|
430
|
+
const result = await this.fetchGraphQL(LIST_ISSUE_NOTES_QUERY, variables);
|
|
431
|
+
const notes = result.project?.issue?.notes;
|
|
432
|
+
if (!notes) {
|
|
433
|
+
throw new Error("Issue not found or access denied");
|
|
434
|
+
}
|
|
435
|
+
return {
|
|
436
|
+
notes,
|
|
437
|
+
pageInfo: notes.pageInfo,
|
|
438
|
+
totalCount: notes.count
|
|
439
|
+
};
|
|
269
440
|
}
|
|
270
441
|
async listIssueDiscussions(projectId, issueIid) {
|
|
271
442
|
const encodedProject = this.encodeProjectId(projectId);
|
|
@@ -312,10 +483,6 @@ var IssuesClient = class extends GitLabApiClient {
|
|
|
312
483
|
{ resolved: false }
|
|
313
484
|
);
|
|
314
485
|
}
|
|
315
|
-
/**
|
|
316
|
-
* Get a single note from an issue
|
|
317
|
-
* API: GET /projects/:id/issues/:issue_iid/notes/:note_id
|
|
318
|
-
*/
|
|
319
486
|
async getIssueNote(projectId, issueIid, noteId) {
|
|
320
487
|
const encodedProject = this.encodeProjectId(projectId);
|
|
321
488
|
return this.fetch(
|
|
@@ -1066,6 +1233,31 @@ var TodosClient = class extends GitLabApiClient {
|
|
|
1066
1233
|
};
|
|
1067
1234
|
|
|
1068
1235
|
// src/client/epics.ts
|
|
1236
|
+
var LIST_EPIC_NOTES_QUERY = `
|
|
1237
|
+
${NOTES_FRAGMENT}
|
|
1238
|
+
${NOTES_CONNECTION_FRAGMENT}
|
|
1239
|
+
query listEpicNotes(
|
|
1240
|
+
$groupPath: ID!
|
|
1241
|
+
$epicIid: ID!
|
|
1242
|
+
$first: Int
|
|
1243
|
+
$after: String
|
|
1244
|
+
$last: Int
|
|
1245
|
+
$before: String
|
|
1246
|
+
) {
|
|
1247
|
+
group(fullPath: $groupPath) {
|
|
1248
|
+
epic(iid: $epicIid) {
|
|
1249
|
+
notes(
|
|
1250
|
+
first: $first
|
|
1251
|
+
after: $after
|
|
1252
|
+
last: $last
|
|
1253
|
+
before: $before
|
|
1254
|
+
) {
|
|
1255
|
+
...NotesConnectionFields
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
`;
|
|
1069
1261
|
var EpicsClient = class extends GitLabApiClient {
|
|
1070
1262
|
async getEpic(groupId, epicIid) {
|
|
1071
1263
|
const encodedGroup = encodeURIComponent(groupId);
|
|
@@ -1114,12 +1306,25 @@ var EpicsClient = class extends GitLabApiClient {
|
|
|
1114
1306
|
`/groups/${encodedGroup}/epics/${epicIid}/issues/${epicIssueId}`
|
|
1115
1307
|
);
|
|
1116
1308
|
}
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1309
|
+
/**
|
|
1310
|
+
* List notes on an epic using GraphQL API with pagination support
|
|
1311
|
+
*/
|
|
1312
|
+
async listEpicNotes(groupId, epicIid, options) {
|
|
1313
|
+
const variables = {
|
|
1314
|
+
groupPath: groupId,
|
|
1315
|
+
epicIid: String(epicIid),
|
|
1316
|
+
...buildPaginationVariables(options)
|
|
1317
|
+
};
|
|
1318
|
+
const result = await this.fetchGraphQL(LIST_EPIC_NOTES_QUERY, variables);
|
|
1319
|
+
const notes = result.group?.epic?.notes;
|
|
1320
|
+
if (!notes) {
|
|
1321
|
+
throw new Error("Epic not found or access denied");
|
|
1322
|
+
}
|
|
1323
|
+
return {
|
|
1324
|
+
notes,
|
|
1325
|
+
pageInfo: notes.pageInfo,
|
|
1326
|
+
totalCount: notes.count
|
|
1327
|
+
};
|
|
1123
1328
|
}
|
|
1124
1329
|
async listEpicDiscussions(groupId, epicIid) {
|
|
1125
1330
|
const encodedGroup = encodeURIComponent(groupId);
|
|
@@ -1150,10 +1355,6 @@ var EpicsClient = class extends GitLabApiClient {
|
|
|
1150
1355
|
{ body }
|
|
1151
1356
|
);
|
|
1152
1357
|
}
|
|
1153
|
-
/**
|
|
1154
|
-
* Get a single note from an epic
|
|
1155
|
-
* API: GET /groups/:id/epics/:epic_iid/notes/:note_id
|
|
1156
|
-
*/
|
|
1157
1358
|
async getEpicNote(groupId, epicIid, noteId) {
|
|
1158
1359
|
const encodedGroup = encodeURIComponent(groupId);
|
|
1159
1360
|
return this.fetch(
|
|
@@ -1164,6 +1365,30 @@ var EpicsClient = class extends GitLabApiClient {
|
|
|
1164
1365
|
};
|
|
1165
1366
|
|
|
1166
1367
|
// src/client/snippets.ts
|
|
1368
|
+
var LIST_SNIPPET_NOTES_QUERY = `
|
|
1369
|
+
${NOTES_FRAGMENT}
|
|
1370
|
+
${NOTES_CONNECTION_FRAGMENT}
|
|
1371
|
+
query listSnippetNotes(
|
|
1372
|
+
$snippetGid: SnippetID!
|
|
1373
|
+
$first: Int
|
|
1374
|
+
$after: String
|
|
1375
|
+
$last: Int
|
|
1376
|
+
$before: String
|
|
1377
|
+
) {
|
|
1378
|
+
snippets(ids: [$snippetGid]) {
|
|
1379
|
+
nodes {
|
|
1380
|
+
notes(
|
|
1381
|
+
first: $first
|
|
1382
|
+
after: $after
|
|
1383
|
+
last: $last
|
|
1384
|
+
before: $before
|
|
1385
|
+
) {
|
|
1386
|
+
...NotesConnectionFields
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
`;
|
|
1167
1392
|
var SnippetsClient = class extends GitLabApiClient {
|
|
1168
1393
|
async listSnippetDiscussions(projectId, snippetId) {
|
|
1169
1394
|
const encodedProject = this.encodeProjectId(projectId);
|
|
@@ -1179,12 +1404,30 @@ var SnippetsClient = class extends GitLabApiClient {
|
|
|
1179
1404
|
`/projects/${encodedProject}/snippets/${snippetId}/discussions/${discussionId}`
|
|
1180
1405
|
);
|
|
1181
1406
|
}
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1407
|
+
/**
|
|
1408
|
+
* List notes on a snippet using GraphQL API with pagination support
|
|
1409
|
+
*/
|
|
1410
|
+
async listSnippetNotes(projectId, snippetId, options) {
|
|
1411
|
+
const variables = {
|
|
1412
|
+
snippetGid: `gid://gitlab/ProjectSnippet/${snippetId}`,
|
|
1413
|
+
...buildPaginationVariables(options)
|
|
1414
|
+
};
|
|
1415
|
+
const result = await this.fetchGraphQL(LIST_SNIPPET_NOTES_QUERY, variables);
|
|
1416
|
+
const notes = result.snippets.nodes[0]?.notes || {
|
|
1417
|
+
nodes: [],
|
|
1418
|
+
pageInfo: {
|
|
1419
|
+
hasNextPage: false,
|
|
1420
|
+
hasPreviousPage: false,
|
|
1421
|
+
startCursor: null,
|
|
1422
|
+
endCursor: null
|
|
1423
|
+
},
|
|
1424
|
+
count: 0
|
|
1425
|
+
};
|
|
1426
|
+
return {
|
|
1427
|
+
notes,
|
|
1428
|
+
pageInfo: notes.pageInfo,
|
|
1429
|
+
totalCount: notes.count
|
|
1430
|
+
};
|
|
1188
1431
|
}
|
|
1189
1432
|
async createSnippetNote(projectId, snippetId, body, discussionId) {
|
|
1190
1433
|
const encodedProject = this.encodeProjectId(projectId);
|
|
@@ -1538,17 +1781,32 @@ Note: For a flattened list of all comments, use gitlab_list_mr_notes instead.`,
|
|
|
1538
1781
|
}
|
|
1539
1782
|
}),
|
|
1540
1783
|
gitlab_list_mr_notes: tool({
|
|
1541
|
-
description: `List all notes/comments on a merge request
|
|
1784
|
+
description: `List all notes/comments on a merge request using GraphQL API with pagination support.
|
|
1542
1785
|
Returns all comments including system notes, code review comments, and general discussion.
|
|
1543
|
-
This is easier to read than discussions which have nested structure
|
|
1786
|
+
This is easier to read than discussions which have nested structure.
|
|
1787
|
+
|
|
1788
|
+
The response includes pagination information (pageInfo) with cursors for fetching additional pages.
|
|
1789
|
+
Use 'after' with the 'endCursor' from pageInfo to get the next page.
|
|
1790
|
+
Use 'before' with the 'startCursor' from pageInfo to get the previous page.`,
|
|
1544
1791
|
args: {
|
|
1545
1792
|
project_id: z.string().describe("The project ID or URL-encoded path"),
|
|
1546
|
-
mr_iid: z.number().describe("The internal ID of the merge request")
|
|
1793
|
+
mr_iid: z.number().describe("The internal ID of the merge request"),
|
|
1794
|
+
first: z.number().optional().describe("Number of items to return from the beginning (default: 20, max: 100)"),
|
|
1795
|
+
after: z.string().optional().describe("Cursor for forward pagination - use endCursor from previous response"),
|
|
1796
|
+
last: z.number().optional().describe("Number of items to return from the end (for backward pagination)"),
|
|
1797
|
+
before: z.string().optional().describe("Cursor for backward pagination - use startCursor from previous response"),
|
|
1798
|
+
filter: z.enum(["ALL_NOTES", "ONLY_COMMENTS", "ONLY_ACTIVITY"]).optional().describe("Filter notes by type: ALL_NOTES (default), ONLY_COMMENTS, or ONLY_ACTIVITY")
|
|
1547
1799
|
},
|
|
1548
1800
|
execute: async (args, _ctx) => {
|
|
1549
1801
|
const client = getGitLabClient();
|
|
1550
|
-
const
|
|
1551
|
-
|
|
1802
|
+
const result = await client.listMrNotes(args.project_id, args.mr_iid, {
|
|
1803
|
+
first: args.first,
|
|
1804
|
+
after: args.after,
|
|
1805
|
+
last: args.last,
|
|
1806
|
+
before: args.before,
|
|
1807
|
+
filter: args.filter
|
|
1808
|
+
});
|
|
1809
|
+
return JSON.stringify(result, null, 2);
|
|
1552
1810
|
}
|
|
1553
1811
|
}),
|
|
1554
1812
|
gitlab_create_mr_note: tool({
|
|
@@ -1775,6 +2033,33 @@ This is useful when you need to process diffs in chunks or when the MR has many
|
|
|
1775
2033
|
});
|
|
1776
2034
|
return JSON.stringify(diffs, null, 2);
|
|
1777
2035
|
}
|
|
2036
|
+
}),
|
|
2037
|
+
gitlab_set_mr_auto_merge: tool({
|
|
2038
|
+
description: `Enable auto-merge (MWPS - Merge When Pipeline Succeeds) on a merge request.
|
|
2039
|
+
Uses the GitLab GraphQL API mergeRequestAccept mutation with a merge strategy.
|
|
2040
|
+
The MR will be automatically merged when all required conditions are met.
|
|
2041
|
+
Requires the MR to be approved and have a passing pipeline (depending on project settings).
|
|
2042
|
+
Note: You must provide the current HEAD SHA of the MR to prevent race conditions.`,
|
|
2043
|
+
args: {
|
|
2044
|
+
project_id: z.string().describe('The project ID or path (e.g., "gitlab-org/gitlab")'),
|
|
2045
|
+
mr_iid: z.number().describe("The internal ID of the merge request"),
|
|
2046
|
+
sha: z.string().describe(
|
|
2047
|
+
"The HEAD SHA of the merge request. Get this from the MR details (diff_refs.head_sha or sha field)."
|
|
2048
|
+
),
|
|
2049
|
+
strategy: z.enum(["MERGE_WHEN_CHECKS_PASS", "ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS"]).optional().describe(
|
|
2050
|
+
"Auto-merge strategy. MERGE_WHEN_CHECKS_PASS (default) waits for all checks including approvals. ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS adds to merge train when checks pass."
|
|
2051
|
+
)
|
|
2052
|
+
},
|
|
2053
|
+
execute: async (args, _ctx) => {
|
|
2054
|
+
const client = getGitLabClient();
|
|
2055
|
+
const result = await client.setAutoMerge(
|
|
2056
|
+
args.project_id,
|
|
2057
|
+
args.mr_iid,
|
|
2058
|
+
args.sha,
|
|
2059
|
+
args.strategy || "MERGE_WHEN_CHECKS_PASS"
|
|
2060
|
+
);
|
|
2061
|
+
return JSON.stringify(result, null, 2);
|
|
2062
|
+
}
|
|
1778
2063
|
})
|
|
1779
2064
|
};
|
|
1780
2065
|
|
|
@@ -1854,16 +2139,31 @@ Can filter by state, labels, assignee, milestone.`,
|
|
|
1854
2139
|
}
|
|
1855
2140
|
}),
|
|
1856
2141
|
gitlab_list_issue_notes: tool2({
|
|
1857
|
-
description: `List all notes/comments on an issue.
|
|
1858
|
-
Returns all comments including system notes in chronological order
|
|
2142
|
+
description: `List all notes/comments on an issue using GraphQL API with pagination support.
|
|
2143
|
+
Returns all comments including system notes in chronological order.
|
|
2144
|
+
|
|
2145
|
+
The response includes pagination information (pageInfo) with cursors for fetching additional pages.
|
|
2146
|
+
Use 'after' with the 'endCursor' from pageInfo to get the next page.
|
|
2147
|
+
Use 'before' with the 'startCursor' from pageInfo to get the previous page.`,
|
|
1859
2148
|
args: {
|
|
1860
2149
|
project_id: z2.string().describe("The project ID or URL-encoded path"),
|
|
1861
|
-
issue_iid: z2.number().describe("The internal ID of the issue")
|
|
2150
|
+
issue_iid: z2.number().describe("The internal ID of the issue"),
|
|
2151
|
+
first: z2.number().optional().describe("Number of items to return from the beginning (default: 20, max: 100)"),
|
|
2152
|
+
after: z2.string().optional().describe("Cursor for forward pagination - use endCursor from previous response"),
|
|
2153
|
+
last: z2.number().optional().describe("Number of items to return from the end (for backward pagination)"),
|
|
2154
|
+
before: z2.string().optional().describe("Cursor for backward pagination - use startCursor from previous response"),
|
|
2155
|
+
filter: z2.enum(["ALL_NOTES", "ONLY_COMMENTS", "ONLY_ACTIVITY"]).optional().describe("Filter notes by type: ALL_NOTES (default), ONLY_COMMENTS, or ONLY_ACTIVITY")
|
|
1862
2156
|
},
|
|
1863
2157
|
execute: async (args, _ctx) => {
|
|
1864
2158
|
const client = getGitLabClient();
|
|
1865
|
-
const
|
|
1866
|
-
|
|
2159
|
+
const result = await client.listIssueNotes(args.project_id, args.issue_iid, {
|
|
2160
|
+
first: args.first,
|
|
2161
|
+
after: args.after,
|
|
2162
|
+
last: args.last,
|
|
2163
|
+
before: args.before,
|
|
2164
|
+
filter: args.filter
|
|
2165
|
+
});
|
|
2166
|
+
return JSON.stringify(result, null, 2);
|
|
1867
2167
|
}
|
|
1868
2168
|
}),
|
|
1869
2169
|
gitlab_list_issue_discussions: tool2({
|
|
@@ -2118,16 +2418,29 @@ Removes the association between the issue and the epic.`,
|
|
|
2118
2418
|
}
|
|
2119
2419
|
}),
|
|
2120
2420
|
gitlab_list_epic_notes: tool3({
|
|
2121
|
-
description: `List all comments/notes on an epic
|
|
2122
|
-
Returns all comments in chronological order
|
|
2421
|
+
description: `List all comments/notes on an epic using GraphQL API with pagination support.
|
|
2422
|
+
Returns all comments in chronological order.
|
|
2423
|
+
|
|
2424
|
+
The response includes pagination information (pageInfo) with cursors for fetching additional pages.
|
|
2425
|
+
Use 'after' with the 'endCursor' from pageInfo to get the next page.
|
|
2426
|
+
Use 'before' with the 'startCursor' from pageInfo to get the previous page.`,
|
|
2123
2427
|
args: {
|
|
2124
2428
|
group_id: z3.string().describe("The group ID or URL-encoded path"),
|
|
2125
|
-
epic_iid: z3.number().describe("The internal ID of the epic")
|
|
2429
|
+
epic_iid: z3.number().describe("The internal ID of the epic"),
|
|
2430
|
+
first: z3.number().optional().describe("Number of items to return from the beginning (default: 20, max: 100)"),
|
|
2431
|
+
after: z3.string().optional().describe("Cursor for forward pagination - use endCursor from previous response"),
|
|
2432
|
+
last: z3.number().optional().describe("Number of items to return from the end (for backward pagination)"),
|
|
2433
|
+
before: z3.string().optional().describe("Cursor for backward pagination - use startCursor from previous response")
|
|
2126
2434
|
},
|
|
2127
2435
|
execute: async (args, _ctx) => {
|
|
2128
2436
|
const client = getGitLabClient();
|
|
2129
|
-
const
|
|
2130
|
-
|
|
2437
|
+
const result = await client.listEpicNotes(args.group_id, args.epic_iid, {
|
|
2438
|
+
first: args.first,
|
|
2439
|
+
after: args.after,
|
|
2440
|
+
last: args.last,
|
|
2441
|
+
before: args.before
|
|
2442
|
+
});
|
|
2443
|
+
return JSON.stringify(result, null, 2);
|
|
2131
2444
|
}
|
|
2132
2445
|
}),
|
|
2133
2446
|
gitlab_list_epic_discussions: tool3({
|
|
@@ -3138,16 +3451,29 @@ Use this to get the full context of a specific conversation.`,
|
|
|
3138
3451
|
}
|
|
3139
3452
|
}),
|
|
3140
3453
|
gitlab_list_snippet_notes: tool9({
|
|
3141
|
-
description: `List all notes/comments on a project snippet
|
|
3142
|
-
Returns all comments including system notes in chronological order
|
|
3454
|
+
description: `List all notes/comments on a project snippet using GraphQL API with pagination support.
|
|
3455
|
+
Returns all comments including system notes in chronological order.
|
|
3456
|
+
|
|
3457
|
+
The response includes pagination information (pageInfo) with cursors for fetching additional pages.
|
|
3458
|
+
Use 'after' with the 'endCursor' from pageInfo to get the next page.
|
|
3459
|
+
Use 'before' with the 'startCursor' from pageInfo to get the previous page.`,
|
|
3143
3460
|
args: {
|
|
3144
3461
|
project_id: z9.string().describe("The project ID or URL-encoded path"),
|
|
3145
|
-
snippet_id: z9.number().describe("The ID of the snippet")
|
|
3462
|
+
snippet_id: z9.number().describe("The ID of the snippet"),
|
|
3463
|
+
first: z9.number().optional().describe("Number of items to return from the beginning (default: 20, max: 100)"),
|
|
3464
|
+
after: z9.string().optional().describe("Cursor for forward pagination - use endCursor from previous response"),
|
|
3465
|
+
last: z9.number().optional().describe("Number of items to return from the end (for backward pagination)"),
|
|
3466
|
+
before: z9.string().optional().describe("Cursor for backward pagination - use startCursor from previous response")
|
|
3146
3467
|
},
|
|
3147
3468
|
execute: async (args, _ctx) => {
|
|
3148
3469
|
const client = getGitLabClient();
|
|
3149
|
-
const
|
|
3150
|
-
|
|
3470
|
+
const result = await client.listSnippetNotes(args.project_id, args.snippet_id, {
|
|
3471
|
+
first: args.first,
|
|
3472
|
+
after: args.after,
|
|
3473
|
+
last: args.last,
|
|
3474
|
+
before: args.before
|
|
3475
|
+
});
|
|
3476
|
+
return JSON.stringify(result, null, 2);
|
|
3151
3477
|
}
|
|
3152
3478
|
}),
|
|
3153
3479
|
gitlab_create_snippet_note: tool9({
|
package/package.json
CHANGED
|
Binary file
|