@gitlab/opencode-gitlab-plugin 1.5.5 → 1.5.7
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 +15 -0
- package/README.md +16 -27
- package/dist/gitlab-opencode-gitlab-plugin-1.5.7.tgz +0 -0
- package/dist/index.js +221 -273
- package/package.json +1 -1
- package/dist/gitlab-opencode-gitlab-plugin-1.5.5.tgz +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
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.7](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin/compare/v1.5.6...v1.5.7) (2026-02-03)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### ♻️ Code Refactoring
|
|
9
|
+
|
|
10
|
+
* consolidate epic issue management tools into unified interface ([b8708d7](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin/commit/b8708d7fa65e4fcc5fda0e46daaf2391d8bbc094))
|
|
11
|
+
|
|
12
|
+
## [1.5.6](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin/compare/v1.5.5...v1.5.6) (2026-02-03)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### ♻️ Code Refactoring
|
|
16
|
+
|
|
17
|
+
* consolidate search tools into unified interface ([bb75def](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin/commit/bb75def68290ea740a04d09afc5d7efa9da02020))
|
|
18
|
+
* implement GitLab Duo review suggestions ([8fa6738](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin/commit/8fa67382436d8edb9bce1868c3330d8853255606))
|
|
19
|
+
|
|
5
20
|
## [1.5.5](https://gitlab.com/gitlab-org/editor-extensions/opencode-gitlab-plugin/compare/v1.5.4...v1.5.5) (2026-02-03)
|
|
6
21
|
|
|
7
22
|
|
package/README.md
CHANGED
|
@@ -134,7 +134,7 @@ graph LR
|
|
|
134
134
|
B --> B1[readTokenFromAuthStorage]
|
|
135
135
|
B --> B2[getGitLabClient]
|
|
136
136
|
|
|
137
|
-
C --> C1[
|
|
137
|
+
C --> C1[69 Tool Definitions]
|
|
138
138
|
|
|
139
139
|
D --> A
|
|
140
140
|
D --> B
|
|
@@ -287,7 +287,7 @@ Or for API tokens:
|
|
|
287
287
|
|
|
288
288
|
## 🛠️ Available Tools
|
|
289
289
|
|
|
290
|
-
The plugin provides **
|
|
290
|
+
The plugin provides **67 tools** organized into the following categories:
|
|
291
291
|
|
|
292
292
|
### Merge Request Tools (9 tools)
|
|
293
293
|
|
|
@@ -311,17 +311,15 @@ The plugin provides **78 tools** organized into the following categories:
|
|
|
311
311
|
| `gitlab_get_issue` | Get issue details including state, author, assignees, labels, and comments |
|
|
312
312
|
| `gitlab_list_issues` | List issues with filtering by state, labels, assignee, and milestone |
|
|
313
313
|
|
|
314
|
-
### Epic Tools (
|
|
314
|
+
### Epic Tools (5 tools)
|
|
315
315
|
|
|
316
|
-
| Tool
|
|
317
|
-
|
|
|
318
|
-
| `gitlab_get_epic`
|
|
319
|
-
| `gitlab_list_epics`
|
|
320
|
-
| `gitlab_create_epic`
|
|
321
|
-
| `gitlab_update_epic`
|
|
322
|
-
| `
|
|
323
|
-
| `gitlab_add_issue_to_epic` | Link an issue to an epic |
|
|
324
|
-
| `gitlab_remove_issue_from_epic` | Unlink an issue from an epic |
|
|
316
|
+
| Tool | Description |
|
|
317
|
+
| --------------------------- | ----------------------------------------------------------------------------- |
|
|
318
|
+
| `gitlab_get_epic` | Get epic details with title, description, state, dates, and associated issues |
|
|
319
|
+
| `gitlab_list_epics` | List epics with filtering by state, author, and labels |
|
|
320
|
+
| `gitlab_create_epic` | Create a new epic in a group |
|
|
321
|
+
| `gitlab_update_epic` | Update epic title, description, labels, dates, and state |
|
|
322
|
+
| `gitlab_manage_epic_issues` | Manage issues linked to an epic (list, add, remove) with action parameter |
|
|
325
323
|
|
|
326
324
|
### Pipeline Tools (8 tools)
|
|
327
325
|
|
|
@@ -348,21 +346,12 @@ The plugin provides **78 tools** organized into the following categories:
|
|
|
348
346
|
| `gitlab_list_branches` | List all branches in a repository |
|
|
349
347
|
| `gitlab_get_commit_comments` | Get all commit comments in flat structure |
|
|
350
348
|
|
|
351
|
-
### Search Tools (
|
|
352
|
-
|
|
353
|
-
| Tool | Description
|
|
354
|
-
| ----------------------------- |
|
|
355
|
-
| `gitlab_search` |
|
|
356
|
-
| `
|
|
357
|
-
| `gitlab_merge_request_search` | Specialized merge request search with better filtering |
|
|
358
|
-
| `gitlab_blob_search` | Search code/text within repository files |
|
|
359
|
-
| `gitlab_commit_search` | Search commits by message, author, or SHA |
|
|
360
|
-
| `gitlab_group_project_search` | Search projects within a specific group |
|
|
361
|
-
| `gitlab_milestone_search` | Search milestones by title or description |
|
|
362
|
-
| `gitlab_note_search` | Search comments across issues, MRs, and commits (Premium/Ultimate) |
|
|
363
|
-
| `gitlab_user_search` | Search users by name or email |
|
|
364
|
-
| `gitlab_wiki_blob_search` | Search wiki content with advanced filters |
|
|
365
|
-
| `gitlab_documentation_search` | Search GitLab official documentation |
|
|
349
|
+
### Search Tools (2 tools)
|
|
350
|
+
|
|
351
|
+
| Tool | Description |
|
|
352
|
+
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
353
|
+
| `gitlab_search` | Unified search across all GitLab resources with scope-specific options (projects, issues, merge_requests, milestones, users, blobs, commits, notes, wiki_blobs, group_projects) |
|
|
354
|
+
| `gitlab_documentation_search` | Search GitLab official documentation at docs.gitlab.com |
|
|
366
355
|
|
|
367
356
|
### Work Item Tools (6 tools)
|
|
368
357
|
|
|
Binary file
|
package/dist/index.js
CHANGED
|
@@ -2309,6 +2309,9 @@ Can filter by state, labels, assignee, milestone.`,
|
|
|
2309
2309
|
// src/tools/epics.ts
|
|
2310
2310
|
import { tool as tool3 } from "@opencode-ai/plugin";
|
|
2311
2311
|
var z3 = tool3.schema;
|
|
2312
|
+
function validationError(message) {
|
|
2313
|
+
return JSON.stringify({ error: message }, null, 2);
|
|
2314
|
+
}
|
|
2312
2315
|
var epicTools = {
|
|
2313
2316
|
gitlab_get_epic: tool3({
|
|
2314
2317
|
description: `Get details of a specific epic by group and epic IID.
|
|
@@ -2402,49 +2405,55 @@ Can update title, description, labels, dates, state, and confidentiality.`,
|
|
|
2402
2405
|
return JSON.stringify(epic, null, 2);
|
|
2403
2406
|
}
|
|
2404
2407
|
}),
|
|
2405
|
-
|
|
2406
|
-
description: `
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
description: `Link an existing issue to an epic.
|
|
2420
|
-
The issue can be from any project within the group hierarchy.`,
|
|
2421
|
-
args: {
|
|
2422
|
-
group_id: z3.string().describe("The group ID or URL-encoded path"),
|
|
2423
|
-
epic_iid: z3.number().describe("The internal ID of the epic"),
|
|
2424
|
-
issue_id: z3.number().describe("The global ID of the issue to add")
|
|
2425
|
-
},
|
|
2426
|
-
execute: async (args, _ctx) => {
|
|
2427
|
-
const client = getGitLabClient();
|
|
2428
|
-
const result = await client.addIssueToEpic(args.group_id, args.epic_iid, args.issue_id);
|
|
2429
|
-
return JSON.stringify(result, null, 2);
|
|
2430
|
-
}
|
|
2431
|
-
}),
|
|
2432
|
-
gitlab_remove_issue_from_epic: tool3({
|
|
2433
|
-
description: `Unlink an issue from an epic.
|
|
2434
|
-
Removes the association between the issue and the epic.`,
|
|
2408
|
+
gitlab_manage_epic_issues: tool3({
|
|
2409
|
+
description: `Manage issues linked to a GitLab epic.
|
|
2410
|
+
|
|
2411
|
+
Actions:
|
|
2412
|
+
- list: Get all issues associated with the epic
|
|
2413
|
+
- add: Link an existing issue to the epic (issue can be from any project within the group hierarchy)
|
|
2414
|
+
- remove: Unlink an issue from the epic
|
|
2415
|
+
|
|
2416
|
+
Examples:
|
|
2417
|
+
- List issues: action="list", group_id="gitlab-org", epic_iid=123
|
|
2418
|
+
- Add issue: action="add", group_id="gitlab-org", epic_iid=123, issue_id=456
|
|
2419
|
+
- Remove issue: action="remove", group_id="gitlab-org", epic_iid=123, epic_issue_id=789
|
|
2420
|
+
|
|
2421
|
+
Note: The epic_issue_id (for remove) is the ID of the epic-issue association, which can be obtained from the list action response.`,
|
|
2435
2422
|
args: {
|
|
2423
|
+
action: z3.enum(["list", "add", "remove"]).describe("The action to perform"),
|
|
2436
2424
|
group_id: z3.string().describe("The group ID or URL-encoded path"),
|
|
2437
|
-
epic_iid: z3.number().describe("The internal ID of the epic"),
|
|
2438
|
-
|
|
2425
|
+
epic_iid: z3.number().describe("The internal ID of the epic within the group"),
|
|
2426
|
+
issue_id: z3.number().optional().describe('The global ID of the issue to add (required for "add" action)'),
|
|
2427
|
+
epic_issue_id: z3.number().optional().describe(
|
|
2428
|
+
'The ID of the epic-issue association to remove (required for "remove" action, from list response)'
|
|
2429
|
+
)
|
|
2439
2430
|
},
|
|
2440
2431
|
execute: async (args, _ctx) => {
|
|
2441
2432
|
const client = getGitLabClient();
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2433
|
+
switch (args.action) {
|
|
2434
|
+
case "list": {
|
|
2435
|
+
const issues = await client.listEpicIssues(args.group_id, args.epic_iid);
|
|
2436
|
+
return JSON.stringify(issues, null, 2);
|
|
2437
|
+
}
|
|
2438
|
+
case "add": {
|
|
2439
|
+
if (args.issue_id === void 0) {
|
|
2440
|
+
return validationError('issue_id is required for "add" action');
|
|
2441
|
+
}
|
|
2442
|
+
const result = await client.addIssueToEpic(args.group_id, args.epic_iid, args.issue_id);
|
|
2443
|
+
return JSON.stringify(result, null, 2);
|
|
2444
|
+
}
|
|
2445
|
+
case "remove": {
|
|
2446
|
+
if (args.epic_issue_id === void 0) {
|
|
2447
|
+
return validationError('epic_issue_id is required for "remove" action');
|
|
2448
|
+
}
|
|
2449
|
+
const result = await client.removeIssueFromEpic(
|
|
2450
|
+
args.group_id,
|
|
2451
|
+
args.epic_iid,
|
|
2452
|
+
args.epic_issue_id
|
|
2453
|
+
);
|
|
2454
|
+
return JSON.stringify(result, null, 2);
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2448
2457
|
}
|
|
2449
2458
|
})
|
|
2450
2459
|
};
|
|
@@ -2734,10 +2743,83 @@ This is different from discussions - it returns individual comments in a flat st
|
|
|
2734
2743
|
// src/tools/search.ts
|
|
2735
2744
|
import { tool as tool6 } from "@opencode-ai/plugin";
|
|
2736
2745
|
var z6 = tool6.schema;
|
|
2746
|
+
var GENERIC_SEARCH_SCOPES = ["projects", "issues", "merge_requests", "blobs"];
|
|
2747
|
+
var SPECIALIZED_SCOPES = [
|
|
2748
|
+
"milestones",
|
|
2749
|
+
"users",
|
|
2750
|
+
"commits",
|
|
2751
|
+
"notes",
|
|
2752
|
+
"wiki_blobs",
|
|
2753
|
+
"group_projects"
|
|
2754
|
+
];
|
|
2755
|
+
var ALL_SCOPES = [...GENERIC_SEARCH_SCOPES, ...SPECIALIZED_SCOPES];
|
|
2756
|
+
var REF_SUPPORTED_SCOPES = ["commits", "wiki_blobs"];
|
|
2757
|
+
var STATE_SUPPORTED_SCOPES = ["milestones"];
|
|
2758
|
+
function validationError2(param, scope) {
|
|
2759
|
+
return new Error(`Missing required parameter: '${param}' is required for scope '${scope}'`);
|
|
2760
|
+
}
|
|
2761
|
+
function invalidParamError(param, validScopes) {
|
|
2762
|
+
return new Error(
|
|
2763
|
+
`Invalid parameter: '${param}' is only valid for scopes: ${validScopes.join(", ")}`
|
|
2764
|
+
);
|
|
2765
|
+
}
|
|
2766
|
+
function validateSearchParams(scope, args) {
|
|
2767
|
+
switch (scope) {
|
|
2768
|
+
case "notes":
|
|
2769
|
+
if (!args.project_id) throw validationError2("project_id", scope);
|
|
2770
|
+
break;
|
|
2771
|
+
case "group_projects":
|
|
2772
|
+
if (!args.group_id) throw validationError2("group_id", scope);
|
|
2773
|
+
break;
|
|
2774
|
+
}
|
|
2775
|
+
if (args.ref && !REF_SUPPORTED_SCOPES.includes(scope)) {
|
|
2776
|
+
throw invalidParamError("ref", REF_SUPPORTED_SCOPES);
|
|
2777
|
+
}
|
|
2778
|
+
if (args.state && !STATE_SUPPORTED_SCOPES.includes(scope)) {
|
|
2779
|
+
throw invalidParamError("state", STATE_SUPPORTED_SCOPES);
|
|
2780
|
+
}
|
|
2781
|
+
}
|
|
2737
2782
|
var searchTools = {
|
|
2783
|
+
/**
|
|
2784
|
+
* Unified search across all GitLab resources
|
|
2785
|
+
*
|
|
2786
|
+
* @example
|
|
2787
|
+
* // Search for issues in a project
|
|
2788
|
+
* gitlab_search({ scope: "issues", search: "bug", project_id: "my-group/project" })
|
|
2789
|
+
*
|
|
2790
|
+
* @example
|
|
2791
|
+
* // Search commits on specific branch
|
|
2792
|
+
* gitlab_search({ scope: "commits", search: "fix", ref: "main" })
|
|
2793
|
+
*
|
|
2794
|
+
* @example
|
|
2795
|
+
* // Search for projects within a group
|
|
2796
|
+
* gitlab_search({ scope: "group_projects", group_id: "gitlab-org", search: "runner" })
|
|
2797
|
+
*
|
|
2798
|
+
* @example
|
|
2799
|
+
* // Search notes/comments in a project
|
|
2800
|
+
* gitlab_search({ scope: "notes", search: "LGTM", project_id: "my-group/project" })
|
|
2801
|
+
*/
|
|
2738
2802
|
gitlab_search: tool6({
|
|
2739
|
-
description: `Search across GitLab for various resources.
|
|
2740
|
-
|
|
2803
|
+
description: `Search across GitLab for various resources with scope-specific options.
|
|
2804
|
+
|
|
2805
|
+
Scopes and their requirements:
|
|
2806
|
+
- projects: Search projects by name/description
|
|
2807
|
+
- issues: Search issues by title/description
|
|
2808
|
+
- merge_requests: Search MRs by title/description
|
|
2809
|
+
- milestones: Search milestones (supports state filter)
|
|
2810
|
+
- users: Search users by name/email
|
|
2811
|
+
- blobs: Search file content (code search)
|
|
2812
|
+
- commits: Search commits by message/author/SHA (supports ref filter)
|
|
2813
|
+
- notes: Search comments/notes (requires project_id)
|
|
2814
|
+
- wiki_blobs: Search wiki content (supports ref filter)
|
|
2815
|
+
- group_projects: Search projects within a group (requires group_id)
|
|
2816
|
+
|
|
2817
|
+
Examples:
|
|
2818
|
+
- Issues: scope="issues", search="bug", project_id="my-group/my-project"
|
|
2819
|
+
- Code: scope="blobs", search="function calculateTotal"
|
|
2820
|
+
- Commits: scope="commits", search="fix login", ref="main"
|
|
2821
|
+
- Group projects: scope="group_projects", group_id="gitlab-org", search="runner"
|
|
2822
|
+
- Notes: scope="notes", search="LGTM", project_id="my-group/my-project"`,
|
|
2741
2823
|
args: {
|
|
2742
2824
|
scope: z6.enum([
|
|
2743
2825
|
"projects",
|
|
@@ -2748,238 +2830,104 @@ Scopes: projects, issues, merge_requests, milestones, users, blobs (code), commi
|
|
|
2748
2830
|
"blobs",
|
|
2749
2831
|
"commits",
|
|
2750
2832
|
"notes",
|
|
2751
|
-
"wiki_blobs"
|
|
2752
|
-
|
|
2833
|
+
"wiki_blobs",
|
|
2834
|
+
"group_projects"
|
|
2835
|
+
]).describe("The type of resource to search"),
|
|
2753
2836
|
search: z6.string().describe("The search query"),
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
args: {
|
|
2767
|
-
search: z6.string().describe("The search query"),
|
|
2768
|
-
project_id: z6.string().optional().describe("Limit search to a specific project (optional)"),
|
|
2769
|
-
state: z6.enum(["opened", "closed", "all"]).optional().describe("Filter by issue state"),
|
|
2770
|
-
labels: z6.string().optional().describe("Comma-separated list of labels to filter by"),
|
|
2771
|
-
limit: z6.number().optional().describe("Maximum number of results (default: 20)")
|
|
2772
|
-
},
|
|
2773
|
-
execute: async (args, _ctx) => {
|
|
2774
|
-
const client = getGitLabClient();
|
|
2775
|
-
const results = await client.search("issues", args.search, args.project_id, args.limit);
|
|
2776
|
-
return JSON.stringify(results, null, 2);
|
|
2777
|
-
}
|
|
2778
|
-
}),
|
|
2779
|
-
gitlab_blob_search: tool6({
|
|
2780
|
-
description: `Search file content in repositories.
|
|
2781
|
-
Search for code/text within files across projects.`,
|
|
2782
|
-
args: {
|
|
2783
|
-
search: z6.string().describe("The search query (code/text to find)"),
|
|
2784
|
-
project_id: z6.string().optional().describe("Limit search to a specific project (optional)"),
|
|
2785
|
-
limit: z6.number().optional().describe("Maximum number of results (default: 20)")
|
|
2786
|
-
},
|
|
2787
|
-
execute: async (args, _ctx) => {
|
|
2788
|
-
const client = getGitLabClient();
|
|
2789
|
-
const results = await client.search("blobs", args.search, args.project_id, args.limit);
|
|
2790
|
-
return JSON.stringify(results, null, 2);
|
|
2791
|
-
}
|
|
2792
|
-
}),
|
|
2793
|
-
gitlab_merge_request_search: tool6({
|
|
2794
|
-
description: `Search merge requests by keyword.
|
|
2795
|
-
Specialized search for merge requests with better filtering than the generic search.`,
|
|
2796
|
-
args: {
|
|
2797
|
-
search: z6.string().describe("The search query"),
|
|
2798
|
-
project_id: z6.string().optional().describe("Limit search to a specific project (optional)"),
|
|
2799
|
-
state: z6.enum(["opened", "closed", "merged", "all"]).optional().describe("Filter by MR state"),
|
|
2800
|
-
labels: z6.string().optional().describe("Comma-separated list of labels to filter by"),
|
|
2801
|
-
limit: z6.number().optional().describe("Maximum number of results (default: 20)")
|
|
2802
|
-
},
|
|
2803
|
-
execute: async (args, _ctx) => {
|
|
2804
|
-
const client = getGitLabClient();
|
|
2805
|
-
const results = await client.search(
|
|
2806
|
-
"merge_requests",
|
|
2807
|
-
args.search,
|
|
2808
|
-
args.project_id,
|
|
2809
|
-
args.limit
|
|
2810
|
-
);
|
|
2811
|
-
return JSON.stringify(results, null, 2);
|
|
2812
|
-
}
|
|
2813
|
-
}),
|
|
2814
|
-
gitlab_commit_search: tool6({
|
|
2815
|
-
description: `Search for commits in a project or across GitLab.
|
|
2816
|
-
Returns commits matching the search query with commit details including SHA, title, message, author, and dates.
|
|
2817
|
-
|
|
2818
|
-
Supports searching by:
|
|
2819
|
-
- Commit message content
|
|
2820
|
-
- Author name or email
|
|
2821
|
-
- Commit SHA (partial or full)
|
|
2822
|
-
|
|
2823
|
-
Note: Advanced search features (Premium/Ultimate) provide better commit search capabilities.`,
|
|
2824
|
-
args: {
|
|
2825
|
-
search: z6.string().describe("The search query (commit message, author, or SHA)"),
|
|
2826
|
-
project_id: z6.string().optional().describe("Limit search to a specific project (optional)"),
|
|
2827
|
-
ref: z6.string().optional().describe("Branch or tag name to search on (defaults to default branch)"),
|
|
2828
|
-
order_by: z6.enum(["created_at"]).optional().describe("Order results by created_at (default: created_at desc)"),
|
|
2829
|
-
sort: z6.enum(["asc", "desc"]).optional().describe("Sort order (asc or desc)"),
|
|
2830
|
-
limit: z6.number().optional().describe("Maximum number of results (default: 20)")
|
|
2837
|
+
// Context parameters
|
|
2838
|
+
project_id: z6.string().optional().describe("Limit search to a specific project. Required for notes scope"),
|
|
2839
|
+
group_id: z6.string().optional().describe("Group ID or path. Required for group_projects scope"),
|
|
2840
|
+
// Common options
|
|
2841
|
+
limit: z6.number().optional().describe("Maximum number of results (default: 20)"),
|
|
2842
|
+
order_by: z6.enum(["created_at"]).optional().describe(
|
|
2843
|
+
"Order results by field (for milestones, users, commits, notes, wiki_blobs, group_projects)"
|
|
2844
|
+
),
|
|
2845
|
+
sort: z6.enum(["asc", "desc"]).optional().describe("Sort order (for milestones, users, commits, notes, wiki_blobs, group_projects)"),
|
|
2846
|
+
// Scope-specific options
|
|
2847
|
+
ref: z6.string().optional().describe("Branch or tag name (for commits, wiki_blobs scopes)"),
|
|
2848
|
+
state: z6.enum(["active", "closed", "all"]).optional().describe("Filter by state (for milestones scope)")
|
|
2831
2849
|
},
|
|
2832
2850
|
execute: async (args, _ctx) => {
|
|
2833
|
-
|
|
2834
|
-
|
|
2851
|
+
validateSearchParams(args.scope, {
|
|
2852
|
+
project_id: args.project_id,
|
|
2853
|
+
group_id: args.group_id,
|
|
2835
2854
|
ref: args.ref,
|
|
2836
|
-
|
|
2837
|
-
sort: args.sort,
|
|
2838
|
-
limit: args.limit
|
|
2839
|
-
});
|
|
2840
|
-
return JSON.stringify(results, null, 2);
|
|
2841
|
-
}
|
|
2842
|
-
}),
|
|
2843
|
-
gitlab_group_project_search: tool6({
|
|
2844
|
-
description: `Search for projects within a specific group.
|
|
2845
|
-
Returns projects matching the search query within the specified group and its subgroups.
|
|
2846
|
-
|
|
2847
|
-
Useful for:
|
|
2848
|
-
- Finding projects by name or description within a group
|
|
2849
|
-
- Discovering projects in large group hierarchies
|
|
2850
|
-
- Filtering group projects by keywords`,
|
|
2851
|
-
args: {
|
|
2852
|
-
group_id: z6.string().describe("The group ID or URL-encoded path"),
|
|
2853
|
-
search: z6.string().describe("The search query (project name or description)"),
|
|
2854
|
-
order_by: z6.enum(["created_at"]).optional().describe("Order results by created_at (default: created_at desc)"),
|
|
2855
|
-
sort: z6.enum(["asc", "desc"]).optional().describe("Sort order (asc or desc)"),
|
|
2856
|
-
limit: z6.number().optional().describe("Maximum number of results (default: 20)")
|
|
2857
|
-
},
|
|
2858
|
-
execute: async (args, _ctx) => {
|
|
2859
|
-
const client = getGitLabClient();
|
|
2860
|
-
const results = await client.searchGroupProjects(args.group_id, args.search, {
|
|
2861
|
-
order_by: args.order_by,
|
|
2862
|
-
sort: args.sort,
|
|
2863
|
-
limit: args.limit
|
|
2864
|
-
});
|
|
2865
|
-
return JSON.stringify(results, null, 2);
|
|
2866
|
-
}
|
|
2867
|
-
}),
|
|
2868
|
-
gitlab_milestone_search: tool6({
|
|
2869
|
-
description: `Search for milestones in a project or across GitLab.
|
|
2870
|
-
Returns milestones matching the search query with details including title, description, state, and dates.
|
|
2871
|
-
|
|
2872
|
-
Useful for:
|
|
2873
|
-
- Finding milestones by title or description
|
|
2874
|
-
- Discovering active or closed milestones
|
|
2875
|
-
- Planning and tracking project milestones`,
|
|
2876
|
-
args: {
|
|
2877
|
-
search: z6.string().describe("The search query (milestone title or description)"),
|
|
2878
|
-
project_id: z6.string().optional().describe("Limit search to a specific project (optional)"),
|
|
2879
|
-
state: z6.enum(["active", "closed", "all"]).optional().describe("Filter by milestone state"),
|
|
2880
|
-
order_by: z6.enum(["created_at"]).optional().describe("Order results by created_at (default: created_at desc)"),
|
|
2881
|
-
sort: z6.enum(["asc", "desc"]).optional().describe("Sort order (asc or desc)"),
|
|
2882
|
-
limit: z6.number().optional().describe("Maximum number of results (default: 20)")
|
|
2883
|
-
},
|
|
2884
|
-
execute: async (args, _ctx) => {
|
|
2885
|
-
const client = getGitLabClient();
|
|
2886
|
-
const results = await client.searchMilestones(args.search, args.project_id, {
|
|
2887
|
-
state: args.state,
|
|
2888
|
-
order_by: args.order_by,
|
|
2889
|
-
sort: args.sort,
|
|
2890
|
-
limit: args.limit
|
|
2891
|
-
});
|
|
2892
|
-
return JSON.stringify(results, null, 2);
|
|
2893
|
-
}
|
|
2894
|
-
}),
|
|
2895
|
-
gitlab_note_search: tool6({
|
|
2896
|
-
description: `Search for notes/comments in a project.
|
|
2897
|
-
Returns notes (comments) matching the search query from issues, merge requests, commits, and snippets.
|
|
2898
|
-
|
|
2899
|
-
Useful for:
|
|
2900
|
-
- Finding specific comments or discussions
|
|
2901
|
-
- Tracking feedback and review comments
|
|
2902
|
-
- Searching for mentions or keywords in conversations
|
|
2903
|
-
|
|
2904
|
-
Note: This scope requires Premium or Ultimate tier with advanced search enabled.`,
|
|
2905
|
-
args: {
|
|
2906
|
-
search: z6.string().describe("The search query (comment text)"),
|
|
2907
|
-
project_id: z6.string().describe("The project ID or URL-encoded path to search in"),
|
|
2908
|
-
order_by: z6.enum(["created_at"]).optional().describe("Order results by created_at (default: created_at desc)"),
|
|
2909
|
-
sort: z6.enum(["asc", "desc"]).optional().describe("Sort order (asc or desc)"),
|
|
2910
|
-
limit: z6.number().optional().describe("Maximum number of results (default: 20)")
|
|
2911
|
-
},
|
|
2912
|
-
execute: async (args, _ctx) => {
|
|
2913
|
-
const client = getGitLabClient();
|
|
2914
|
-
const results = await client.searchNotes(args.search, args.project_id, {
|
|
2915
|
-
order_by: args.order_by,
|
|
2916
|
-
sort: args.sort,
|
|
2917
|
-
limit: args.limit
|
|
2918
|
-
});
|
|
2919
|
-
return JSON.stringify(results, null, 2);
|
|
2920
|
-
}
|
|
2921
|
-
}),
|
|
2922
|
-
gitlab_user_search: tool6({
|
|
2923
|
-
description: `Search for users by name or email across GitLab.
|
|
2924
|
-
Returns users matching the search query with details including username, name, state, and avatar.
|
|
2925
|
-
|
|
2926
|
-
Useful for:
|
|
2927
|
-
- Finding users to assign to issues or merge requests
|
|
2928
|
-
- Looking up user information by name or email
|
|
2929
|
-
- Discovering team members and collaborators`,
|
|
2930
|
-
args: {
|
|
2931
|
-
search: z6.string().describe("The search query (user name or email)"),
|
|
2932
|
-
project_id: z6.string().optional().describe("Limit search to project members (optional)"),
|
|
2933
|
-
order_by: z6.enum(["created_at"]).optional().describe("Order results by created_at (default: created_at desc)"),
|
|
2934
|
-
sort: z6.enum(["asc", "desc"]).optional().describe("Sort order (asc or desc)"),
|
|
2935
|
-
limit: z6.number().optional().describe("Maximum number of results (default: 20)")
|
|
2936
|
-
},
|
|
2937
|
-
execute: async (args, _ctx) => {
|
|
2938
|
-
const client = getGitLabClient();
|
|
2939
|
-
const results = await client.searchUsers(args.search, args.project_id, {
|
|
2940
|
-
order_by: args.order_by,
|
|
2941
|
-
sort: args.sort,
|
|
2942
|
-
limit: args.limit
|
|
2855
|
+
state: args.state
|
|
2943
2856
|
});
|
|
2944
|
-
return JSON.stringify(results, null, 2);
|
|
2945
|
-
}
|
|
2946
|
-
}),
|
|
2947
|
-
gitlab_wiki_blob_search: tool6({
|
|
2948
|
-
description: `Search for wiki content (blobs) in a project or across GitLab.
|
|
2949
|
-
Returns wiki pages matching the search query with content snippets and file information.
|
|
2950
|
-
|
|
2951
|
-
Supports advanced filters (use in search query):
|
|
2952
|
-
- filename:some_name* - Filter by filename with wildcards
|
|
2953
|
-
- path:some/path* - Filter by path with wildcards
|
|
2954
|
-
- extension:md - Filter by file extension
|
|
2955
|
-
|
|
2956
|
-
Examples:
|
|
2957
|
-
- "installation" - Search for "installation" in wiki content
|
|
2958
|
-
- "setup filename:getting-started*" - Search in files starting with "getting-started"
|
|
2959
|
-
- "api extension:md" - Search for "api" in markdown files
|
|
2960
|
-
|
|
2961
|
-
Note: Advanced search (Premium/Ultimate) provides better wiki search capabilities.`,
|
|
2962
|
-
args: {
|
|
2963
|
-
search: z6.string().describe(
|
|
2964
|
-
"The search query (supports filters: filename:, path:, extension: with wildcards)"
|
|
2965
|
-
),
|
|
2966
|
-
project_id: z6.string().optional().describe("Limit search to a specific project (optional)"),
|
|
2967
|
-
ref: z6.string().optional().describe("Branch or tag name to search on (defaults to default branch)"),
|
|
2968
|
-
order_by: z6.enum(["created_at"]).optional().describe("Order results by created_at (default: created_at desc)"),
|
|
2969
|
-
sort: z6.enum(["asc", "desc"]).optional().describe("Sort order (asc or desc)"),
|
|
2970
|
-
limit: z6.number().optional().describe("Maximum number of results (default: 20)")
|
|
2971
|
-
},
|
|
2972
|
-
execute: async (args, _ctx) => {
|
|
2973
2857
|
const client = getGitLabClient();
|
|
2974
|
-
const
|
|
2975
|
-
ref: args.ref,
|
|
2858
|
+
const commonOptions = {
|
|
2976
2859
|
order_by: args.order_by,
|
|
2977
2860
|
sort: args.sort,
|
|
2978
2861
|
limit: args.limit
|
|
2979
|
-
}
|
|
2980
|
-
|
|
2862
|
+
};
|
|
2863
|
+
switch (args.scope) {
|
|
2864
|
+
// Generic search API scopes
|
|
2865
|
+
case "projects":
|
|
2866
|
+
case "issues":
|
|
2867
|
+
case "merge_requests":
|
|
2868
|
+
case "blobs":
|
|
2869
|
+
return JSON.stringify(
|
|
2870
|
+
await client.search(args.scope, args.search, args.project_id, args.limit),
|
|
2871
|
+
null,
|
|
2872
|
+
2
|
|
2873
|
+
);
|
|
2874
|
+
// Specialized scopes with dedicated client methods
|
|
2875
|
+
case "milestones":
|
|
2876
|
+
return JSON.stringify(
|
|
2877
|
+
await client.searchMilestones(args.search, args.project_id, {
|
|
2878
|
+
...commonOptions,
|
|
2879
|
+
state: args.state
|
|
2880
|
+
}),
|
|
2881
|
+
null,
|
|
2882
|
+
2
|
|
2883
|
+
);
|
|
2884
|
+
case "users":
|
|
2885
|
+
return JSON.stringify(
|
|
2886
|
+
await client.searchUsers(args.search, args.project_id, commonOptions),
|
|
2887
|
+
null,
|
|
2888
|
+
2
|
|
2889
|
+
);
|
|
2890
|
+
case "commits":
|
|
2891
|
+
return JSON.stringify(
|
|
2892
|
+
await client.searchCommits(args.search, args.project_id, {
|
|
2893
|
+
...commonOptions,
|
|
2894
|
+
ref: args.ref
|
|
2895
|
+
}),
|
|
2896
|
+
null,
|
|
2897
|
+
2
|
|
2898
|
+
);
|
|
2899
|
+
case "notes":
|
|
2900
|
+
return JSON.stringify(
|
|
2901
|
+
await client.searchNotes(args.search, args.project_id, commonOptions),
|
|
2902
|
+
null,
|
|
2903
|
+
2
|
|
2904
|
+
);
|
|
2905
|
+
case "wiki_blobs":
|
|
2906
|
+
return JSON.stringify(
|
|
2907
|
+
await client.searchWikiBlobs(args.search, args.project_id, {
|
|
2908
|
+
...commonOptions,
|
|
2909
|
+
ref: args.ref
|
|
2910
|
+
}),
|
|
2911
|
+
null,
|
|
2912
|
+
2
|
|
2913
|
+
);
|
|
2914
|
+
case "group_projects":
|
|
2915
|
+
return JSON.stringify(
|
|
2916
|
+
await client.searchGroupProjects(args.group_id, args.search, commonOptions),
|
|
2917
|
+
null,
|
|
2918
|
+
2
|
|
2919
|
+
);
|
|
2920
|
+
default:
|
|
2921
|
+
throw new Error(
|
|
2922
|
+
`Invalid scope '${args.scope}'. Must be one of: ${ALL_SCOPES.join(", ")}`
|
|
2923
|
+
);
|
|
2924
|
+
}
|
|
2981
2925
|
}
|
|
2982
2926
|
}),
|
|
2927
|
+
/**
|
|
2928
|
+
* Search GitLab official documentation
|
|
2929
|
+
* Separate tool because it uses a completely different API (docs.gitlab.com)
|
|
2930
|
+
*/
|
|
2983
2931
|
gitlab_documentation_search: tool6({
|
|
2984
2932
|
description: `Search GitLab official documentation at docs.gitlab.com.
|
|
2985
2933
|
Returns relevant documentation pages matching the search query.
|
|
@@ -3757,7 +3705,7 @@ import { tool as tool13 } from "@opencode-ai/plugin";
|
|
|
3757
3705
|
var z13 = tool13.schema;
|
|
3758
3706
|
var VALID_LIST_CREATE_TYPES = ["merge_request", "issue", "epic", "snippet"];
|
|
3759
3707
|
var VALID_GET_NOTE_TYPES = ["issue", "epic"];
|
|
3760
|
-
function
|
|
3708
|
+
function validationError3(param, resourceType) {
|
|
3761
3709
|
return new Error(
|
|
3762
3710
|
`Missing required parameter: '${param}' is required for resource_type '${resourceType}'`
|
|
3763
3711
|
);
|
|
@@ -3771,16 +3719,16 @@ function validateListCreateParams(resourceType, args) {
|
|
|
3771
3719
|
switch (resourceType) {
|
|
3772
3720
|
case "merge_request":
|
|
3773
3721
|
case "issue":
|
|
3774
|
-
if (!args.project_id) throw
|
|
3775
|
-
if (args.iid == null) throw
|
|
3722
|
+
if (!args.project_id) throw validationError3("project_id", resourceType);
|
|
3723
|
+
if (args.iid == null) throw validationError3("iid", resourceType);
|
|
3776
3724
|
break;
|
|
3777
3725
|
case "epic":
|
|
3778
|
-
if (!args.group_id) throw
|
|
3779
|
-
if (args.iid == null) throw
|
|
3726
|
+
if (!args.group_id) throw validationError3("group_id", resourceType);
|
|
3727
|
+
if (args.iid == null) throw validationError3("iid", resourceType);
|
|
3780
3728
|
break;
|
|
3781
3729
|
case "snippet":
|
|
3782
|
-
if (!args.project_id) throw
|
|
3783
|
-
if (args.snippet_id == null) throw
|
|
3730
|
+
if (!args.project_id) throw validationError3("project_id", resourceType);
|
|
3731
|
+
if (args.snippet_id == null) throw validationError3("snippet_id", resourceType);
|
|
3784
3732
|
break;
|
|
3785
3733
|
}
|
|
3786
3734
|
}
|
|
@@ -3790,15 +3738,15 @@ function validateGetNoteParams(resourceType, args) {
|
|
|
3790
3738
|
`Invalid resource_type '${resourceType}'. Must be one of: ${VALID_GET_NOTE_TYPES.join(", ")}`
|
|
3791
3739
|
);
|
|
3792
3740
|
}
|
|
3793
|
-
if (args.note_id == null) throw
|
|
3741
|
+
if (args.note_id == null) throw validationError3("note_id", resourceType);
|
|
3794
3742
|
switch (resourceType) {
|
|
3795
3743
|
case "issue":
|
|
3796
|
-
if (!args.project_id) throw
|
|
3797
|
-
if (args.iid == null) throw
|
|
3744
|
+
if (!args.project_id) throw validationError3("project_id", resourceType);
|
|
3745
|
+
if (args.iid == null) throw validationError3("iid", resourceType);
|
|
3798
3746
|
break;
|
|
3799
3747
|
case "epic":
|
|
3800
|
-
if (!args.group_id) throw
|
|
3801
|
-
if (args.iid == null) throw
|
|
3748
|
+
if (!args.group_id) throw validationError3("group_id", resourceType);
|
|
3749
|
+
if (args.iid == null) throw validationError3("iid", resourceType);
|
|
3802
3750
|
break;
|
|
3803
3751
|
}
|
|
3804
3752
|
}
|
package/package.json
CHANGED
|
Binary file
|