@gitlab/opencode-gitlab-plugin 1.4.0 → 1.5.1

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,20 @@
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.5.1](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin/compare/v1.5.0...v1.5.1) (2026-02-02)
6
+
7
+
8
+ ### 🐛 Bug Fixes
9
+
10
+ * remove unsupported GraphQL fields causing API errors ([6d6de6f](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin/commit/6d6de6fff29609f3fc591a199055a752abe0fdcd))
11
+
12
+ ## [1.5.0](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin/compare/v1.4.0...v1.5.0) (2026-02-02)
13
+
14
+
15
+ ### ✨ Features
16
+
17
+ * migrate discussions to GraphQL with cursor-based pagination ([1c61895](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin/commit/1c61895a8f0146f40d7a29a303cdc49e91280280))
18
+
5
19
  ## [1.4.0](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin/compare/v1.3.0...v1.4.0) (2026-02-02)
6
20
 
7
21
 
package/dist/index.js CHANGED
@@ -93,7 +93,6 @@ function buildPaginationVariables(options) {
93
93
  if (options?.after) variables.after = options.after;
94
94
  if (options?.last !== void 0) variables.last = options.last;
95
95
  if (options?.before) variables.before = options.before;
96
- if (options?.filter) variables.filter = options.filter;
97
96
  return variables;
98
97
  }
99
98
  var NOTES_FRAGMENT = `
@@ -132,6 +131,74 @@ var NOTES_CONNECTION_FRAGMENT = `
132
131
  }
133
132
  `;
134
133
 
134
+ // src/client/discussions-types.ts
135
+ function buildDiscussionsPaginationVariables(options) {
136
+ const variables = {};
137
+ if (options?.first !== void 0) {
138
+ variables.first = options.first;
139
+ } else if (options?.last == null) {
140
+ variables.first = 20;
141
+ }
142
+ if (options?.after) variables.after = options.after;
143
+ if (options?.last !== void 0) variables.last = options.last;
144
+ if (options?.before) variables.before = options.before;
145
+ return variables;
146
+ }
147
+ var DISCUSSION_NOTE_FRAGMENT = `
148
+ fragment DiscussionNoteFields on Note {
149
+ id
150
+ body
151
+ bodyHtml
152
+ createdAt
153
+ updatedAt
154
+ system
155
+ resolvable
156
+ resolved
157
+ resolvedAt
158
+ url
159
+ author {
160
+ id
161
+ username
162
+ name
163
+ avatarUrl
164
+ }
165
+ }
166
+ `;
167
+ var DISCUSSION_FRAGMENT = `
168
+ fragment DiscussionFields on Discussion {
169
+ id
170
+ replyId
171
+ createdAt
172
+ resolved
173
+ resolvable
174
+ resolvedAt
175
+ resolvedBy {
176
+ id
177
+ username
178
+ name
179
+ avatarUrl
180
+ }
181
+ notes {
182
+ nodes {
183
+ ...DiscussionNoteFields
184
+ }
185
+ }
186
+ }
187
+ `;
188
+ var DISCUSSIONS_CONNECTION_FRAGMENT = `
189
+ fragment DiscussionsConnectionFields on DiscussionConnection {
190
+ pageInfo {
191
+ hasNextPage
192
+ hasPreviousPage
193
+ startCursor
194
+ endCursor
195
+ }
196
+ nodes {
197
+ ...DiscussionFields
198
+ }
199
+ }
200
+ `;
201
+
135
202
  // src/client/merge-requests.ts
136
203
  var LIST_MR_NOTES_QUERY = `
137
204
  ${NOTES_FRAGMENT}
@@ -143,7 +210,6 @@ var LIST_MR_NOTES_QUERY = `
143
210
  $after: String
144
211
  $last: Int
145
212
  $before: String
146
- $filter: WorkItemNotesFilterType
147
213
  ) {
148
214
  project(fullPath: $projectPath) {
149
215
  mergeRequest(iid: $mrIid) {
@@ -152,7 +218,6 @@ var LIST_MR_NOTES_QUERY = `
152
218
  after: $after
153
219
  last: $last
