opencode-gitlab-plugin 2.8.0 → 2.8.2
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 +14 -0
- package/README.md +9 -9
- package/dist/index.js +101 -39
- package/dist/index.js.map +1 -1
- package/dist/mcp-server.cjs +102 -40
- package/dist/mcp-server.cjs.map +1 -1
- package/package.json +1 -1
package/dist/mcp-server.cjs
CHANGED
|
@@ -28893,19 +28893,45 @@ var GitLabApiClient = class {
|
|
|
28893
28893
|
}
|
|
28894
28894
|
};
|
|
28895
28895
|
|
|
28896
|
-
// src/client/
|
|
28897
|
-
|
|
28896
|
+
// src/client/connection-pagination.ts
|
|
28897
|
+
var DEFAULT_PAGE_SIZE = 20;
|
|
28898
|
+
var MAX_PAGE_SIZE = 100;
|
|
28899
|
+
function normalizePageSize(value) {
|
|
28900
|
+
if (value === void 0 || value === 0) return void 0;
|
|
28901
|
+
if (!Number.isFinite(value)) return DEFAULT_PAGE_SIZE;
|
|
28902
|
+
return Math.min(Math.max(Math.floor(value), 1), MAX_PAGE_SIZE);
|
|
28903
|
+
}
|
|
28904
|
+
function buildConnectionVariables(options) {
|
|
28898
28905
|
const variables = {};
|
|
28899
|
-
|
|
28900
|
-
|
|
28901
|
-
|
|
28902
|
-
|
|
28906
|
+
const first = normalizePageSize(options?.first);
|
|
28907
|
+
const last = normalizePageSize(options?.last);
|
|
28908
|
+
if (first !== void 0 && last !== void 0) {
|
|
28909
|
+
throw new Error("Pagination accepts either 'first' or 'last', not both");
|
|
28910
|
+
}
|
|
28911
|
+
if (options?.after && last !== void 0) {
|
|
28912
|
+
throw new Error("Pagination cursor 'after' cannot be combined with 'last'");
|
|
28913
|
+
}
|
|
28914
|
+
if (options?.before && first !== void 0) {
|
|
28915
|
+
throw new Error("Pagination cursor 'before' cannot be combined with 'first'");
|
|
28916
|
+
}
|
|
28917
|
+
if (first !== void 0) {
|
|
28918
|
+
variables.first = first;
|
|
28919
|
+
} else if (last !== void 0) {
|
|
28920
|
+
variables.last = last;
|
|
28921
|
+
} else if (options?.before) {
|
|
28922
|
+
variables.last = DEFAULT_PAGE_SIZE;
|
|
28923
|
+
} else {
|
|
28924
|
+
variables.first = DEFAULT_PAGE_SIZE;
|
|
28903
28925
|
}
|
|
28904
28926
|
if (options?.after) variables.after = options.after;
|
|
28905
|
-
if (options?.last !== void 0) variables.last = options.last;
|
|
28906
28927
|
if (options?.before) variables.before = options.before;
|
|
28907
28928
|
return variables;
|
|
28908
28929
|
}
|
|
28930
|
+
|
|
28931
|
+
// src/client/notes-types.ts
|
|
28932
|
+
function buildPaginationVariables(options) {
|
|
28933
|
+
return buildConnectionVariables(options);
|
|
28934
|
+
}
|
|
28909
28935
|
var NOTES_FRAGMENT = `
|
|
28910
28936
|
fragment NoteFields on Note {
|
|
28911
28937
|
id
|
|
@@ -28944,16 +28970,7 @@ var NOTES_CONNECTION_FRAGMENT = `
|
|
|
28944
28970
|
|
|
28945
28971
|
// src/client/discussions-types.ts
|
|
28946
28972
|
function buildDiscussionsPaginationVariables(options) {
|
|
28947
|
-
|
|
28948
|
-
if (options?.first !== void 0) {
|
|
28949
|
-
variables.first = options.first;
|
|
28950
|
-
} else if (options?.last == null) {
|
|
28951
|
-
variables.first = 20;
|
|
28952
|
-
}
|
|
28953
|
-
if (options?.after) variables.after = options.after;
|
|
28954
|
-
if (options?.last !== void 0) variables.last = options.last;
|
|
28955
|
-
if (options?.before) variables.before = options.before;
|
|
28956
|
-
return variables;
|
|
28973
|
+
return buildConnectionVariables(options);
|
|
28957
28974
|
}
|
|
28958
28975
|
var DISCUSSION_NOTE_FRAGMENT = `
|
|
28959
28976
|
fragment DiscussionNoteFields on Note {
|
|
@@ -29469,11 +29486,48 @@ var MergeRequestsClient = class _MergeRequestsClient extends GitLabApiClient {
|
|
|
29469
29486
|
Object.keys(body).length > 0 ? body : void 0
|
|
29470
29487
|
);
|
|
29471
29488
|
}
|
|
29489
|
+
/**
|
|
29490
|
+
* Resolve the auto-merge strategy for a project.
|
|
29491
|
+
*
|
|
29492
|
+
* When the caller does not specify a strategy, projects with merge trains
|
|
29493
|
+
* enabled require ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS; otherwise
|
|
29494
|
+
* MERGE_WHEN_CHECKS_PASS is correct. Using the wrong one causes auto-merge to
|
|
29495
|
+
* fail with an opaque "The merge failed" error. Falls back to
|
|
29496
|
+
* MERGE_WHEN_CHECKS_PASS if the project setting cannot be read.
|
|
29497
|
+
*
|
|
29498
|
+
* Returns both the chosen strategy and how it was arrived at, so the caller
|
|
29499
|
+
* can thread a breadcrumb into its result. A bare fallback would collapse a
|
|
29500
|
+
* 401, a network timeout, and a genuine 404 all into a silent MWPS default,
|
|
29501
|
+
* reintroducing the opaque "The merge failed" this behaviour exists to
|
|
29502
|
+
* eliminate; `detection` makes that observable without changing the fallback.
|
|
29503
|
+
*/
|
|
29504
|
+
async resolveAutoMergeStrategy(projectId) {
|
|
29505
|
+
try {
|
|
29506
|
+
const encodedProject = this.encodeProjectId(projectId);
|
|
29507
|
+
const project = await this.fetch(
|
|
29508
|
+
"GET",
|
|
29509
|
+
`/projects/${encodedProject}`
|
|
29510
|
+
);
|
|
29511
|
+
return project.merge_trains_enabled ? {
|
|
29512
|
+
strategy: "ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS",
|
|
29513
|
+
detection: "merge_trains_enabled"
|
|
29514
|
+
} : { strategy: "MERGE_WHEN_CHECKS_PASS", detection: "merge_trains_disabled" };
|
|
29515
|
+
} catch (error45) {
|
|
29516
|
+
return {
|
|
29517
|
+
strategy: "MERGE_WHEN_CHECKS_PASS",
|
|
29518
|
+
detection: "defaulted_after_error",
|
|
29519
|
+
reason: error45 instanceof Error ? error45.message : String(error45)
|
|
29520
|
+
};
|
|
29521
|
+
}
|
|
29522
|
+
}
|
|
29472
29523
|
/**
|
|
29473
29524
|
* Smart merge: merge immediately if checks pass, otherwise set auto-merge
|
|
29474
|
-
* Returns detailed context about what happened
|
|
29525
|
+
* Returns detailed context about what happened.
|
|
29526
|
+
*
|
|
29527
|
+
* If `strategy` is omitted, it is auto-detected from the project's merge
|
|
29528
|
+
* train settings (merge-train projects need ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS).
|
|
29475
29529
|
*/
|
|
29476
|
-
async smartMerge(projectId, mrIid, sha, strategy
|
|
29530
|
+
async smartMerge(projectId, mrIid, sha, strategy) {
|
|
29477
29531
|
let mr = await this.getMergeRequest(projectId, mrIid);
|
|
29478
29532
|
if (mr.detailed_merge_status === "checking") {
|
|
29479
29533
|
for (let attempt = 0; attempt < 5 && mr.detailed_merge_status === "checking"; attempt++) {
|
|
@@ -29521,15 +29575,24 @@ var MergeRequestsClient = class _MergeRequestsClient extends GitLabApiClient {
|
|
|
29521
29575
|
}
|
|
29522
29576
|
const autoMergeStatuses = ["ci_still_running", "not_approved"];
|
|
29523
29577
|
if (autoMergeStatuses.includes(mr.detailed_merge_status)) {
|
|
29578
|
+
let resolvedStrategy;
|
|
29579
|
+
if (strategy) {
|
|
29580
|
+
resolvedStrategy = strategy;
|
|
29581
|
+
context.strategyDetection = `explicit: ${strategy}`;
|
|
29582
|
+
} else {
|
|
29583
|
+
const detected = await this.resolveAutoMergeStrategy(projectId);
|
|
29584
|
+
resolvedStrategy = detected.strategy;
|
|
29585
|
+
context.strategyDetection = detected.detection === "defaulted_after_error" ? `failed, defaulted to MERGE_WHEN_CHECKS_PASS${detected.reason ? ` (${detected.reason})` : ""}` : `auto-detected (${detected.detection}): ${detected.strategy}`;
|
|
29586
|
+
}
|
|
29524
29587
|
try {
|
|
29525
|
-
const result = await this.setAutoMerge(projectId, mrIid, sha,
|
|
29588
|
+
const result = await this.setAutoMerge(projectId, mrIid, sha, resolvedStrategy);
|
|
29526
29589
|
const autoMergeMessages = {
|
|
29527
29590
|
ci_still_running: "pipeline passes",
|
|
29528
29591
|
not_approved: "approved"
|
|
29529
29592
|
};
|
|
29530
29593
|
return {
|
|
29531
29594
|
action: "auto_merge_enabled",
|
|
29532
|
-
message: `Auto-merge enabled (${
|
|
29595
|
+
message: `Auto-merge enabled (${resolvedStrategy}). MR will merge when ${autoMergeMessages[mr.detailed_merge_status]}.`,
|
|
29533
29596
|
mergeRequest: result,
|
|
29534
29597
|
context
|
|
29535
29598
|
};
|
|
@@ -30167,10 +30230,7 @@ var RepositoryClient = class extends GitLabApiClient {
|
|
|
30167
30230
|
async getFile(projectId, filePath, ref) {
|
|
30168
30231
|
const encodedProject = this.encodeProjectId(projectId);
|
|
30169
30232
|
const encodedPath = encodeURIComponent(filePath);
|
|
30170
|
-
|
|
30171
|
-
if (ref) {
|
|
30172
|
-
url2 += `?ref=${encodeURIComponent(ref)}`;
|
|
30173
|
-
}
|
|
30233
|
+
const url2 = `/projects/${encodedProject}/repository/files/${encodedPath}?ref=${encodeURIComponent(ref)}`;
|
|
30174
30234
|
const file2 = await this.fetch("GET", url2);
|
|
30175
30235
|
if (file2.encoding === "base64") {
|
|
30176
30236
|
return Buffer.from(file2.content, "base64").toString("utf-8");
|
|
@@ -31779,17 +31839,12 @@ Note: You must provide the current HEAD SHA of the MR to prevent race conditions
|
|
|
31779
31839
|
"The HEAD SHA of the merge request. Get this from the MR details (diff_refs.head_sha or sha field)."
|
|
31780
31840
|
),
|
|
31781
31841
|
strategy: z.enum(["MERGE_WHEN_CHECKS_PASS", "ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS"]).optional().describe(
|
|
31782
|
-
"Auto-merge strategy when immediate merge is not possible.
|
|
31842
|
+
"Auto-merge strategy when immediate merge is not possible. If omitted, it is auto-detected from the project: merge-train projects use ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS, otherwise MERGE_WHEN_CHECKS_PASS."
|
|
31783
31843
|
)
|
|
31784
31844
|
},
|
|
31785
31845
|
execute: async (args, _ctx) => {
|
|
31786
31846
|
const client = getGitLabClient();
|
|
31787
|
-
const result = await client.smartMerge(
|
|
31788
|
-
args.project_id,
|
|
31789
|
-
args.mr_iid,
|
|
31790
|
-
args.sha,
|
|
31791
|
-
args.strategy || "MERGE_WHEN_CHECKS_PASS"
|
|
31792
|
-
);
|
|
31847
|
+
const result = await client.smartMerge(args.project_id, args.mr_iid, args.sha, args.strategy);
|
|
31793
31848
|
return JSON.stringify(result, null, 2);
|
|
31794
31849
|
}
|
|
31795
31850
|
}),
|
|
@@ -32271,13 +32326,13 @@ var repositoryTools = {
|
|
|
32271
32326
|
gitlab_get_file: tool({
|
|
32272
32327
|
description: `Get the contents of a file from a repository.
|
|
32273
32328
|
Supports fetching files from any branch, tag, or commit SHA.
|
|
32274
|
-
|
|
32329
|
+
An explicit ref is required by the GitLab repository files API.
|
|
32275
32330
|
Note: Invalid refs will result in a 404 error from the GitLab API.`,
|
|
32276
32331
|
args: {
|
|
32277
32332
|
project_id: z5.string().describe("The project ID or URL-encoded path"),
|
|
32278
32333
|
file_path: z5.string().describe("Path to the file in the repository"),
|
|
32279
|
-
ref: z5.string().
|
|
32280
|
-
|
|
32334
|
+
ref: z5.string().trim().min(1).describe(
|
|
32335
|
+
"Branch name, tag, or commit SHA to fetch the file from. Supports full or short commit SHAs."
|
|
32281
32336
|
)
|
|
32282
32337
|
},
|
|
32283
32338
|
execute: async (args, _ctx) => {
|
|
@@ -32454,6 +32509,8 @@ Scopes and their requirements:
|
|
|
32454
32509
|
- wiki_blobs: Search wiki content (supports ref filter)
|
|
32455
32510
|
- group_projects: Search projects within a group (requires group_id)
|
|
32456
32511
|
|
|
32512
|
+
For scopes other than milestones, state="all" is treated as omitted because it does not filter results.
|
|
32513
|
+
|
|
32457
32514
|
Examples:
|
|
32458
32515
|
- Issues: scope="issues", search="bug", project_id="my-group/my-project"
|
|
32459
32516
|
- Code: scope="blobs", search="function calculateTotal"
|
|
@@ -32488,6 +32545,9 @@ Examples:
|
|
|
32488
32545
|
state: z6.enum(["active", "closed", "all"]).optional().describe("Filter by state (for milestones scope)")
|
|
32489
32546
|
},
|
|
32490
32547
|
execute: async (args, _ctx) => {
|
|
32548
|
+
if (args.scope !== "milestones" && args.state === "all") {
|
|
32549
|
+
args.state = void 0;
|
|
32550
|
+
}
|
|
32491
32551
|
validateSearchParams(args.scope, {
|
|
32492
32552
|
project_id: args.project_id,
|
|
32493
32553
|
group_id: args.group_id,
|
|
@@ -33189,10 +33249,10 @@ Examples:
|
|
|
33189
33249
|
"Filter by resolved status: true for resolved, false for unresolved. Only returns resolvable discussions (excludes system notes). Client-side filtering."
|
|
33190
33250
|
),
|
|
33191
33251
|
// Pagination
|
|
33192
|
-
first: z13.number().optional().describe("Number of items to return (default: 20)"),
|
|
33252
|
+
first: z13.number().int().min(0).max(100).optional().describe("Number of items to return (default: 20, max: 100; 0 uses the default)"),
|
|
33193
33253
|
after: z13.string().optional().describe("Cursor for pagination - use endCursor from previous response"),
|
|
33194
33254
|
before: z13.string().optional().describe("Cursor for backward pagination"),
|
|
33195
|
-
last: z13.number().optional().describe("Number of items from the end")
|
|
33255
|
+
last: z13.number().int().min(0).max(100).optional().describe("Number of items from the end (max: 100; 0 is omitted)")
|
|
33196
33256
|
},
|
|
33197
33257
|
execute: async (args, _ctx) => {
|
|
33198
33258
|
validateResourceParams(args.resource_type, args);
|
|
@@ -33504,9 +33564,11 @@ Examples:
|
|
|
33504
33564
|
"Filter by resolved status: true for resolved, false for unresolved. Only returns resolvable notes (excludes system notes). Client-side filtering."
|
|
33505
33565
|
),
|
|
33506
33566
|
// Pagination
|
|
33507
|
-
first: z14.number().
|
|
33567
|
+
first: z14.number().int().min(0).max(100).optional().describe(
|
|
33568
|
+
"Number of items to return from the beginning (default: 20, max: 100; 0 uses the default)"
|
|
33569
|
+
),
|
|
33508
33570
|
after: z14.string().optional().describe("Cursor for forward pagination - use endCursor from previous response"),
|
|
33509
|
-
last: z14.number().optional().describe("Number of items to return from the end (
|
|
33571
|
+
last: z14.number().int().min(0).max(100).optional().describe("Number of items to return from the end (max: 100; 0 is omitted)"),
|
|
33510
33572
|
before: z14.string().optional().describe("Cursor for backward pagination - use startCursor from previous response")
|
|
33511
33573
|
},
|
|
33512
33574
|
execute: async (args, _ctx) => {
|
|
@@ -34181,7 +34243,7 @@ async function main() {
|
|
|
34181
34243
|
...auditTools,
|
|
34182
34244
|
...awardEmojiTools
|
|
34183
34245
|
};
|
|
34184
|
-
const version2 = true ? "2.8.
|
|
34246
|
+
const version2 = true ? "2.8.2" : "0.0.0";
|
|
34185
34247
|
const server = new McpServer({ name: "gitlab", version: version2 });
|
|
34186
34248
|
adaptToolsToMcp(server, allTools);
|
|
34187
34249
|
const transport = new StdioServerTransport();
|