@gitlab/opencode-gitlab-plugin 1.5.4 → 1.5.5
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 +8 -0
- package/README.md +24 -25
- package/dist/gitlab-opencode-gitlab-plugin-1.5.5.tgz +0 -0
- package/dist/index.js +321 -244
- package/package.json +1 -1
- package/dist/gitlab-opencode-gitlab-plugin-1.5.4.tgz +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
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.5](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin/compare/v1.5.4...v1.5.5) (2026-02-03)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### ♻️ Code Refactoring
|
|
9
|
+
|
|
10
|
+
* consolidate notes tools into unified interface ([2e407ad](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin/commit/2e407ad9bce03b7c6b2220ab39d6dac9bc82ebd4))
|
|
11
|
+
* improve validation error messages in notes tools ([3c95ca6](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin/commit/3c95ca66281378f480250ed549611e352319b001))
|
|
12
|
+
|
|
5
13
|
## [1.5.4](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin/compare/v1.5.3...v1.5.4) (2026-02-03)
|
|
6
14
|
|
|
7
15
|
|
package/README.md
CHANGED
|
@@ -62,7 +62,7 @@ The following tools use GitLab's GraphQL API for enhanced functionality:
|
|
|
62
62
|
| Category | Tools | Benefits |
|
|
63
63
|
| --------------- | ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
|
|
64
64
|
| **TODOs** | `gitlab_list_todos`, `gitlab_get_todo_count` | Cursor-based pagination, rich filtering |
|
|
65
|
-
| **Notes** | `
|
|
65
|
+
| **Notes** | `gitlab_list_notes`, `gitlab_get_note`, `gitlab_create_note` | Unified interface for all resource types, efficient pagination |
|
|
66
66
|
| **Discussions** | `gitlab_list_discussions`, `gitlab_get_discussion`, `gitlab_create_discussion`, `gitlab_resolve_discussion` | Unified interface for all resource types, cursor-based pagination, code position support |
|
|
67
67
|
| **Auto-merge** | `gitlab_set_mr_auto_merge` | MWPS (Merge When Pipeline Succeeds), merge train support |
|
|
68
68
|
| **Security** | All vulnerability management tools | Type-safe GID validation, mutation support |
|
|
@@ -134,7 +134,7 @@ graph LR
|
|
|
134
134
|
B --> B1[readTokenFromAuthStorage]
|
|
135
135
|
B --> B2[getGitLabClient]
|
|
136
136
|
|
|
137
|
-
C --> C1[
|
|
137
|
+
C --> C1[78 Tool Definitions]
|
|
138
138
|
|
|
139
139
|
D --> A
|
|
140
140
|
D --> B
|
|
@@ -287,9 +287,9 @@ Or for API tokens:
|
|
|
287
287
|
|
|
288
288
|
## 🛠️ Available Tools
|
|
289
289
|
|
|
290
|
-
The plugin provides **
|
|
290
|
+
The plugin provides **78 tools** organized into the following categories:
|
|
291
291
|
|
|
292
|
-
### Merge Request Tools (
|
|
292
|
+
### Merge Request Tools (9 tools)
|
|
293
293
|
|
|
294
294
|
| Tool | Description |
|
|
295
295
|
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -298,23 +298,20 @@ The plugin provides **81 tools** organized into the following categories:
|
|
|
298
298
|
| `gitlab_create_merge_request` | Create a new merge request |
|
|
299
299
|
| `gitlab_update_merge_request` | Update merge request title, description, state, assignees, reviewers, and labels |
|
|
300
300
|
| `gitlab_get_mr_changes` | Get file changes/diffs for a merge request |
|
|
301
|
-
| `gitlab_list_mr_notes` | List all comments with cursor-based pagination (GraphQL) |
|
|
302
301
|
| `gitlab_get_mr_commits` | Get all commits in a merge request |
|
|
303
302
|
| `gitlab_get_mr_pipelines` | Get all pipelines for a merge request |
|
|
304
303
|
| `gitlab_list_merge_request_diffs` | List file diffs with pagination support for large changesets |
|
|
305
304
|
| `gitlab_set_mr_auto_merge` | Enable auto-merge (MWPS) using GraphQL API when pipeline succeeds |
|
|
306
305
|
|
|
307
|
-
### Issue Tools (
|
|
306
|
+
### Issue Tools (3 tools)
|
|
308
307
|
|
|
309
|
-
| Tool
|
|
310
|
-
|
|
|
311
|
-
| `gitlab_create_issue`
|
|
312
|
-
| `gitlab_get_issue`
|
|
313
|
-
| `gitlab_list_issues`
|
|
314
|
-
| `gitlab_list_issue_notes` | List all comments with cursor-based pagination (GraphQL) |
|
|
315
|
-
| `gitlab_get_issue_note` | Get a specific note by ID with full details |
|
|
308
|
+
| Tool | Description |
|
|
309
|
+
| --------------------- | ---------------------------------------------------------------------------- |
|
|
310
|
+
| `gitlab_create_issue` | Create a new issue with title, description, labels, assignees, and milestone |
|
|
311
|
+
| `gitlab_get_issue` | Get issue details including state, author, assignees, labels, and comments |
|
|
312
|
+
| `gitlab_list_issues` | List issues with filtering by state, labels, assignee, and milestone |
|
|
316
313
|
|
|
317
|
-
### Epic Tools (
|
|
314
|
+
### Epic Tools (7 tools)
|
|
318
315
|
|
|
319
316
|
| Tool | Description |
|
|
320
317
|
| ------------------------------- | ----------------------------------------------------------------------------- |
|
|
@@ -325,8 +322,6 @@ The plugin provides **81 tools** organized into the following categories:
|
|
|
325
322
|
| `gitlab_list_epic_issues` | Get all issues linked to an epic |
|
|
326
323
|
| `gitlab_add_issue_to_epic` | Link an issue to an epic |
|
|
327
324
|
| `gitlab_remove_issue_from_epic` | Unlink an issue from an epic |
|
|
328
|
-
| `gitlab_list_epic_notes` | List all comments with cursor-based pagination (GraphQL) |
|
|
329
|
-
| `gitlab_get_epic_note` | Get a specific epic note by ID |
|
|
330
325
|
|
|
331
326
|
### Pipeline Tools (8 tools)
|
|
332
327
|
|
|
@@ -412,12 +407,6 @@ The plugin provides **81 tools** organized into the following categories:
|
|
|
412
407
|
| `gitlab_list_project_members` | List all members of a project |
|
|
413
408
|
| `gitlab_get_current_user` | Get authenticated user information |
|
|
414
409
|
|
|
415
|
-
### Snippet Tools (1 tool)
|
|
416
|
-
|
|
417
|
-
| Tool | Description |
|
|
418
|
-
| --------------------------- | -------------------------------------------------------- |
|
|
419
|
-
| `gitlab_list_snippet_notes` | List all comments with cursor-based pagination (GraphQL) |
|
|
420
|
-
|
|
421
410
|
### Discussion Tools (4 tools)
|
|
422
411
|
|
|
423
412
|
| Tool | Description |
|
|
@@ -427,6 +416,14 @@ The plugin provides **81 tools** organized into the following categories:
|
|
|
427
416
|
| `gitlab_create_discussion` | Create a new discussion thread OR reply to an existing one (supports code-position comments for MRs and commits) |
|
|
428
417
|
| `gitlab_resolve_discussion` | Mark a discussion thread as resolved or unresolve it (MRs and issues only) |
|
|
429
418
|
|
|
419
|
+
### Notes Tools (3 tools)
|
|
420
|
+
|
|
421
|
+
| Tool | Description |
|
|
422
|
+
| -------------------- | --------------------------------------------------------------------------------------------------- |
|
|
423
|
+
| `gitlab_list_notes` | List all notes/comments on any resource (MRs, issues, epics, snippets) with cursor-based pagination |
|
|
424
|
+
| `gitlab_get_note` | Get a single note by ID (issues and epics only) |
|
|
425
|
+
| `gitlab_create_note` | Add a simple comment to any resource (for thread replies, use `gitlab_create_discussion`) |
|
|
426
|
+
|
|
430
427
|
### Audit Event Tools (3 tools)
|
|
431
428
|
|
|
432
429
|
| Tool | Description |
|
|
@@ -470,10 +467,11 @@ const issue = await plugin.tool.gitlab_create_issue.execute({
|
|
|
470
467
|
|
|
471
468
|
console.log(`Issue created: ${issue.web_url}`);
|
|
472
469
|
|
|
473
|
-
// Add a comment to the issue
|
|
474
|
-
await plugin.tool.
|
|
470
|
+
// Add a comment to the issue (using unified notes tool)
|
|
471
|
+
await plugin.tool.gitlab_create_note.execute({
|
|
472
|
+
resource_type: 'issue',
|
|
475
473
|
project_id: 'my-group/my-project',
|
|
476
|
-
|
|
474
|
+
iid: issue.iid,
|
|
477
475
|
body: 'I will start working on this today.',
|
|
478
476
|
});
|
|
479
477
|
|
|
@@ -766,6 +764,7 @@ opencode-gitlab-plugin/
|
|
|
766
764
|
│ │ ├── pipelines.ts # Pipeline tool definitions
|
|
767
765
|
│ │ ├── repository.ts # Repository tool definitions
|
|
768
766
|
│ │ ├── discussions-unified.ts # Unified discussion tools (4 tools)
|
|
767
|
+
│ │ ├── notes-unified.ts # Unified notes tools (3 tools)
|
|
769
768
|
│ │ └── ... # Other tool definitions
|
|
770
769
|
│ ├── index.ts # Main plugin entry point
|
|
771
770
|
│ ├── utils.ts # Utility functions
|
|
Binary file
|
package/dist/index.js
CHANGED
|
@@ -2086,33 +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_notes: tool({
|
|
2090
|
-
description: `List all notes/comments on a merge request using GraphQL API with pagination support.
|
|
2091
|
-
Returns all comments including system notes, code review comments, and general discussion.
|
|
2092
|
-
This is easier to read than discussions which have nested structure.
|
|
2093
|
-
|
|
2094
|
-
The response includes pagination information (pageInfo) with cursors for fetching additional pages.
|
|
2095
|
-
Use 'after' with the 'endCursor' from pageInfo to get the next page.
|
|
2096
|
-
Use 'before' with the 'startCursor' from pageInfo to get the previous page.`,
|
|
2097
|
-
args: {
|
|
2098
|
-
project_id: z.string().describe("The project ID or URL-encoded path"),
|
|
2099
|
-
mr_iid: z.number().describe("The internal ID of the merge request"),
|
|
2100
|
-
first: z.number().optional().describe("Number of items to return from the beginning (default: 20, max: 100)"),
|
|
2101
|
-
after: z.string().optional().describe("Cursor for forward pagination - use endCursor from previous response"),
|
|
2102
|
-
last: z.number().optional().describe("Number of items to return from the end (for backward pagination)"),
|
|
2103
|
-
before: z.string().optional().describe("Cursor for backward pagination - use startCursor from previous response")
|
|
2104
|
-
},
|
|
2105
|
-
execute: async (args, _ctx) => {
|
|
2106
|
-
const client = getGitLabClient();
|
|
2107
|
-
const result = await client.listMrNotes(args.project_id, args.mr_iid, {
|
|
2108
|
-
first: args.first,
|
|
2109
|
-
after: args.after,
|
|
2110
|
-
last: args.last,
|
|
2111
|
-
before: args.before
|
|
2112
|
-
});
|
|
2113
|
-
return JSON.stringify(result, null, 2);
|
|
2114
|
-
}
|
|
2115
|
-
}),
|
|
2116
2089
|
gitlab_create_merge_request: tool({
|
|
2117
2090
|
description: `Create a new merge request.
|
|
2118
2091
|
Returns the created merge request with all details.`,
|
|
@@ -2330,47 +2303,6 @@ Can filter by state, labels, assignee, milestone.`,
|
|
|
2330
2303
|
});
|
|
2331
2304
|
return JSON.stringify(issues, null, 2);
|
|
2332
2305
|
}
|
|
2333
|
-
}),
|
|
2334
|
-
gitlab_list_issue_notes: tool2({
|
|
2335
|
-
description: `List all notes/comments on an issue using GraphQL API with pagination support.
|
|
2336
|
-
Returns all comments including system notes in chronological order.
|
|
2337
|
-
|
|
2338
|
-
The response includes pagination information (pageInfo) with cursors for fetching additional pages.
|
|
2339
|
-
Use 'after' with the 'endCursor' from pageInfo to get the next page.
|
|
2340
|
-
Use 'before' with the 'startCursor' from pageInfo to get the previous page.`,
|
|
2341
|
-
args: {
|
|
2342
|
-
project_id: z2.string().describe("The project ID or URL-encoded path"),
|
|
2343
|
-
issue_iid: z2.number().describe("The internal ID of the issue"),
|
|
2344
|
-
first: z2.number().optional().describe("Number of items to return from the beginning (default: 20, max: 100)"),
|
|
2345
|
-
after: z2.string().optional().describe("Cursor for forward pagination - use endCursor from previous response"),
|
|
2346
|
-
last: z2.number().optional().describe("Number of items to return from the end (for backward pagination)"),
|
|
2347
|
-
before: z2.string().optional().describe("Cursor for backward pagination - use startCursor from previous response")
|
|
2348
|
-
},
|
|
2349
|
-
execute: async (args, _ctx) => {
|
|
2350
|
-
const client = getGitLabClient();
|
|
2351
|
-
const result = await client.listIssueNotes(args.project_id, args.issue_iid, {
|
|
2352
|
-
first: args.first,
|
|
2353
|
-
after: args.after,
|
|
2354
|
-
last: args.last,
|
|
2355
|
-
before: args.before
|
|
2356
|
-
});
|
|
2357
|
-
return JSON.stringify(result, null, 2);
|
|
2358
|
-
}
|
|
2359
|
-
}),
|
|
2360
|
-
gitlab_get_issue_note: tool2({
|
|
2361
|
-
description: `Get a single note/comment from an issue by its ID.
|
|
2362
|
-
Returns the full details of a specific note including author, body, timestamps, and metadata.
|
|
2363
|
-
Useful when you need to retrieve a specific comment without fetching all notes.`,
|
|
2364
|
-
args: {
|
|
2365
|
-
project_id: z2.string().describe("The project ID or URL-encoded path"),
|
|
2366
|
-
issue_iid: z2.number().describe("The internal ID of the issue"),
|
|
2367
|
-
note_id: z2.number().describe("The ID of the note to retrieve")
|
|
2368
|
-
},
|
|
2369
|
-
execute: async (args, _ctx) => {
|
|
2370
|
-
const client = getGitLabClient();
|
|
2371
|
-
const note = await client.getIssueNote(args.project_id, args.issue_iid, args.note_id);
|
|
2372
|
-
return JSON.stringify(note, null, 2);
|
|
2373
|
-
}
|
|
2374
2306
|
})
|
|
2375
2307
|
};
|
|
2376
2308
|
|
|
@@ -2514,47 +2446,6 @@ Removes the association between the issue and the epic.`,
|
|
|
2514
2446
|
);
|
|
2515
2447
|
return JSON.stringify(result, null, 2);
|
|
2516
2448
|
}
|
|
2517
|
-
}),
|
|
2518
|
-
gitlab_list_epic_notes: tool3({
|
|
2519
|
-
description: `List all comments/notes on an epic using GraphQL API with pagination support.
|
|
2520
|
-
Returns all comments in chronological order.
|
|
2521
|
-
|
|
2522
|
-
The response includes pagination information (pageInfo) with cursors for fetching additional pages.
|
|
2523
|
-
Use 'after' with the 'endCursor' from pageInfo to get the next page.
|
|
2524
|
-
Use 'before' with the 'startCursor' from pageInfo to get the previous page.`,
|
|
2525
|
-
args: {
|
|
2526
|
-
group_id: z3.string().describe("The group ID or URL-encoded path"),
|
|
2527
|
-
epic_iid: z3.number().describe("The internal ID of the epic"),
|
|
2528
|
-
first: z3.number().optional().describe("Number of items to return from the beginning (default: 20, max: 100)"),
|
|
2529
|
-
after: z3.string().optional().describe("Cursor for forward pagination - use endCursor from previous response"),
|
|
2530
|
-
last: z3.number().optional().describe("Number of items to return from the end (for backward pagination)"),
|
|
2531
|
-
before: z3.string().optional().describe("Cursor for backward pagination - use startCursor from previous response")
|
|
2532
|
-
},
|
|
2533
|
-
execute: async (args, _ctx) => {
|
|
2534
|
-
const client = getGitLabClient();
|
|
2535
|
-
const result = await client.listEpicNotes(args.group_id, args.epic_iid, {
|
|
2536
|
-
first: args.first,
|
|
2537
|
-
after: args.after,
|
|
2538
|
-
last: args.last,
|
|
2539
|
-
before: args.before
|
|
2540
|
-
});
|
|
2541
|
-
return JSON.stringify(result, null, 2);
|
|
2542
|
-
}
|
|
2543
|
-
}),
|
|
2544
|
-
gitlab_get_epic_note: tool3({
|
|
2545
|
-
description: `Get a single note/comment from an epic by its ID.
|
|
2546
|
-
Returns the full details of a specific note including author, body, timestamps, and metadata.
|
|
2547
|
-
Useful when you need to retrieve a specific comment without fetching all notes.`,
|
|
2548
|
-
args: {
|
|
2549
|
-
group_id: z3.string().describe("The group ID or URL-encoded path"),
|
|
2550
|
-
epic_iid: z3.number().describe("The internal ID of the epic"),
|
|
2551
|
-
note_id: z3.number().describe("The ID of the note to retrieve")
|
|
2552
|
-
},
|
|
2553
|
-
execute: async (args, _ctx) => {
|
|
2554
|
-
const client = getGitLabClient();
|
|
2555
|
-
const note = await client.getEpicNote(args.group_id, args.epic_iid, args.note_id);
|
|
2556
|
-
return JSON.stringify(note, null, 2);
|
|
2557
|
-
}
|
|
2558
2449
|
})
|
|
2559
2450
|
};
|
|
2560
2451
|
|
|
@@ -3320,43 +3211,11 @@ Requires Developer role or higher.`,
|
|
|
3320
3211
|
})
|
|
3321
3212
|
};
|
|
3322
3213
|
|
|
3323
|
-
// src/tools/
|
|
3214
|
+
// src/tools/todos.ts
|
|
3324
3215
|
import { tool as tool9 } from "@opencode-ai/plugin";
|
|
3325
3216
|
var z9 = tool9.schema;
|
|
3326
|
-
var snippetTools = {
|
|
3327
|
-
gitlab_list_snippet_notes: tool9({
|
|
3328
|
-
description: `List all notes/comments on a project snippet using GraphQL API with pagination support.
|
|
3329
|
-
Returns all comments including system notes in chronological order.
|
|
3330
|
-
|
|
3331
|
-
The response includes pagination information (pageInfo) with cursors for fetching additional pages.
|
|
3332
|
-
Use 'after' with the 'endCursor' from pageInfo to get the next page.
|
|
3333
|
-
Use 'before' with the 'startCursor' from pageInfo to get the previous page.`,
|
|
3334
|
-
args: {
|
|
3335
|
-
project_id: z9.string().describe("The project ID or URL-encoded path"),
|
|
3336
|
-
snippet_id: z9.number().describe("The ID of the snippet"),
|
|
3337
|
-
first: z9.number().optional().describe("Number of items to return from the beginning (default: 20, max: 100)"),
|
|
3338
|
-
after: z9.string().optional().describe("Cursor for forward pagination - use endCursor from previous response"),
|
|
3339
|
-
last: z9.number().optional().describe("Number of items to return from the end (for backward pagination)"),
|
|
3340
|
-
before: z9.string().optional().describe("Cursor for backward pagination - use startCursor from previous response")
|
|
3341
|
-
},
|
|
3342
|
-
execute: async (args, _ctx) => {
|
|
3343
|
-
const client = getGitLabClient();
|
|
3344
|
-
const result = await client.listSnippetNotes(args.project_id, args.snippet_id, {
|
|
3345
|
-
first: args.first,
|
|
3346
|
-
after: args.after,
|
|
3347
|
-
last: args.last,
|
|
3348
|
-
before: args.before
|
|
3349
|
-
});
|
|
3350
|
-
return JSON.stringify(result, null, 2);
|
|
3351
|
-
}
|
|
3352
|
-
})
|
|
3353
|
-
};
|
|
3354
|
-
|
|
3355
|
-
// src/tools/todos.ts
|
|
3356
|
-
import { tool as tool10 } from "@opencode-ai/plugin";
|
|
3357
|
-
var z10 = tool10.schema;
|
|
3358
3217
|
var todoTools = {
|
|
3359
|
-
gitlab_list_todos:
|
|
3218
|
+
gitlab_list_todos: tool9({
|
|
3360
3219
|
description: `List TODO items for the current user using GraphQL API with pagination support.
|
|
3361
3220
|
Returns a list of pending or done TODO items assigned to the authenticated user.
|
|
3362
3221
|
TODOs are created when you are assigned to an issue/MR, mentioned in a comment, or when someone requests your review.
|
|
@@ -3365,7 +3224,7 @@ The response includes pagination information (pageInfo) with cursors for fetchin
|
|
|
3365
3224
|
Use 'after' with the 'endCursor' from pageInfo to get the next page.
|
|
3366
3225
|
Use 'before' with the 'startCursor' from pageInfo to get the previous page.`,
|
|
3367
3226
|
args: {
|
|
3368
|
-
action:
|
|
3227
|
+
action: z9.enum([
|
|
3369
3228
|
"assigned",
|
|
3370
3229
|
"mentioned",
|
|
3371
3230
|
"build_failed",
|
|
@@ -3376,15 +3235,15 @@ Use 'before' with the 'startCursor' from pageInfo to get the previous page.`,
|
|
|
3376
3235
|
"merge_train_removed",
|
|
3377
3236
|
"review_requested"
|
|
3378
3237
|
]).optional().describe("Filter by action type"),
|
|
3379
|
-
author_id:
|
|
3380
|
-
project_id:
|
|
3381
|
-
group_id:
|
|
3382
|
-
state:
|
|
3383
|
-
type:
|
|
3384
|
-
first:
|
|
3385
|
-
after:
|
|
3386
|
-
last:
|
|
3387
|
-
before:
|
|
3238
|
+
author_id: z9.number().optional().describe("Filter by author ID"),
|
|
3239
|
+
project_id: z9.string().optional().describe("Filter by project ID or path"),
|
|
3240
|
+
group_id: z9.string().optional().describe("Filter by group ID"),
|
|
3241
|
+
state: z9.enum(["pending", "done"]).optional().describe("Filter by state (default: pending)"),
|
|
3242
|
+
type: z9.enum(["Issue", "MergeRequest", "DesignManagement::Design", "Alert", "Epic", "Commit"]).optional().describe("Filter by target type"),
|
|
3243
|
+
first: z9.number().optional().describe("Number of items to return from the beginning (default: 20, max: 100)"),
|
|
3244
|
+
after: z9.string().optional().describe("Cursor for forward pagination - use endCursor from previous response"),
|
|
3245
|
+
last: z9.number().optional().describe("Number of items to return from the end (for backward pagination)"),
|
|
3246
|
+
before: z9.string().optional().describe("Cursor for backward pagination - use startCursor from previous response")
|
|
3388
3247
|
},
|
|
3389
3248
|
execute: async (args, _ctx) => {
|
|
3390
3249
|
const client = getGitLabClient();
|
|
@@ -3403,11 +3262,11 @@ Use 'before' with the 'startCursor' from pageInfo to get the previous page.`,
|
|
|
3403
3262
|
return JSON.stringify(result, null, 2);
|
|
3404
3263
|
}
|
|
3405
3264
|
}),
|
|
3406
|
-
gitlab_mark_todo_done:
|
|
3265
|
+
gitlab_mark_todo_done: tool9({
|
|
3407
3266
|
description: `Mark a specific TODO item as done.
|
|
3408
3267
|
Use this to mark a single TODO as completed.`,
|
|
3409
3268
|
args: {
|
|
3410
|
-
todo_id:
|
|
3269
|
+
todo_id: z9.number().describe("The ID of the TODO item to mark as done")
|
|
3411
3270
|
},
|
|
3412
3271
|
execute: async (args, _ctx) => {
|
|
3413
3272
|
const client = getGitLabClient();
|
|
@@ -3415,7 +3274,7 @@ Use this to mark a single TODO as completed.`,
|
|
|
3415
3274
|
return JSON.stringify(result, null, 2);
|
|
3416
3275
|
}
|
|
3417
3276
|
}),
|
|
3418
|
-
gitlab_mark_all_todos_done:
|
|
3277
|
+
gitlab_mark_all_todos_done: tool9({
|
|
3419
3278
|
description: `Mark all TODO items as done.
|
|
3420
3279
|
Use this to mark all pending TODOs for the current user as completed.`,
|
|
3421
3280
|
args: {},
|
|
@@ -3425,7 +3284,7 @@ Use this to mark all pending TODOs for the current user as completed.`,
|
|
|
3425
3284
|
return JSON.stringify(result, null, 2);
|
|
3426
3285
|
}
|
|
3427
3286
|
}),
|
|
3428
|
-
gitlab_get_todo_count:
|
|
3287
|
+
gitlab_get_todo_count: tool9({
|
|
3429
3288
|
description: `Get the count of pending TODO items.
|
|
3430
3289
|
Returns the total number of pending TODOs for the current user.`,
|
|
3431
3290
|
args: {},
|
|
@@ -3438,15 +3297,15 @@ Returns the total number of pending TODOs for the current user.`,
|
|
|
3438
3297
|
};
|
|
3439
3298
|
|
|
3440
3299
|
// src/tools/wikis.ts
|
|
3441
|
-
import { tool as
|
|
3442
|
-
var
|
|
3300
|
+
import { tool as tool10 } from "@opencode-ai/plugin";
|
|
3301
|
+
var z10 = tool10.schema;
|
|
3443
3302
|
var wikiTools = {
|
|
3444
|
-
gitlab_get_wiki_page:
|
|
3303
|
+
gitlab_get_wiki_page: tool10({
|
|
3445
3304
|
description: `Get a wiki page with its content.
|
|
3446
3305
|
Returns the wiki page content and metadata.`,
|
|
3447
3306
|
args: {
|
|
3448
|
-
project_id:
|
|
3449
|
-
slug:
|
|
3307
|
+
project_id: z10.string().describe("The project ID or URL-encoded path"),
|
|
3308
|
+
slug: z10.string().describe("The slug (URL-friendly name) of the wiki page")
|
|
3450
3309
|
},
|
|
3451
3310
|
execute: async (args, _ctx) => {
|
|
3452
3311
|
const client = getGitLabClient();
|
|
@@ -3457,15 +3316,15 @@ Returns the wiki page content and metadata.`,
|
|
|
3457
3316
|
};
|
|
3458
3317
|
|
|
3459
3318
|
// src/tools/work-items.ts
|
|
3460
|
-
import { tool as
|
|
3461
|
-
var
|
|
3319
|
+
import { tool as tool11 } from "@opencode-ai/plugin";
|
|
3320
|
+
var z11 = tool11.schema;
|
|
3462
3321
|
var workItemTools = {
|
|
3463
|
-
gitlab_get_work_item:
|
|
3322
|
+
gitlab_get_work_item: tool11({
|
|
3464
3323
|
description: `Get a single work item (issue, epic, task, etc.).
|
|
3465
3324
|
Work items are the new unified model for issues, epics, tasks, and other work tracking items in GitLab.`,
|
|
3466
3325
|
args: {
|
|
3467
|
-
project_id:
|
|
3468
|
-
work_item_id:
|
|
3326
|
+
project_id: z11.string().describe("The project ID or URL-encoded path"),
|
|
3327
|
+
work_item_id: z11.number().describe("The ID of the work item")
|
|
3469
3328
|
},
|
|
3470
3329
|
execute: async (args, _ctx) => {
|
|
3471
3330
|
const client = getGitLabClient();
|
|
@@ -3473,17 +3332,17 @@ Work items are the new unified model for issues, epics, tasks, and other work tr
|
|
|
3473
3332
|
return JSON.stringify(workItem, null, 2);
|
|
3474
3333
|
}
|
|
3475
3334
|
}),
|
|
3476
|
-
gitlab_list_work_items:
|
|
3335
|
+
gitlab_list_work_items: tool11({
|
|
3477
3336
|
description: `List work items in a project or group.
|
|
3478
3337
|
Work items include issues, epics, tasks, and other work tracking items.`,
|
|
3479
3338
|
args: {
|
|
3480
|
-
project_id:
|
|
3481
|
-
group_id:
|
|
3482
|
-
state:
|
|
3483
|
-
search:
|
|
3484
|
-
labels:
|
|
3485
|
-
work_item_type:
|
|
3486
|
-
limit:
|
|
3339
|
+
project_id: z11.string().optional().describe("The project ID or URL-encoded path"),
|
|
3340
|
+
group_id: z11.string().optional().describe("The group ID or URL-encoded path"),
|
|
3341
|
+
state: z11.enum(["opened", "closed", "all"]).optional().describe("Filter by state (default: opened)"),
|
|
3342
|
+
search: z11.string().optional().describe("Search work items by title or description"),
|
|
3343
|
+
labels: z11.string().optional().describe("Comma-separated list of labels to filter by"),
|
|
3344
|
+
work_item_type: z11.string().optional().describe("Filter by work item type (e.g., 'Issue', 'Epic', 'Task')"),
|
|
3345
|
+
limit: z11.number().optional().describe("Maximum number of results (default: 20)")
|
|
3487
3346
|
},
|
|
3488
3347
|
execute: async (args, _ctx) => {
|
|
3489
3348
|
const client = getGitLabClient();
|
|
@@ -3499,12 +3358,12 @@ Work items include issues, epics, tasks, and other work tracking items.`,
|
|
|
3499
3358
|
return JSON.stringify(workItems, null, 2);
|
|
3500
3359
|
}
|
|
3501
3360
|
}),
|
|
3502
|
-
gitlab_get_work_item_notes:
|
|
3361
|
+
gitlab_get_work_item_notes: tool11({
|
|
3503
3362
|
description: `Get all comments for a work item.
|
|
3504
3363
|
Returns all notes/comments on the work item in chronological order.`,
|
|
3505
3364
|
args: {
|
|
3506
|
-
project_id:
|
|
3507
|
-
work_item_id:
|
|
3365
|
+
project_id: z11.string().describe("The project ID or URL-encoded path"),
|
|
3366
|
+
work_item_id: z11.number().describe("The ID of the work item")
|
|
3508
3367
|
},
|
|
3509
3368
|
execute: async (args, _ctx) => {
|
|
3510
3369
|
const client = getGitLabClient();
|
|
@@ -3512,16 +3371,16 @@ Returns all notes/comments on the work item in chronological order.`,
|
|
|
3512
3371
|
return JSON.stringify(notes, null, 2);
|
|
3513
3372
|
}
|
|
3514
3373
|
}),
|
|
3515
|
-
gitlab_create_work_item:
|
|
3374
|
+
gitlab_create_work_item: tool11({
|
|
3516
3375
|
description: `Create a new work item (issue, task, etc.).
|
|
3517
3376
|
Work items are the new unified model for issues, epics, tasks, and other work tracking items.`,
|
|
3518
3377
|
args: {
|
|
3519
|
-
project_id:
|
|
3520
|
-
title:
|
|
3521
|
-
work_item_type_id:
|
|
3522
|
-
description:
|
|
3523
|
-
labels:
|
|
3524
|
-
assignee_ids:
|
|
3378
|
+
project_id: z11.string().describe("The project ID or URL-encoded path"),
|
|
3379
|
+
title: z11.string().describe("The title of the work item"),
|
|
3380
|
+
work_item_type_id: z11.number().describe("The ID of the work item type (e.g., 1 for Issue, 2 for Task)"),
|
|
3381
|
+
description: z11.string().optional().describe("The description of the work item (supports Markdown)"),
|
|
3382
|
+
labels: z11.array(z11.string()).optional().describe("Array of label names"),
|
|
3383
|
+
assignee_ids: z11.array(z11.number()).optional().describe("Array of user IDs to assign")
|
|
3525
3384
|
},
|
|
3526
3385
|
execute: async (args, _ctx) => {
|
|
3527
3386
|
const client = getGitLabClient();
|
|
@@ -3535,17 +3394,17 @@ Work items are the new unified model for issues, epics, tasks, and other work tr
|
|
|
3535
3394
|
return JSON.stringify(workItem, null, 2);
|
|
3536
3395
|
}
|
|
3537
3396
|
}),
|
|
3538
|
-
gitlab_update_work_item:
|
|
3397
|
+
gitlab_update_work_item: tool11({
|
|
3539
3398
|
description: `Update an existing work item.
|
|
3540
3399
|
Can update title, description, state, labels, and assignees.`,
|
|
3541
3400
|
args: {
|
|
3542
|
-
project_id:
|
|
3543
|
-
work_item_id:
|
|
3544
|
-
title:
|
|
3545
|
-
description:
|
|
3546
|
-
state_event:
|
|
3547
|
-
labels:
|
|
3548
|
-
assignee_ids:
|
|
3401
|
+
project_id: z11.string().describe("The project ID or URL-encoded path"),
|
|
3402
|
+
work_item_id: z11.number().describe("The ID of the work item"),
|
|
3403
|
+
title: z11.string().optional().describe("The new title"),
|
|
3404
|
+
description: z11.string().optional().describe("The new description (supports Markdown)"),
|
|
3405
|
+
state_event: z11.enum(["close", "reopen"]).optional().describe("Change the state (close or reopen)"),
|
|
3406
|
+
labels: z11.array(z11.string()).optional().describe("Array of label names"),
|
|
3407
|
+
assignee_ids: z11.array(z11.number()).optional().describe("Array of user IDs to assign")
|
|
3549
3408
|
},
|
|
3550
3409
|
execute: async (args, _ctx) => {
|
|
3551
3410
|
const client = getGitLabClient();
|
|
@@ -3559,12 +3418,12 @@ Can update title, description, state, labels, and assignees.`,
|
|
|
3559
3418
|
return JSON.stringify(workItem, null, 2);
|
|
3560
3419
|
}
|
|
3561
3420
|
}),
|
|
3562
|
-
gitlab_create_work_item_note:
|
|
3421
|
+
gitlab_create_work_item_note: tool11({
|
|
3563
3422
|
description: `Create a comment on a work item.`,
|
|
3564
3423
|
args: {
|
|
3565
|
-
project_id:
|
|
3566
|
-
work_item_id:
|
|
3567
|
-
body:
|
|
3424
|
+
project_id: z11.string().describe("The project ID or URL-encoded path"),
|
|
3425
|
+
work_item_id: z11.number().describe("The ID of the work item"),
|
|
3426
|
+
body: z11.string().describe("The content of the note/comment (supports Markdown)")
|
|
3568
3427
|
},
|
|
3569
3428
|
execute: async (args, _ctx) => {
|
|
3570
3429
|
const client = getGitLabClient();
|
|
@@ -3575,17 +3434,17 @@ Can update title, description, state, labels, and assignees.`,
|
|
|
3575
3434
|
};
|
|
3576
3435
|
|
|
3577
3436
|
// src/tools/discussions-unified.ts
|
|
3578
|
-
import { tool as
|
|
3579
|
-
var
|
|
3580
|
-
var positionSchema =
|
|
3581
|
-
base_sha:
|
|
3582
|
-
start_sha:
|
|
3583
|
-
head_sha:
|
|
3584
|
-
position_type:
|
|
3585
|
-
old_path:
|
|
3586
|
-
new_path:
|
|
3587
|
-
old_line:
|
|
3588
|
-
new_line:
|
|
3437
|
+
import { tool as tool12 } from "@opencode-ai/plugin";
|
|
3438
|
+
var z12 = tool12.schema;
|
|
3439
|
+
var positionSchema = z12.object({
|
|
3440
|
+
base_sha: z12.string().describe("SHA of the base commit"),
|
|
3441
|
+
start_sha: z12.string().describe("SHA of the start commit"),
|
|
3442
|
+
head_sha: z12.string().describe("SHA of the head commit"),
|
|
3443
|
+
position_type: z12.enum(["text", "image"]).describe("Type of position"),
|
|
3444
|
+
old_path: z12.string().optional().describe("Path of the file before changes"),
|
|
3445
|
+
new_path: z12.string().optional().describe("Path of the file after changes"),
|
|
3446
|
+
old_line: z12.number().optional().describe("Line number in the old version"),
|
|
3447
|
+
new_line: z12.number().optional().describe("Line number in the new version")
|
|
3589
3448
|
});
|
|
3590
3449
|
function validateResourceParams(resourceType, args) {
|
|
3591
3450
|
switch (resourceType) {
|
|
@@ -3612,7 +3471,7 @@ var discussionsUnifiedTools = {
|
|
|
3612
3471
|
/**
|
|
3613
3472
|
* List discussions for any GitLab resource type
|
|
3614
3473
|
*/
|
|
3615
|
-
gitlab_list_discussions:
|
|
3474
|
+
gitlab_list_discussions: tool12({
|
|
3616
3475
|
description: `List discussions (comment threads) on any GitLab resource.
|
|
3617
3476
|
Supports: merge_requests, issues, epics, commits, snippets.
|
|
3618
3477
|
|
|
@@ -3628,17 +3487,17 @@ Examples:
|
|
|
3628
3487
|
- Commit: resource_type="commit", project_id="group/project", sha="abc123"
|
|
3629
3488
|
- Snippet: resource_type="snippet", project_id="group/project", snippet_id=789`,
|
|
3630
3489
|
args: {
|
|
3631
|
-
resource_type:
|
|
3632
|
-
project_id:
|
|
3633
|
-
group_id:
|
|
3634
|
-
iid:
|
|
3635
|
-
sha:
|
|
3636
|
-
snippet_id:
|
|
3490
|
+
resource_type: z12.enum(["merge_request", "issue", "epic", "commit", "snippet"]).describe("Type of GitLab resource"),
|
|
3491
|
+
project_id: z12.string().optional().describe("Project ID or path. Required for merge_request, issue, commit, snippet"),
|
|
3492
|
+
group_id: z12.string().optional().describe("Group ID or path. Required for epic"),
|
|
3493
|
+
iid: z12.number().optional().describe("Internal ID of the resource (for merge_request, issue, epic)"),
|
|
3494
|
+
sha: z12.string().optional().describe("Commit SHA (required for commit)"),
|
|
3495
|
+
snippet_id: z12.number().optional().describe("Snippet ID (required for snippet)"),
|
|
3637
3496
|
// Pagination
|
|
3638
|
-
first:
|
|
3639
|
-
after:
|
|
3640
|
-
before:
|
|
3641
|
-
last:
|
|
3497
|
+
first: z12.number().optional().describe("Number of items to return (default: 20)"),
|
|
3498
|
+
after: z12.string().optional().describe("Cursor for pagination - use endCursor from previous response"),
|
|
3499
|
+
before: z12.string().optional().describe("Cursor for backward pagination"),
|
|
3500
|
+
last: z12.number().optional().describe("Number of items from the end")
|
|
3642
3501
|
},
|
|
3643
3502
|
execute: async (args, _ctx) => {
|
|
3644
3503
|
validateResourceParams(args.resource_type, args);
|
|
@@ -3692,7 +3551,7 @@ Examples:
|
|
|
3692
3551
|
/**
|
|
3693
3552
|
* Get a specific discussion thread from any GitLab resource
|
|
3694
3553
|
*/
|
|
3695
|
-
gitlab_get_discussion:
|
|
3554
|
+
gitlab_get_discussion: tool12({
|
|
3696
3555
|
description: `Get a specific discussion thread with all its replies.
|
|
3697
3556
|
Returns the discussion with its 'notes' array containing all comments.
|
|
3698
3557
|
|
|
@@ -3705,13 +3564,13 @@ Required parameters vary by resource type:
|
|
|
3705
3564
|
- commit: project_id, sha, discussion_id
|
|
3706
3565
|
- snippet: project_id, snippet_id, discussion_id`,
|
|
3707
3566
|
args: {
|
|
3708
|
-
resource_type:
|
|
3709
|
-
discussion_id:
|
|
3710
|
-
project_id:
|
|
3711
|
-
group_id:
|
|
3712
|
-
iid:
|
|
3713
|
-
sha:
|
|
3714
|
-
snippet_id:
|
|
3567
|
+
resource_type: z12.enum(["merge_request", "issue", "epic", "commit", "snippet"]).describe("Type of GitLab resource"),
|
|
3568
|
+
discussion_id: z12.string().describe("The ID of the discussion thread"),
|
|
3569
|
+
project_id: z12.string().optional().describe("Project ID or path"),
|
|
3570
|
+
group_id: z12.string().optional().describe("Group ID or path (for epic)"),
|
|
3571
|
+
iid: z12.number().optional().describe("Internal ID (for merge_request, issue, epic)"),
|
|
3572
|
+
sha: z12.string().optional().describe("Commit SHA (for commit)"),
|
|
3573
|
+
snippet_id: z12.number().optional().describe("Snippet ID (for snippet)")
|
|
3715
3574
|
},
|
|
3716
3575
|
execute: async (args, _ctx) => {
|
|
3717
3576
|
validateResourceParams(args.resource_type, args);
|
|
@@ -3759,7 +3618,7 @@ Required parameters vary by resource type:
|
|
|
3759
3618
|
/**
|
|
3760
3619
|
* Create a new discussion thread or reply to an existing one
|
|
3761
3620
|
*/
|
|
3762
|
-
gitlab_create_discussion:
|
|
3621
|
+
gitlab_create_discussion: tool12({
|
|
3763
3622
|
description: `Create a new discussion thread or reply to an existing one.
|
|
3764
3623
|
|
|
3765
3624
|
For NEW discussion: Omit discussion_id
|
|
@@ -3772,14 +3631,14 @@ Examples:
|
|
|
3772
3631
|
- Reply to thread: resource_type="merge_request", ..., discussion_id="...", body="..."
|
|
3773
3632
|
- Code comment: resource_type="merge_request", ..., body="...", position={base_sha, head_sha, ...}`,
|
|
3774
3633
|
args: {
|
|
3775
|
-
resource_type:
|
|
3776
|
-
body:
|
|
3777
|
-
project_id:
|
|
3778
|
-
group_id:
|
|
3779
|
-
iid:
|
|
3780
|
-
sha:
|
|
3781
|
-
snippet_id:
|
|
3782
|
-
discussion_id:
|
|
3634
|
+
resource_type: z12.enum(["merge_request", "issue", "epic", "commit", "snippet"]).describe("Type of GitLab resource"),
|
|
3635
|
+
body: z12.string().describe("The comment text (Markdown supported)"),
|
|
3636
|
+
project_id: z12.string().optional().describe("Project ID or path"),
|
|
3637
|
+
group_id: z12.string().optional().describe("Group ID or path (for epic)"),
|
|
3638
|
+
iid: z12.number().optional().describe("Internal ID (for merge_request, issue, epic)"),
|
|
3639
|
+
sha: z12.string().optional().describe("Commit SHA (for commit)"),
|
|
3640
|
+
snippet_id: z12.number().optional().describe("Snippet ID (for snippet)"),
|
|
3641
|
+
discussion_id: z12.string().optional().describe("If provided, replies to existing discussion. If omitted, creates new thread"),
|
|
3783
3642
|
position: positionSchema.optional().describe("Position for code-specific comments (MR/commit only)")
|
|
3784
3643
|
},
|
|
3785
3644
|
execute: async (args, _ctx) => {
|
|
@@ -3844,17 +3703,17 @@ Examples:
|
|
|
3844
3703
|
/**
|
|
3845
3704
|
* Resolve or unresolve a discussion thread
|
|
3846
3705
|
*/
|
|
3847
|
-
gitlab_resolve_discussion:
|
|
3706
|
+
gitlab_resolve_discussion: tool12({
|
|
3848
3707
|
description: `Mark a discussion thread as resolved or unresolve it.
|
|
3849
3708
|
Only works for resolvable discussions (MRs and issues only).
|
|
3850
3709
|
|
|
3851
3710
|
Use after addressing feedback to indicate the discussion is complete.`,
|
|
3852
3711
|
args: {
|
|
3853
|
-
resource_type:
|
|
3854
|
-
action:
|
|
3855
|
-
discussion_id:
|
|
3856
|
-
project_id:
|
|
3857
|
-
iid:
|
|
3712
|
+
resource_type: z12.enum(["merge_request", "issue"]).describe("Type of resource (only MR and issue discussions can be resolved)"),
|
|
3713
|
+
action: z12.enum(["resolve", "unresolve"]).describe("Whether to resolve or unresolve"),
|
|
3714
|
+
discussion_id: z12.string().describe("The ID of the discussion thread"),
|
|
3715
|
+
project_id: z12.string().describe("Project ID or path"),
|
|
3716
|
+
iid: z12.number().describe("Internal ID of the MR or issue")
|
|
3858
3717
|
},
|
|
3859
3718
|
execute: async (args, _ctx) => {
|
|
3860
3719
|
const client = getGitLabClient();
|
|
@@ -3893,6 +3752,224 @@ Use after addressing feedback to indicate the discussion is complete.`,
|
|
|
3893
3752
|
})
|
|
3894
3753
|
};
|
|
3895
3754
|
|
|
3755
|
+
// src/tools/notes-unified.ts
|
|
3756
|
+
import { tool as tool13 } from "@opencode-ai/plugin";
|
|
3757
|
+
var z13 = tool13.schema;
|
|
3758
|
+
var VALID_LIST_CREATE_TYPES = ["merge_request", "issue", "epic", "snippet"];
|
|
3759
|
+
var VALID_GET_NOTE_TYPES = ["issue", "epic"];
|
|
3760
|
+
function validationError(param, resourceType) {
|
|
3761
|
+
return new Error(
|
|
3762
|
+
`Missing required parameter: '${param}' is required for resource_type '${resourceType}'`
|
|
3763
|
+
);
|
|
3764
|
+
}
|
|
3765
|
+
function validateListCreateParams(resourceType, args) {
|
|
3766
|
+
if (!VALID_LIST_CREATE_TYPES.includes(resourceType)) {
|
|
3767
|
+
throw new Error(
|
|
3768
|
+
`Invalid resource_type '${resourceType}'. Must be one of: ${VALID_LIST_CREATE_TYPES.join(", ")}`
|
|
3769
|
+
);
|
|
3770
|
+
}
|
|
3771
|
+
switch (resourceType) {
|
|
3772
|
+
case "merge_request":
|
|
3773
|
+
case "issue":
|
|
3774
|
+
if (!args.project_id) throw validationError("project_id", resourceType);
|
|
3775
|
+
if (args.iid == null) throw validationError("iid", resourceType);
|
|
3776
|
+
break;
|
|
3777
|
+
case "epic":
|
|
3778
|
+
if (!args.group_id) throw validationError("group_id", resourceType);
|
|
3779
|
+
if (args.iid == null) throw validationError("iid", resourceType);
|
|
3780
|
+
break;
|
|
3781
|
+
case "snippet":
|
|
3782
|
+
if (!args.project_id) throw validationError("project_id", resourceType);
|
|
3783
|
+
if (args.snippet_id == null) throw validationError("snippet_id", resourceType);
|
|
3784
|
+
break;
|
|
3785
|
+
}
|
|
3786
|
+
}
|
|
3787
|
+
function validateGetNoteParams(resourceType, args) {
|
|
3788
|
+
if (!VALID_GET_NOTE_TYPES.includes(resourceType)) {
|
|
3789
|
+
throw new Error(
|
|
3790
|
+
`Invalid resource_type '${resourceType}'. Must be one of: ${VALID_GET_NOTE_TYPES.join(", ")}`
|
|
3791
|
+
);
|
|
3792
|
+
}
|
|
3793
|
+
if (args.note_id == null) throw validationError("note_id", resourceType);
|
|
3794
|
+
switch (resourceType) {
|
|
3795
|
+
case "issue":
|
|
3796
|
+
if (!args.project_id) throw validationError("project_id", resourceType);
|
|
3797
|
+
if (args.iid == null) throw validationError("iid", resourceType);
|
|
3798
|
+
break;
|
|
3799
|
+
case "epic":
|
|
3800
|
+
if (!args.group_id) throw validationError("group_id", resourceType);
|
|
3801
|
+
if (args.iid == null) throw validationError("iid", resourceType);
|
|
3802
|
+
break;
|
|
3803
|
+
}
|
|
3804
|
+
}
|
|
3805
|
+
var notesUnifiedTools = {
|
|
3806
|
+
/**
|
|
3807
|
+
* List notes/comments for any GitLab resource type
|
|
3808
|
+
*/
|
|
3809
|
+
gitlab_list_notes: tool13({
|
|
3810
|
+
description: `List all notes/comments on any GitLab resource using GraphQL API with pagination support.
|
|
3811
|
+
Returns all comments including system notes in chronological order.
|
|
3812
|
+
This is easier to read than discussions which have nested structure.
|
|
3813
|
+
|
|
3814
|
+
The response includes pagination information (pageInfo) with cursors for fetching additional pages.
|
|
3815
|
+
Use 'after' with the 'endCursor' from pageInfo to get the next page.
|
|
3816
|
+
Use 'before' with the 'startCursor' from pageInfo to get the previous page.
|
|
3817
|
+
|
|
3818
|
+
Examples:
|
|
3819
|
+
- MR: resource_type="merge_request", project_id="group/project", iid=123
|
|
3820
|
+
- Issue: resource_type="issue", project_id="group/project", iid=456
|
|
3821
|
+
- Epic: resource_type="epic", group_id="my-group", iid=1
|
|
3822
|
+
- Snippet: resource_type="snippet", project_id="group/project", snippet_id=789`,
|
|
3823
|
+
args: {
|
|
3824
|
+
resource_type: z13.enum(["merge_request", "issue", "epic", "snippet"]).describe("Type of GitLab resource"),
|
|
3825
|
+
project_id: z13.string().optional().describe("Project ID or path. Required for merge_request, issue, snippet"),
|
|
3826
|
+
group_id: z13.string().optional().describe("Group ID or path. Required for epic"),
|
|
3827
|
+
iid: z13.number().optional().describe("Internal ID of the resource (for merge_request, issue, epic)"),
|
|
3828
|
+
snippet_id: z13.number().optional().describe("Snippet ID (required for snippet)"),
|
|
3829
|
+
// Pagination
|
|
3830
|
+
first: z13.number().optional().describe("Number of items to return from the beginning (default: 20, max: 100)"),
|
|
3831
|
+
after: z13.string().optional().describe("Cursor for forward pagination - use endCursor from previous response"),
|
|
3832
|
+
last: z13.number().optional().describe("Number of items to return from the end (for backward pagination)"),
|
|
3833
|
+
before: z13.string().optional().describe("Cursor for backward pagination - use startCursor from previous response")
|
|
3834
|
+
},
|
|
3835
|
+
execute: async (args, _ctx) => {
|
|
3836
|
+
validateListCreateParams(args.resource_type, args);
|
|
3837
|
+
const client = getGitLabClient();
|
|
3838
|
+
const paginationOptions = {
|
|
3839
|
+
first: args.first,
|
|
3840
|
+
after: args.after,
|
|
3841
|
+
last: args.last,
|
|
3842
|
+
before: args.before
|
|
3843
|
+
};
|
|
3844
|
+
switch (args.resource_type) {
|
|
3845
|
+
case "merge_request":
|
|
3846
|
+
return JSON.stringify(
|
|
3847
|
+
await client.listMrNotes(args.project_id, args.iid, paginationOptions),
|
|
3848
|
+
null,
|
|
3849
|
+
2
|
|
3850
|
+
);
|
|
3851
|
+
case "issue":
|
|
3852
|
+
return JSON.stringify(
|
|
3853
|
+
await client.listIssueNotes(args.project_id, args.iid, paginationOptions),
|
|
3854
|
+
null,
|
|
3855
|
+
2
|
|
3856
|
+
);
|
|
3857
|
+
case "epic":
|
|
3858
|
+
return JSON.stringify(
|
|
3859
|
+
await client.listEpicNotes(args.group_id, args.iid, paginationOptions),
|
|
3860
|
+
null,
|
|
3861
|
+
2
|
|
3862
|
+
);
|
|
3863
|
+
case "snippet":
|
|
3864
|
+
return JSON.stringify(
|
|
3865
|
+
await client.listSnippetNotes(args.project_id, args.snippet_id, paginationOptions),
|
|
3866
|
+
null,
|
|
3867
|
+
2
|
|
3868
|
+
);
|
|
3869
|
+
default:
|
|
3870
|
+
throw new Error(`Unsupported resource type: ${args.resource_type}`);
|
|
3871
|
+
}
|
|
3872
|
+
}
|
|
3873
|
+
}),
|
|
3874
|
+
/**
|
|
3875
|
+
* Get a single note/comment by its ID
|
|
3876
|
+
*/
|
|
3877
|
+
gitlab_get_note: tool13({
|
|
3878
|
+
description: `Get a single note/comment from an issue or epic by its ID.
|
|
3879
|
+
Returns the full details of a specific note including author, body, timestamps, and metadata.
|
|
3880
|
+
Useful when you need to retrieve a specific comment without fetching all notes.
|
|
3881
|
+
|
|
3882
|
+
Supports: issues, epics (MR notes use discussions API)
|
|
3883
|
+
|
|
3884
|
+
Examples:
|
|
3885
|
+
- Issue note: resource_type="issue", project_id="group/project", iid=456, note_id=123
|
|
3886
|
+
- Epic note: resource_type="epic", group_id="my-group", iid=1, note_id=456`,
|
|
3887
|
+
args: {
|
|
3888
|
+
resource_type: z13.enum(["issue", "epic"]).describe("Type of GitLab resource (issue or epic only)"),
|
|
3889
|
+
note_id: z13.number().describe("The ID of the note to retrieve"),
|
|
3890
|
+
project_id: z13.string().optional().describe("Project ID or path. Required for issue"),
|
|
3891
|
+
group_id: z13.string().optional().describe("Group ID or path. Required for epic"),
|
|
3892
|
+
iid: z13.number().describe("Internal ID of the issue or epic")
|
|
3893
|
+
},
|
|
3894
|
+
execute: async (args, _ctx) => {
|
|
3895
|
+
validateGetNoteParams(args.resource_type, args);
|
|
3896
|
+
const client = getGitLabClient();
|
|
3897
|
+
switch (args.resource_type) {
|
|
3898
|
+
case "issue":
|
|
3899
|
+
return JSON.stringify(
|
|
3900
|
+
await client.getIssueNote(args.project_id, args.iid, args.note_id),
|
|
3901
|
+
null,
|
|
3902
|
+
2
|
|
3903
|
+
);
|
|
3904
|
+
case "epic":
|
|
3905
|
+
return JSON.stringify(
|
|
3906
|
+
await client.getEpicNote(args.group_id, args.iid, args.note_id),
|
|
3907
|
+
null,
|
|
3908
|
+
2
|
|
3909
|
+
);
|
|
3910
|
+
default:
|
|
3911
|
+
throw new Error(`Unsupported resource type: ${args.resource_type}`);
|
|
3912
|
+
}
|
|
3913
|
+
}
|
|
3914
|
+
}),
|
|
3915
|
+
/**
|
|
3916
|
+
* Create a simple note/comment on any GitLab resource
|
|
3917
|
+
*/
|
|
3918
|
+
gitlab_create_note: tool13({
|
|
3919
|
+
description: `Add a simple comment/note to any GitLab resource.
|
|
3920
|
+
Creates a standalone comment (not part of a thread).
|
|
3921
|
+
|
|
3922
|
+
For replying to existing discussion threads, use gitlab_create_discussion
|
|
3923
|
+
with discussion_id parameter instead.
|
|
3924
|
+
|
|
3925
|
+
Examples:
|
|
3926
|
+
- MR comment: resource_type="merge_request", project_id="group/project", iid=123, body="LGTM!"
|
|
3927
|
+
- Issue comment: resource_type="issue", project_id="group/project", iid=456, body="Working on this"
|
|
3928
|
+
- Epic comment: resource_type="epic", group_id="my-group", iid=1, body="Planning complete"
|
|
3929
|
+
- Snippet comment: resource_type="snippet", project_id="group/project", snippet_id=789, body="Nice code!"`,
|
|
3930
|
+
args: {
|
|
3931
|
+
resource_type: z13.enum(["merge_request", "issue", "epic", "snippet"]).describe("Type of GitLab resource"),
|
|
3932
|
+
body: z13.string().describe("The content of the note/comment (supports Markdown)"),
|
|
3933
|
+
project_id: z13.string().optional().describe("Project ID or path. Required for merge_request, issue, snippet"),
|
|
3934
|
+
group_id: z13.string().optional().describe("Group ID or path. Required for epic"),
|
|
3935
|
+
iid: z13.number().optional().describe("Internal ID of the resource (for merge_request, issue, epic)"),
|
|
3936
|
+
snippet_id: z13.number().optional().describe("Snippet ID (required for snippet)")
|
|
3937
|
+
},
|
|
3938
|
+
execute: async (args, _ctx) => {
|
|
3939
|
+
validateListCreateParams(args.resource_type, args);
|
|
3940
|
+
const client = getGitLabClient();
|
|
3941
|
+
switch (args.resource_type) {
|
|
3942
|
+
case "merge_request":
|
|
3943
|
+
return JSON.stringify(
|
|
3944
|
+
await client.createMrNote(args.project_id, args.iid, args.body),
|
|
3945
|
+
null,
|
|
3946
|
+
2
|
|
3947
|
+
);
|
|
3948
|
+
case "issue":
|
|
3949
|
+
return JSON.stringify(
|
|
3950
|
+
await client.createIssueNote(args.project_id, args.iid, args.body),
|
|
3951
|
+
null,
|
|
3952
|
+
2
|
|
3953
|
+
);
|
|
3954
|
+
case "epic":
|
|
3955
|
+
return JSON.stringify(
|
|
3956
|
+
await client.createEpicNote(args.group_id, args.iid, args.body),
|
|
3957
|
+
null,
|
|
3958
|
+
2
|
|
3959
|
+
);
|
|
3960
|
+
case "snippet":
|
|
3961
|
+
return JSON.stringify(
|
|
3962
|
+
await client.createSnippetNote(args.project_id, args.snippet_id, args.body),
|
|
3963
|
+
null,
|
|
3964
|
+
2
|
|
3965
|
+
);
|
|
3966
|
+
default:
|
|
3967
|
+
throw new Error(`Unsupported resource type: ${args.resource_type}`);
|
|
3968
|
+
}
|
|
3969
|
+
}
|
|
3970
|
+
})
|
|
3971
|
+
};
|
|
3972
|
+
|
|
3896
3973
|
// src/tools/git.ts
|
|
3897
3974
|
import { tool as tool14 } from "@opencode-ai/plugin";
|
|
3898
3975
|
|
|
@@ -4249,8 +4326,6 @@ var gitlabPlugin = async (_input) => {
|
|
|
4249
4326
|
...userTools,
|
|
4250
4327
|
// Security Tools
|
|
4251
4328
|
...securityTools,
|
|
4252
|
-
// Snippet Tools
|
|
4253
|
-
...snippetTools,
|
|
4254
4329
|
// TODO Tools
|
|
4255
4330
|
...todoTools,
|
|
4256
4331
|
// Wiki Tools
|
|
@@ -4259,6 +4334,8 @@ var gitlabPlugin = async (_input) => {
|
|
|
4259
4334
|
...workItemTools,
|
|
4260
4335
|
// Unified Discussion Tools (covers MR, issue, epic, commit, snippet discussions)
|
|
4261
4336
|
...discussionsUnifiedTools,
|
|
4337
|
+
// Unified Notes Tools (covers MR, issue, epic, snippet notes)
|
|
4338
|
+
...notesUnifiedTools,
|
|
4262
4339
|
// Git Tools
|
|
4263
4340
|
...gitTools,
|
|
4264
4341
|
// Audit Tools
|
package/package.json
CHANGED
|
Binary file
|