154
220
  before: $before
155
- filter: $filter
156
221
  ) {
157
222
  ...NotesConnectionFields
158
223
  }
@@ -160,6 +225,32 @@ var LIST_MR_NOTES_QUERY = `
160
225
  }
161
226
  }
162
227
  `;
228
+ var LIST_MR_DISCUSSIONS_QUERY = `
229
+ ${DISCUSSION_NOTE_FRAGMENT}
230
+ ${DISCUSSION_FRAGMENT}
231
+ ${DISCUSSIONS_CONNECTION_FRAGMENT}
232
+ query listMrDiscussions(
233
+ $projectPath: ID!
234
+ $mrIid: String!
235
+ $first: Int
236
+ $after: String
237
+ $last: Int
238
+ $before: String
239
+ ) {
240
+ project(fullPath: $projectPath) {
241
+ mergeRequest(iid: $mrIid) {
242
+ discussions(
243
+ first: $first
244
+ after: $after
245
+ last: $last
246
+ before: $before
247
+ ) {
248
+ ...DiscussionsConnectionFields
249
+ }
250
+ }
251
+ }
252
+ }
253
+ `;
163
254
  var SET_AUTO_MERGE_MUTATION = `
164
255
  mutation setAutoMerge(
165
256
  $projectPath: ID!
@@ -218,12 +309,41 @@ var MergeRequestsClient = class extends GitLabApiClient {
218
309
  `/projects/${encodedProject}/merge_requests/${mrIid}/changes`
219
310
  );
220
311
  }
221
- async listMrDiscussions(projectId, mrIid) {
222
- const encodedProject = this.encodeProjectId(projectId);
223
- return this.fetch(
224
- "GET",
225
- `/projects/${encodedProject}/merge_requests/${mrIid}/discussions`
226
- );
312
+ /**
313
+ * List notes on a merge request using GraphQL API with pagination support
314
+ */
315
+ async listMrNotes(projectId, mrIid, options) {
316
+ const variables = {
317
+ projectPath: projectId,
318
+ mrIid: String(mrIid),
319
+ ...buildPaginationVariables(options)
320
+ };
321
+ const result = await this.fetchGraphQL(LIST_MR_NOTES_QUERY, variables);
322
+ const notes = result.project?.mergeRequest?.notes;
323
+ if (!notes) {
324
+ throw new Error("Merge request not found or access denied");
325
+ }
326
+ return {
327
+ notes,
328
+ pageInfo: notes.pageInfo,
329
+ totalCount: notes.count
330
+ };
331
+ }
332
+ /**
333
+ * List discussions on a merge request using GraphQL API with pagination support
334
+ */
335
+ async listMrDiscussions(projectId, mrIid, options) {
336
+ const variables = {
337
+ projectPath: projectId,
338
+ mrIid: String(mrIid),
339
+ ...buildDiscussionsPaginationVariables(options)
340
+ };
341
+ const result = await this.fetchGraphQL(LIST_MR_DISCUSSIONS_QUERY, variables);
342
+ const discussions = result.project?.mergeRequest?.discussions;
343
+ if (!discussions) {
344
+ throw new Error("Merge request not found or access denied");
345
+ }
346
+ return { discussions };
227
347
  }
228
348
  async getMrDiscussion(projectId, mrIid, discussionId) {
229
349
  const encodedProject = this.encodeProjectId(projectId);
@@ -260,26 +380,6 @@ var MergeRequestsClient = class extends GitLabApiClient {
260
380
  requestBody
261
381
  );
262
382
  }
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
- };
282
- }
283
383
  async createMrNote(projectId, mrIid, body, discussionId) {
284
384
  const encodedProject = this.encodeProjectId(projectId);
285
385
  if (discussionId) {
@@ -366,7 +466,6 @@ var LIST_ISSUE_NOTES_QUERY = `
366
466
  $after: String
367
467
  $last: Int
368
468
  $before: String
369
- $filter: WorkItemNotesFilterType
370
469
  ) {
371
470
  project(fullPath: $projectPath) {
372
471
  issue(iid: $issueIid) {
@@ -375,7 +474,6 @@ var LIST_ISSUE_NOTES_QUERY = `
375
474
  after: $after
376
475
  last: $last
377
476
  before: $before
378
- filter: $filter
379
477
  ) {
380
478
  ...NotesConnectionFields
381
479
  }
@@ -383,6 +481,32 @@ var LIST_ISSUE_NOTES_QUERY = `
383
481
  }
384
482
  }
385
483
  `;
484
+ var LIST_ISSUE_DISCUSSIONS_QUERY = `
485
+ ${DISCUSSION_NOTE_FRAGMENT}
486
+ ${DISCUSSION_FRAGMENT}
487
+ ${DISCUSSIONS_CONNECTION_FRAGMENT}
488
+ query listIssueDiscussions(
489
+ $projectPath: ID!
490
+ $issueIid: String!
491
+ $first: Int
492
+ $after: String
493
+ $last: Int
494
+ $before: String
495
+ ) {
496
+ project(fullPath: $projectPath) {
497
+ issue(iid: $issueIid) {
498
+ discussions(
499
+ first: $first
500
+ after: $after
501
+ last: $last
502
+ before: $before
503
+ ) {
504
+ ...DiscussionsConnectionFields
505
+ }
506
+ }
507
+ }
508
+ }
509
+ `;
386
510
  var IssuesClient = class extends GitLabApiClient {
387
511
  async createIssue(projectId, title, options) {
388
512
  const encodedProject = this.encodeProjectId(projectId);
@@ -438,12 +562,21 @@ var IssuesClient = class extends GitLabApiClient {
438
562
  totalCount: notes.count
439
563
  };
440
564
  }
441
- async listIssueDiscussions(projectId, issueIid) {
442
- const encodedProject = this.encodeProjectId(projectId);
443
- return this.fetch(
444
- "GET",
445
- `/projects/${encodedProject}/issues/${issueIid}/discussions`
446
- );
565
+ /**
566
+ * List discussions on an issue using GraphQL API with pagination support
567
+ */
568
+ async listIssueDiscussions(projectId, issueIid, options) {
569
+ const variables = {
570
+ projectPath: projectId,
571
+ issueIid: String(issueIid),
572
+ ...buildDiscussionsPaginationVariables(options)
573
+ };
574
+ const result = await this.fetchGraphQL(LIST_ISSUE_DISCUSSIONS_QUERY, variables);
575
+ const discussions = result.project?.issue?.discussions;
576
+ if (!discussions) {
577
+ throw new Error("Issue not found or access denied");
578
+ }
579
+ return { discussions };
447
580
  }
448
581
  async getIssueDiscussion(projectId, issueIid, discussionId) {
449
582
  const encodedProject = this.encodeProjectId(projectId);
@@ -1264,36 +1397,6 @@ var LIST_TODOS_QUERY = `
1264
1397
  name
1265
1398
  avatarUrl
1266
1399
  }
1267
- targetEntity {
1268
- __typename
1269
- ... on Issue {
1270
- id
1271
- title
1272
- iid
1273
- }
1274
- ... on MergeRequest {
1275
- id
1276
- title
1277
- iid
1278
- }
1279
- ... on Epic {
1280
- id
1281
- title
1282
- iid
1283
- }
1284
- ... on Commit {
1285
- id
1286
- title
1287
- }
1288
- ... on DesignManagement__Design {
1289
- id
1290
- }
1291
- ... on AlertManagement__Alert {
1292
- id
1293
- title
1294
- iid
1295
- }
1296
- }
1297
1400
  }
1298
1401
  }
1299
1402
  }
@@ -1382,7 +1485,7 @@ var LIST_EPIC_NOTES_QUERY = `
1382
1485
  ${NOTES_CONNECTION_FRAGMENT}
1383
1486
  query listEpicNotes(
1384
1487
  $groupPath: ID!
1385
- $epicIid: ID!
1488
+ $epicIid: String!
1386
1489
  $first: Int
1387
1490
  $after: String
1388
1491
  $last: Int
@@ -1402,6 +1505,32 @@ var LIST_EPIC_NOTES_QUERY = `
1402
1505
  }
1403
1506
  }
1404
1507
  `;
1508
+ var LIST_EPIC_DISCUSSIONS_QUERY = `
1509
+ ${DISCUSSION_NOTE_FRAGMENT}
1510
+ ${DISCUSSION_FRAGMENT}
1511
+ ${DISCUSSIONS_CONNECTION_FRAGMENT}
1512
+ query listEpicDiscussions(
1513
+ $groupPath: ID!
1514
+ $epicIid: String!
1515
+ $first: Int
1516
+ $after: String
1517
+ $last: Int
1518
+ $before: String
1519
+ ) {
1520
+ group(fullPath: $groupPath) {
1521
+ epic(iid: $epicIid) {
1522
+ discussions(
1523
+ first: $first
1524
+ after: $after
1525
+ last: $last
1526
+ before: $before
1527
+ ) {
1528
+ ...DiscussionsConnectionFields
1529
+ }
1530
+ }
1531
+ }
1532
+ }
1533
+ `;
1405
1534
  var EpicsClient = class extends GitLabApiClient {
1406
1535
  async getEpic(groupId, epicIid) {
1407
1536
  const encodedGroup = encodeURIComponent(groupId);
@@ -1470,12 +1599,21 @@ var EpicsClient = class extends GitLabApiClient {
1470
1599
  totalCount: notes.count
1471
1600
  };
1472
1601
  }
1473
- async listEpicDiscussions(groupId, epicIid) {
1474
- const encodedGroup = encodeURIComponent(groupId);
1475
- return this.fetch(
1476
- "GET",
1477
- `/groups/${encodedGroup}/epics/${epicIid}/discussions`
1478
- );
1602
+ /**
1603
+ * List discussions on an epic using GraphQL API with pagination support
1604
+ */
1605
+ async listEpicDiscussions(groupId, epicIid, options) {
1606
+ const variables = {
1607
+ groupPath: groupId,
1608
+ epicIid: String(epicIid),
1609
+ ...buildDiscussionsPaginationVariables(options)
1610
+ };
1611
+ const result = await this.fetchGraphQL(LIST_EPIC_DISCUSSIONS_QUERY, variables);
1612
+ const discussions = result.group?.epic?.discussions;
1613
+ if (!discussions) {
1614
+ throw new Error("Epic not found or access denied");
1615
+ }
1616
+ return { discussions };
1479
1617
  }
1480
1618
  async getEpicDiscussion(groupId, epicIid, discussionId) {
1481
1619
  const encodedGroup = encodeURIComponent(groupId);
@@ -1533,21 +1671,32 @@ var LIST_SNIPPET_NOTES_QUERY = `
1533
1671
  }
1534
1672
  }
1535
1673
  `;
1536
- var SnippetsClient = class extends GitLabApiClient {
1537
- async listSnippetDiscussions(projectId, snippetId) {
1538
- const encodedProject = this.encodeProjectId(projectId);
1539
- return this.fetch(
1540
- "GET",
1541
- `/projects/${encodedProject}/snippets/${snippetId}/discussions`
1542
- );
1543
- }
1544
- async getSnippetDiscussion(projectId, snippetId, discussionId) {
1545
- const encodedProject = this.encodeProjectId(projectId);
1546
- return this.fetch(
1547
- "GET",
1548
- `/projects/${encodedProject}/snippets/${snippetId}/discussions/${discussionId}`
1549
- );
1674
+ var LIST_SNIPPET_DISCUSSIONS_QUERY = `
1675
+ ${DISCUSSION_NOTE_FRAGMENT}
1676
+ ${DISCUSSION_FRAGMENT}
1677
+ ${DISCUSSIONS_CONNECTION_FRAGMENT}
1678
+ query listSnippetDiscussions(
1679
+ $snippetGid: SnippetID!
1680
+ $first: Int
1681
+ $after: String
1682
+ $last: Int
1683
+ $before: String
1684
+ ) {
1685
+ snippets(ids: [$snippetGid]) {
1686
+ nodes {
1687
+ discussions(
1688
+ first: $first
1689
+ after: $after
1690
+ last: $last
1691
+ before: $before
1692
+ ) {
1693
+ ...DiscussionsConnectionFields
1694
+ }
1695
+ }
1696
+ }
1550
1697
  }
1698
+ `;
1699
+ var SnippetsClient = class extends GitLabApiClient {
1551
1700
  /**
1552
1701
  * List notes on a snippet using GraphQL API with pagination support
1553
1702
  */
@@ -1573,6 +1722,33 @@ var SnippetsClient = class extends GitLabApiClient {
1573
1722
  totalCount: notes.count
1574
1723
  };
1575
1724
  }
1725
+ /**
1726
+ * List discussions on a snippet using GraphQL API with pagination support
1727
+ */
1728
+ async listSnippetDiscussions(projectId, snippetId, options) {
1729
+ const variables = {
1730
+ snippetGid: `gid://gitlab/ProjectSnippet/${snippetId}`,
1731
+ ...buildDiscussionsPaginationVariables(options)
1732
+ };
1733
+ const result = await this.fetchGraphQL(LIST_SNIPPET_DISCUSSIONS_QUERY, variables);
1734
+ const discussions = result.snippets.nodes[0]?.discussions || {
1735
+ nodes: [],
1736
+ pageInfo: {
1737
+ hasNextPage: false,
1738
+ hasPreviousPage: false,
1739
+ startCursor: null,
1740
+ endCursor: null
1741
+ }
1742
+ };
1743
+ return { discussions };
1744
+ }
1745
+ async getSnippetDiscussion(projectId, snippetId, discussionId) {
1746
+ const encodedProject = this.encodeProjectId(projectId);
1747
+ return this.fetch(
1748
+ "GET",
1749
+ `/projects/${encodedProject}/snippets/${snippetId}/discussions/${discussionId}`
1750
+ );
1751
+ }
1576
1752
  async createSnippetNote(projectId, snippetId, body, discussionId) {
1577
1753
  const encodedProject = this.encodeProjectId(projectId);
1578
1754
  if (discussionId) {
@@ -1916,11 +2092,20 @@ Returns all discussion threads with nested notes. Each discussion contains a 'no
1916
2092
  Note: For a flattened list of all comments, use gitlab_list_mr_notes instead.`,
1917
2093
  args: {
1918
2094
  project_id: z.string().describe("The project ID or URL-encoded path"),
1919
- mr_iid: z.number().describe("The internal ID of the merge request")
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)")
1920
2100
  },
1921
2101
  execute: async (args, _ctx) => {
1922
2102
  const client = getGitLabClient();
1923
- const discussions = await client.listMrDiscussions(args.project_id, args.mr_iid);
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
+ });
1924
2109
  return JSON.stringify(discussions, null, 2);
1925
2110
  }
1926
2111
  }),
@@ -1938,8 +2123,7 @@ Use 'before' with the 'startCursor' from pageInfo to get the previous page.`,
1938
2123
  first: z.number().optional().describe("Number of items to return from the beginning (default: 20, max: 100)"),
1939
2124
  after: z.string().optional().describe("Cursor for forward pagination - use endCursor from previous response"),
1940
2125
  last: z.number().optional().describe("Number of items to return from the end (for backward pagination)"),
1941
- before: z.string().optional().describe("Cursor for backward pagination - use startCursor from previous response"),
1942
- filter: z.enum(["ALL_NOTES", "ONLY_COMMENTS", "ONLY_ACTIVITY"]).optional().describe("Filter notes by type: ALL_NOTES (default), ONLY_COMMENTS, or ONLY_ACTIVITY")
2126
+ before: z.string().optional().describe("Cursor for backward pagination - use startCursor from previous response")
1943
2127
  },
1944
2128
  execute: async (args, _ctx) => {
1945
2129
  const client = getGitLabClient();
@@ -1947,8 +2131,7 @@ Use 'before' with the 'startCursor' from pageInfo to get the previous page.`,
1947
2131
  first: args.first,
1948
2132
  after: args.after,
1949
2133
  last: args.last,
1950
- before: args.before,
1951
- filter: args.filter
2134
+ before: args.before
1952
2135
  });
1953
2136
  return JSON.stringify(result, null, 2);
1954
2137
  }
@@ -2295,8 +2478,7 @@ Use 'before' with the 'startCursor' from pageInfo to get the previous page.`,
2295
2478
  first: z2.number().optional().describe("Number of items to return from the beginning (default: 20, max: 100)"),
2296
2479
  after: z2.string().optional().describe("Cursor for forward pagination - use endCursor from previous response"),
2297
2480
  last: z2.number().optional().describe("Number of items to return from the end (for backward pagination)"),
2298
- before: z2.string().optional().describe("Cursor for backward pagination - use startCursor from previous response"),
2299
- filter: z2.enum(["ALL_NOTES", "ONLY_COMMENTS", "ONLY_ACTIVITY"]).optional().describe("Filter notes by type: ALL_NOTES (default), ONLY_COMMENTS, or ONLY_ACTIVITY")
2481
+ before: z2.string().optional().describe("Cursor for backward pagination - use startCursor from previous response")
2300
2482
  },
2301
2483
  execute: async (args, _ctx) => {
2302
2484
  const client = getGitLabClient();
@@ -2304,8 +2486,7 @@ Use 'before' with the 'startCursor' from pageInfo to get the previous page.`,
2304
2486
  first: args.first,
2305
2487
  after: args.after,
2306
2488
  last: args.last,
2307
- before: args.before,
2308
- filter: args.filter
2489
+ before: args.before
2309
2490
  });
2310
2491
  return JSON.stringify(result, null, 2);
2311
2492
  }
@@ -2316,11 +2497,20 @@ Returns all discussion threads with nested notes. Each discussion contains a 'no
2316
2497
  Use the discussion 'id' field to reply to a specific thread with gitlab_create_issue_note.`,
2317
2498
  args: {
2318
2499
  project_id: z2.string().describe("The project ID or URL-encoded path"),
2319
- issue_iid: z2.number().describe("The internal ID of the issue")
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)")
2320
2505
  },
2321
2506
  execute: async (args, _ctx) => {
2322
2507
  const client = getGitLabClient();
2323
- const discussions = await client.listIssueDiscussions(args.project_id, args.issue_iid);
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
+ });
2324
2514
  return JSON.stringify(discussions, null, 2);
2325
2515
  }
2326
2516
  }),
@@ -2593,11 +2783,20 @@ Returns all discussion threads with nested notes. Each discussion contains a 'no
2593
2783
  Use the discussion 'id' field to reply to a specific thread with gitlab_create_epic_note.`,
2594
2784
  args: {
2595
2785
  group_id: z3.string().describe("The group ID or URL-encoded path"),
2596
- epic_iid: z3.number().describe("The internal ID of the epic")
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)")
2597
2791
  },
2598
2792
  execute: async (args, _ctx) => {
2599
2793
  const client = getGitLabClient();
2600
- const discussions = await client.listEpicDiscussions(args.group_id, args.epic_iid);
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
+ });
2601
2800
  return JSON.stringify(discussions, null, 2);
2602
2801
  }
2603
2802
  }),
@@ -3567,11 +3766,20 @@ Returns all discussion threads with nested notes. Each discussion contains a 'no
3567
3766
  Use the discussion 'id' field to reply to a specific thread with gitlab_create_snippet_note.`,
3568
3767
  args: {
3569
3768
  project_id: z9.string().describe("The project ID or URL-encoded path"),
3570
- snippet_id: z9.number().describe("The ID of the snippet")
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)")
3571
3774
  },
3572
3775
  execute: async (args, _ctx) => {
3573
3776
  const client = getGitLabClient();
3574
- const discussions = await client.listSnippetDiscussions(args.project_id, args.snippet_id);
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
+ });
3575
3783
  return JSON.stringify(discussions, null, 2);
3576
3784
  }
3577
3785
  }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/opencode-gitlab-plugin",
3
- "version": "1.4.0",
3
+ "version": "1.5.1",
4
4
  "description": "GitLab tools plugin for OpenCode - provides GitLab API access for merge requests, issues, pipelines, and more",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",