opencode-gitlab-plugin 2.8.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tools/merge-requests.ts","../src/utils.ts","../src/client/base.ts","../src/client/notes-types.ts","../src/client/discussions-types.ts","../src/client/merge-requests.ts","../src/client/issues.ts","../src/client/work-items.ts","../src/client/pipelines.ts","../src/client/repository.ts","../src/client/search.ts","../src/client/projects.ts","../src/client/users.ts","../src/client/wikis.ts","../src/validation.ts","../src/client/security.ts","../src/client/todos.ts","../src/client/epics.ts","../src/client/snippets.ts","../src/client/discussions.ts","../src/client/audit.ts","../src/client/award-emoji.ts","../src/client/index.ts","../src/tools/issues.ts","../src/tools/epics.ts","../src/tools/pipelines.ts","../src/tools/repository.ts","../src/tools/search.ts","../src/tools/projects.ts","../src/tools/users.ts","../src/tools/security.ts","../src/tools/todos.ts","../src/tools/wikis.ts","../src/tools/work-items.ts","../src/tools/discussions-unified.ts","../src/tools/notes-unified.ts","../src/tools/git.ts","../src/client/git.ts","../src/tools/audit.ts","../src/tools/award-emoji.ts","../src/tools/orbit.ts","../src/index.ts"],"sourcesContent":["import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const mergeRequestTools = {\n gitlab_get_merge_request: tool({\n description: `Get details of a specific merge request by project and MR IID.\nReturns: title, description, state, author, assignees, reviewers, labels, diff stats, and discussion notes.`,\n args: {\n project_id: z\n .string()\n .describe('The project ID or URL-encoded path (e.g., \"gitlab-org/gitlab\" or \"123\")'),\n mr_iid: z.number().describe('The internal ID of the merge request within the project'),\n include_changes: z\n .boolean()\n .optional()\n .describe('Whether to include the list of changed files (default: false)'),\n },\n execute: async (\n args: { project_id: string; mr_iid: number; include_changes?: boolean },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const mr = await client.getMergeRequest(args.project_id, args.mr_iid, args.include_changes);\n return JSON.stringify(mr, null, 2);\n },\n }),\n\n gitlab_list_merge_requests: tool({\n description: `List merge requests for a project or search globally.\nCan filter by state (opened, closed, merged, all), scope (assigned_to_me, created_by_me), and labels.\n\nIMPORTANT: Response includes pagination info. If nextPage exists, there are more results.\nAlways paginate until you get an empty response or no nextPage to ensure you have all data.`,\n args: {\n project_id: z\n .string()\n .optional()\n .describe('The project ID or path. If not provided, searches globally.'),\n state: z\n .enum(['opened', 'closed', 'merged', 'all'])\n .optional()\n .describe('Filter by MR state (default: opened)'),\n scope: z\n .enum(['assigned_to_me', 'created_by_me', 'all'])\n .optional()\n .describe('Filter by scope'),\n search: z.string().optional().describe('Search MRs by title or description'),\n labels: z.string().optional().describe('Comma-separated list of labels to filter by'),\n limit: z.number().optional().describe('Maximum number of results per page (default: 20)'),\n page: z.number().optional().describe('Page number for pagination (default: 1)'),\n },\n execute: async (\n args: {\n project_id?: string;\n state?: 'opened' | 'closed' | 'merged' | 'all';\n scope?: 'assigned_to_me' | 'created_by_me' | 'all';\n search?: string;\n labels?: string;\n limit?: number;\n page?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const result = await client.listMergeRequests({\n projectId: args.project_id,\n state: args.state,\n scope: args.scope,\n search: args.search,\n labels: args.labels,\n limit: args.limit,\n page: args.page,\n });\n return JSON.stringify(result, null, 2);\n },\n }),\n\n gitlab_get_mr_changes: tool({\n description: `Get the file changes (diff) for a merge request.\nReturns the list of files changed with their diffs.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n },\n execute: async (args: { project_id: string; mr_iid: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const changes = await client.getMrChanges(args.project_id, args.mr_iid);\n return JSON.stringify(changes, null, 2);\n },\n }),\n\n gitlab_create_merge_request: tool({\n description: `Create a new merge request.\nReturns the created merge request with all details.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n source_branch: z.string().describe('The source branch name'),\n target_branch: z.string().describe('The target branch name'),\n title: z.string().describe('The title of the merge request'),\n description: z\n .string()\n .optional()\n .describe('The description of the merge request (supports Markdown)'),\n assignee_ids: z.array(z.number()).optional().describe('Array of user IDs to assign'),\n reviewer_ids: z.array(z.number()).optional().describe('Array of user IDs to review'),\n labels: z.string().optional().describe('Comma-separated list of labels'),\n milestone_id: z.number().optional().describe('The ID of a milestone'),\n remove_source_branch: z\n .boolean()\n .optional()\n .describe('Remove source branch after merge (default: false)'),\n squash: z.boolean().optional().describe('Squash commits on merge (default: false)'),\n allow_collaboration: z\n .boolean()\n .optional()\n .describe('Allow commits from members who can merge to the target branch'),\n target_project_id: z\n .number()\n .optional()\n .describe(\n 'The ID of the target project for cross-project (fork to upstream) merge requests. Defaults to the source project when omitted.'\n ),\n },\n execute: async (\n args: {\n project_id: string;\n source_branch: string;\n target_branch: string;\n title: string;\n description?: string;\n assignee_ids?: number[];\n reviewer_ids?: number[];\n labels?: string;\n milestone_id?: number;\n remove_source_branch?: boolean;\n squash?: boolean;\n allow_collaboration?: boolean;\n target_project_id?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const mr = await client.createMergeRequest(args.project_id, {\n source_branch: args.source_branch,\n target_branch: args.target_branch,\n title: args.title,\n description: args.description,\n assignee_ids: args.assignee_ids,\n reviewer_ids: args.reviewer_ids,\n labels: args.labels,\n milestone_id: args.milestone_id,\n remove_source_branch: args.remove_source_branch,\n squash: args.squash,\n allow_collaboration: args.allow_collaboration,\n target_project_id: args.target_project_id,\n });\n return JSON.stringify(mr, null, 2);\n },\n }),\n\n gitlab_update_merge_request: tool({\n description: `Update an existing merge request.\nCan update title, description, state, assignees, reviewers, labels, and more.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n title: z.string().optional().describe('The new title'),\n description: z.string().optional().describe('The new description (supports Markdown)'),\n state_event: z\n .enum(['close', 'reopen'])\n .optional()\n .describe('Change the state (close or reopen)'),\n assignee_ids: z.array(z.number()).optional().describe('Array of user IDs to assign'),\n reviewer_ids: z.array(z.number()).optional().describe('Array of user IDs to review'),\n labels: z.string().optional().describe('Comma-separated list of labels'),\n milestone_id: z.number().optional().describe('The ID of a milestone'),\n remove_source_branch: z.boolean().optional().describe('Remove source branch after merge'),\n squash: z.boolean().optional().describe('Squash commits on merge'),\n target_branch: z.string().optional().describe('The target branch name'),\n },\n execute: async (\n args: {\n project_id: string;\n mr_iid: number;\n title?: string;\n description?: string;\n state_event?: 'close' | 'reopen';\n assignee_ids?: number[];\n reviewer_ids?: number[];\n labels?: string;\n milestone_id?: number;\n remove_source_branch?: boolean;\n squash?: boolean;\n target_branch?: string;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const mr = await client.updateMergeRequest(args.project_id, args.mr_iid, {\n title: args.title,\n description: args.description,\n state_event: args.state_event,\n assignee_ids: args.assignee_ids,\n reviewer_ids: args.reviewer_ids,\n labels: args.labels,\n milestone_id: args.milestone_id,\n remove_source_branch: args.remove_source_branch,\n squash: args.squash,\n target_branch: args.target_branch,\n });\n return JSON.stringify(mr, null, 2);\n },\n }),\n\n gitlab_get_mr_details: tool({\n description: `Get additional details for a merge request.\n\nDetail types:\n- commits: List all commits in the MR\n- pipelines: List all pipelines that ran for the MR\n\nExamples:\n- Get commits: detail_type=\"commits\", project_id=\"group/project\", mr_iid=123\n- Get pipelines: detail_type=\"pipelines\", project_id=\"group/project\", mr_iid=123`,\n args: {\n detail_type: z.enum(['commits', 'pipelines']).describe('Type of details to fetch'),\n project_id: z.string().describe('The project ID or URL-encoded path'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n },\n execute: async (\n args: { detail_type: 'commits' | 'pipelines'; project_id: string; mr_iid: number },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n\n switch (args.detail_type) {\n case 'commits': {\n const commits = await client.getMrCommits(args.project_id, args.mr_iid);\n return JSON.stringify(commits, null, 2);\n }\n case 'pipelines': {\n const pipelines = await client.getMrPipelines(args.project_id, args.mr_iid);\n return JSON.stringify(pipelines, null, 2);\n }\n }\n },\n }),\n\n gitlab_list_merge_request_diffs: tool({\n description: `List merge request diffs with pagination support.\nReturns the list of file diffs for a merge request, with support for pagination to handle large changesets.\nThis is useful when you need to process diffs in chunks or when the MR has many changed files.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n page: z.number().optional().describe('Page number for pagination (default: 1)'),\n per_page: z.number().optional().describe('Number of diffs per page (default: 20, max: 100)'),\n },\n execute: async (\n args: { project_id: string; mr_iid: number; page?: number; per_page?: number },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const diffs = await client.listMergeRequestDiffs(args.project_id, args.mr_iid, {\n page: args.page,\n per_page: args.per_page,\n });\n return JSON.stringify(diffs, null, 2);\n },\n }),\n\n gitlab_add_mr_reviewer: tool({\n description: `Add a reviewer to a merge request without affecting existing reviewers.\nThis is safer than gitlab_update_merge_request when you only want to add a single reviewer,\nas it preserves all existing reviewers.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n reviewer_id: z.number().describe('The user ID of the reviewer to add'),\n },\n execute: async (\n args: { project_id: string; mr_iid: number; reviewer_id: number },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const mr = await client.addReviewer(args.project_id, args.mr_iid, args.reviewer_id);\n return JSON.stringify(mr, null, 2);\n },\n }),\n\n gitlab_remove_mr_reviewer: tool({\n description: `Remove a reviewer from a merge request without affecting other reviewers.\nThis is safer than gitlab_update_merge_request when you only want to remove a single reviewer,\nas it preserves all other reviewers.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n reviewer_id: z.number().describe('The user ID of the reviewer to remove'),\n },\n execute: async (\n args: { project_id: string; mr_iid: number; reviewer_id: number },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const mr = await client.removeReviewer(args.project_id, args.mr_iid, args.reviewer_id);\n return JSON.stringify(mr, null, 2);\n },\n }),\n\n gitlab_set_mr_auto_merge: tool({\n description: `Enable auto-merge (MWPS - Merge When Pipeline Succeeds) on a merge request.\nUses the GitLab GraphQL API mergeRequestAccept mutation with a merge strategy.\nThe MR will be automatically merged when all required conditions are met.\nRequires the MR to be approved and have a passing pipeline (depending on project settings).\nNote: You must provide the current HEAD SHA of the MR to prevent race conditions.`,\n args: {\n project_id: z.string().describe('The project ID or path (e.g., \"gitlab-org/gitlab\")'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n sha: z\n .string()\n .describe(\n 'The HEAD SHA of the merge request. Get this from the MR details (diff_refs.head_sha or sha field).'\n ),\n strategy: z\n .enum(['MERGE_WHEN_CHECKS_PASS', 'ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS'])\n .optional()\n .describe(\n 'MERGE_WHEN_CHECKS_PASS (default) waits for all checks. ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS adds to merge train.'\n ),\n },\n execute: async (\n args: {\n project_id: string;\n mr_iid: number;\n sha: string;\n strategy?: 'MERGE_WHEN_CHECKS_PASS' | 'ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS';\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const result = await client.setAutoMerge(\n args.project_id,\n args.mr_iid,\n args.sha,\n args.strategy || 'MERGE_WHEN_CHECKS_PASS'\n );\n return JSON.stringify(result, null, 2);\n },\n }),\n\n gitlab_smart_merge_mr: tool({\n description: `Smart merge: merges immediately if checks pass, otherwise enables auto-merge (MWPS).\nThis tool automatically determines the best merge action based on MR state:\n- If MR is mergeable (pipeline passed, approved): merges immediately\n- If pipeline is running or awaiting approval: enables auto-merge\n- Returns detailed context about what happened and why\n\nProvides actionable feedback on failures including MR state, pipeline status, and remediation hints.\nNote: You must provide the current HEAD SHA of the MR to prevent race conditions.`,\n args: {\n project_id: z.string().describe('The project ID or path (e.g., \"gitlab-org/gitlab\")'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n sha: z\n .string()\n .describe(\n 'The HEAD SHA of the merge request. Get this from the MR details (diff_refs.head_sha or sha field).'\n ),\n strategy: z\n .enum(['MERGE_WHEN_CHECKS_PASS', 'ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS'])\n .optional()\n .describe(\n '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.'\n ),\n },\n execute: async (\n args: {\n project_id: string;\n mr_iid: number;\n sha: string;\n strategy?: 'MERGE_WHEN_CHECKS_PASS' | 'ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS';\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const result = await client.smartMerge(args.project_id, args.mr_iid, args.sha, args.strategy);\n return JSON.stringify(result, null, 2);\n },\n }),\n\n gitlab_merge_mr: tool({\n description: `Merge a merge request immediately.\nUse this when you know the MR is ready to merge (pipeline passed, approved, no conflicts).\nFor automatic handling based on MR state, use gitlab_smart_merge_mr instead.\n\nWARNING: If sha is omitted, the merge may succeed against a newer commit than what was reviewed/approved.\nAlways provide sha when you want to ensure you're merging the exact code that was reviewed.`,\n args: {\n project_id: z.string().describe('The project ID or path (e.g., \"gitlab-org/gitlab\")'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n sha: z\n .string()\n .optional()\n .describe(\n 'HEAD SHA to verify before merging. Recommended to prevent merging unreviewed code if new commits were pushed.'\n ),\n squash: z\n .boolean()\n .optional()\n .describe('Whether to squash commits (uses project default if not specified)'),\n should_remove_source_branch: z\n .boolean()\n .optional()\n .describe('Whether to delete source branch after merge'),\n },\n execute: async (\n args: {\n project_id: string;\n mr_iid: number;\n sha?: string;\n squash?: boolean;\n should_remove_source_branch?: boolean;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const result = await client.mergeMergeRequest(args.project_id, args.mr_iid, {\n sha: args.sha,\n squash: args.squash,\n shouldRemoveSourceBranch: args.should_remove_source_branch,\n });\n return JSON.stringify(result, null, 2);\n },\n }),\n\n gitlab_override_requested_changes: tool({\n description: `Bypass (or re-enable) a \"requested changes\" merge block on a merge request.\n\nWhen a reviewer formally requests changes, the merge check \"Change requests must be approved by the requesting user\" blocks the merge (detailed_merge_status: requested_changes). This tool sets the persistent override_requested_changes flag, which is exactly what the \"Bypass\" button in the MR widget does: it downgrades that check from a blocking failure to a non-blocking warning so the MR can be merged.\n\nUse this when the requesting reviewer is unavailable (e.g. on PTO) and their concerns have been addressed. The acting user must have permission to merge to the target branch, otherwise GitLab silently ignores the flag.\n\nNote: this is NOT the same as clearing your own requested-changes review. It overrides another user's request. Set override=false to restore the block.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n override: z\n .boolean()\n .optional()\n .describe('true (default) to bypass requested changes, false to restore the block'),\n },\n execute: async (\n args: { project_id: string; mr_iid: number; override?: boolean },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const result = await client.overrideRequestedChanges(\n args.project_id,\n args.mr_iid,\n args.override ?? true\n );\n return JSON.stringify(result, null, 2);\n },\n }),\n\n gitlab_approve_merge_request: tool({\n description: `Approve a merge request.\nAdds the current user's approval to the merge request.\nRequires at least Developer role on the project.\nReturns the updated approval state including approved_by list.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n sha: z\n .string()\n .optional()\n .describe(\n 'The HEAD SHA of the MR. If provided, the approval will only succeed if this matches the current HEAD, preventing approval of outdated code.'\n ),\n },\n execute: async (\n args: { project_id: string; mr_iid: number; sha?: string },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const result = await client.approveMergeRequest(args.project_id, args.mr_iid, args.sha);\n return JSON.stringify(result, null, 2);\n },\n }),\n\n gitlab_unapprove_merge_request: tool({\n description: `Unapprove (revoke approval from) a merge request.\nRemoves the current user's approval from the merge request.\nOnly the user who approved can unapprove; you cannot remove others' approvals.\nReturns the updated approval state.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n },\n execute: async (args: { project_id: string; mr_iid: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const result = await client.unapproveMergeRequest(args.project_id, args.mr_iid);\n return JSON.stringify(result, null, 2);\n },\n }),\n};\n","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport { GitLabApiClient } from './client/index.js';\n\n/**\n * Read GitLab token from OpenCode auth.json storage\n */\nfunction readTokenFromAuthStorage(): string | undefined {\n try {\n const authPath = path.join(os.homedir(), '.local', 'share', 'opencode', 'auth.json');\n\n if (!fs.existsSync(authPath)) {\n return undefined;\n }\n\n const authData = JSON.parse(fs.readFileSync(authPath, 'utf-8'));\n const gitlabAuth = authData?.gitlab;\n\n if (!gitlabAuth) {\n return undefined;\n }\n\n // Handle OAuth token structure (type: \"oauth\", access: \"token\")\n if (gitlabAuth.type === 'oauth' && gitlabAuth.access) {\n return gitlabAuth.access;\n }\n\n // Handle API token structure (type: \"api\", key: \"token\")\n if (gitlabAuth.type === 'api' && gitlabAuth.key) {\n return gitlabAuth.key;\n }\n\n // Fallback to direct token field\n return gitlabAuth.token || undefined;\n } catch (error) {\n // Silently fail if we can't read the auth file\n return undefined;\n }\n}\n\n/**\n * Get GitLab API client from environment or auth storage\n */\nexport function getGitLabClient(): GitLabApiClient {\n // First try GITLAB_TOKEN environment variable\n let token = process.env['GITLAB_TOKEN'];\n\n // If not found, try reading from OpenCode auth storage\n if (!token) {\n token = readTokenFromAuthStorage();\n }\n\n if (!token) {\n throw new Error(\n 'GitLab API token not found. Set GITLAB_TOKEN environment variable or configure it in OpenCode auth storage (~/.local/share/opencode/auth.json).'\n );\n }\n\n const instanceUrl = process.env['GITLAB_INSTANCE_URL'] || 'https://gitlab.com';\n return new GitLabApiClient(instanceUrl, token);\n}\n","/**\n * Pagination info from GitLab API response headers\n */\nexport interface PaginationInfo {\n total?: number;\n totalPages?: number;\n page?: number;\n perPage?: number;\n nextPage?: number;\n prevPage?: number;\n}\n\n/**\n * Response with pagination info for list endpoints\n */\nexport interface PaginatedResponse<T> {\n data: T;\n pagination: PaginationInfo;\n}\n\n/**\n * Base GitLab API client with common HTTP methods\n */\nexport class GitLabApiClient {\n protected instanceUrl: string;\n protected token: string;\n\n constructor(instanceUrl: string, token: string) {\n this.instanceUrl = instanceUrl.replace(/\\/$/, ''); // Remove trailing slash\n this.token = token;\n }\n\n protected get headers(): Record<string, string> {\n return {\n Authorization: `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n };\n }\n\n protected encodeProjectId(projectId: string): string {\n // If it contains a slash, URL-encode the entire path\n if (projectId.includes('/')) {\n return encodeURIComponent(projectId);\n }\n return projectId;\n }\n\n /**\n * Core HTTP request used by all REST helpers.\n *\n * Returns the raw `Response` after validating the status code so callers can\n * inspect headers (e.g. for pagination) before parsing the body.\n */\n protected async rawFetch(method: string, path: string, body?: unknown): Promise<Response> {\n const url = `${this.instanceUrl}/api/v4${path}`;\n\n const response = await fetch(url, {\n method,\n headers: this.headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`GitLab API error ${response.status}: ${errorText}`);\n }\n\n return response;\n }\n\n async fetch<T>(method: string, path: string, body?: unknown): Promise<T> {\n const response = await this.rawFetch(method, path, body);\n\n // Handle empty responses\n const text = await response.text();\n if (!text) {\n return {} as T;\n }\n\n return JSON.parse(text) as T;\n }\n\n /**\n * Parse a numeric pagination header, guarding against empty strings.\n *\n * GitLab returns `\"\"` (rather than omitting the header) for `X-Next-Page` and\n * `X-Prev-Page` when there is no next/prev page, and bare `parseInt` without\n * a radix on an empty string yields `NaN`. Treat empty/missing as `undefined`.\n */\n private parsePaginationHeader(response: Response, name: string): number | undefined {\n const raw = response.headers.get(name);\n if (raw == null || raw === '') return undefined;\n const value = parseInt(raw, 10);\n return Number.isNaN(value) ? undefined : value;\n }\n\n /**\n * Pagination info extracted from GitLab API response headers\n */\n protected extractPaginationInfo(response: Response): PaginationInfo {\n return {\n total: this.parsePaginationHeader(response, 'X-Total'),\n totalPages: this.parsePaginationHeader(response, 'X-Total-Pages'),\n page: this.parsePaginationHeader(response, 'X-Page'),\n perPage: this.parsePaginationHeader(response, 'X-Per-Page'),\n nextPage: this.parsePaginationHeader(response, 'X-Next-Page'),\n prevPage: this.parsePaginationHeader(response, 'X-Prev-Page'),\n };\n }\n\n /**\n * Fetch with pagination info from response headers.\n * Use this for list endpoints where knowing if more data exists is important.\n */\n protected async fetchWithPagination<T>(\n method: string,\n path: string,\n body?: unknown\n ): Promise<PaginatedResponse<T>> {\n const response = await this.rawFetch(method, path, body);\n\n const text = await response.text();\n const data = text ? (JSON.parse(text) as T) : ([] as unknown as T);\n const pagination = this.extractPaginationInfo(response);\n\n return { data, pagination };\n }\n\n async fetchText(method: string, path: string): Promise<string> {\n const url = `${this.instanceUrl}/api/v4${path}`;\n\n const response = await fetch(url, {\n method,\n headers: this.headers,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`GitLab API error ${response.status}: ${errorText}`);\n }\n\n return response.text();\n }\n\n /**\n * Execute a GraphQL query or mutation\n * @template T - The expected type of the data field in the GraphQL response\n * @param query - The GraphQL query or mutation string\n * @param variables - Optional variables for the query\n * @returns The data from the GraphQL response\n */\n async fetchGraphQL<T>(query: string, variables?: Record<string, unknown>): Promise<T> {\n const url = `${this.instanceUrl}/api/graphql`;\n\n const response = await fetch(url, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify({ query, variables }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`GitLab GraphQL error ${response.status}: ${errorText}`);\n }\n\n const result = await response.json();\n\n // Check for GraphQL errors\n if (result.errors && result.errors.length > 0) {\n const errorMessages = result.errors.map((e: { message: string }) => e.message).join(', ');\n throw new Error(`GraphQL errors: ${errorMessages}`);\n }\n\n return result.data as T;\n }\n}\n","/**\n * Shared types for GraphQL notes pagination\n */\n\nexport interface NotesPageInfo {\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n startCursor: string | null;\n endCursor: string | null;\n}\n\nexport interface NoteAuthor {\n id: string;\n username: string;\n name: string;\n avatarUrl: string | null;\n}\n\nexport interface NoteNode {\n id: string;\n body: string;\n bodyHtml: string | null;\n createdAt: string;\n updatedAt: string;\n system: boolean;\n internal: boolean;\n resolvable: boolean;\n resolved: boolean;\n resolvedAt: string | null;\n author: NoteAuthor | null;\n url: string | null;\n}\n\nexport interface NotesConnection {\n nodes: NoteNode[];\n pageInfo: NotesPageInfo;\n count?: number;\n}\n\nexport interface NotesResult {\n notes: NotesConnection;\n pageInfo: NotesPageInfo;\n totalCount?: number;\n}\n\nexport interface NotesPaginationOptions {\n first?: number;\n after?: string;\n last?: number;\n before?: string;\n}\n\nexport function buildPaginationVariables(\n options?: NotesPaginationOptions\n): Record<string, unknown> {\n const variables: Record<string, unknown> = {};\n\n if (options?.first !== undefined) {\n variables.first = options.first;\n } else if (options?.last == null) {\n variables.first = 20;\n }\n\n if (options?.after) variables.after = options.after;\n if (options?.last !== undefined) variables.last = options.last;\n if (options?.before) variables.before = options.before;\n\n return variables;\n}\n\nexport const NOTES_FRAGMENT = `\n fragment NoteFields on Note {\n id\n body\n bodyHtml\n createdAt\n updatedAt\n system\n internal\n resolvable\n resolved\n resolvedAt\n url\n author {\n id\n username\n name\n avatarUrl\n }\n }\n`;\n\nexport const NOTES_CONNECTION_FRAGMENT = `\n fragment NotesConnectionFields on NoteConnection {\n count\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n nodes {\n ...NoteFields\n }\n }\n`;\n","/**\n * Shared types for GraphQL discussions pagination\n */\n\nexport interface DiscussionsPageInfo {\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n startCursor: string | null;\n endCursor: string | null;\n}\n\nexport interface DiscussionNoteAuthor {\n id: string;\n username: string;\n name: string;\n avatarUrl: string | null;\n}\n\nexport interface DiscussionNote {\n id: string;\n body: string;\n bodyHtml: string | null;\n createdAt: string;\n updatedAt: string;\n system: boolean;\n resolvable: boolean;\n resolved: boolean;\n resolvedAt: string | null;\n author: DiscussionNoteAuthor | null;\n url: string | null;\n}\n\nexport interface DiscussionNode {\n id: string;\n replyId: string;\n createdAt: string;\n resolved: boolean;\n resolvable: boolean;\n resolvedAt: string | null;\n resolvedBy: DiscussionNoteAuthor | null;\n notes: {\n nodes: DiscussionNote[];\n };\n}\n\nexport interface DiscussionsConnection {\n nodes: DiscussionNode[];\n pageInfo: DiscussionsPageInfo;\n}\n\nexport interface DiscussionsResult {\n discussions: DiscussionsConnection;\n}\n\nexport interface DiscussionsPaginationOptions {\n first?: number;\n after?: string;\n last?: number;\n before?: string;\n}\n\nexport function buildDiscussionsPaginationVariables(\n options?: DiscussionsPaginationOptions\n): Record<string, unknown> {\n const variables: Record<string, unknown> = {};\n\n if (options?.first !== undefined) {\n variables.first = options.first;\n } else if (options?.last == null) {\n variables.first = 20;\n }\n\n if (options?.after) variables.after = options.after;\n if (options?.last !== undefined) variables.last = options.last;\n if (options?.before) variables.before = options.before;\n\n return variables;\n}\n\nexport const DISCUSSION_NOTE_FRAGMENT = `\n fragment DiscussionNoteFields on Note {\n id\n body\n bodyHtml\n createdAt\n updatedAt\n system\n resolvable\n resolved\n resolvedAt\n url\n author {\n id\n username\n name\n avatarUrl\n }\n }\n`;\n\nexport const DISCUSSION_FRAGMENT = `\n fragment DiscussionFields on Discussion {\n id\n replyId\n createdAt\n resolved\n resolvable\n resolvedAt\n resolvedBy {\n id\n username\n name\n avatarUrl\n }\n notes {\n nodes {\n ...DiscussionNoteFields\n }\n }\n }\n`;\n\nexport const DISCUSSIONS_CONNECTION_FRAGMENT = `\n fragment DiscussionsConnectionFields on DiscussionConnection {\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n nodes {\n ...DiscussionFields\n }\n }\n`;\n","import { GitLabApiClient, PaginatedResponse } from './base.js';\nimport {\n NotesResult,\n NotesConnection,\n NotesPaginationOptions,\n NOTES_FRAGMENT,\n NOTES_CONNECTION_FRAGMENT,\n buildPaginationVariables,\n} from './notes-types.js';\nimport {\n DiscussionsResult,\n DiscussionsConnection,\n DiscussionsPaginationOptions,\n DISCUSSION_NOTE_FRAGMENT,\n DISCUSSION_FRAGMENT,\n DISCUSSIONS_CONNECTION_FRAGMENT,\n buildDiscussionsPaginationVariables,\n} from './discussions-types.js';\n\nconst LIST_MR_NOTES_QUERY = `\n ${NOTES_FRAGMENT}\n ${NOTES_CONNECTION_FRAGMENT}\n query listMrNotes(\n $projectPath: ID!\n $mrIid: String!\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n project(fullPath: $projectPath) {\n mergeRequest(iid: $mrIid) {\n notes(\n first: $first\n after: $after\n last: $last\n before: $before\n ) {\n ...NotesConnectionFields\n }\n }\n }\n }\n`;\n\nconst LIST_MR_DISCUSSIONS_QUERY = `\n ${DISCUSSION_NOTE_FRAGMENT}\n ${DISCUSSION_FRAGMENT}\n ${DISCUSSIONS_CONNECTION_FRAGMENT}\n query listMrDiscussions(\n $projectPath: ID!\n $mrIid: String!\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n project(fullPath: $projectPath) {\n mergeRequest(iid: $mrIid) {\n discussions(\n first: $first\n after: $after\n last: $last\n before: $before\n ) {\n ...DiscussionsConnectionFields\n }\n }\n }\n }\n`;\n\nconst SET_AUTO_MERGE_MUTATION = `\n mutation setAutoMerge(\n $projectPath: ID!\n $iid: String!\n $sha: String!\n $strategy: MergeStrategyEnum\n ) {\n mergeRequestAccept(\n input: {\n projectPath: $projectPath\n iid: $iid\n sha: $sha\n strategy: $strategy\n }\n ) {\n mergeRequest {\n id\n iid\n title\n autoMergeEnabled\n autoMergeStrategy\n }\n errors\n }\n }\n`;\n\nconst OVERRIDE_REQUESTED_CHANGES_MUTATION = `\n mutation overrideRequestedChanges(\n $projectPath: ID!\n $iid: String!\n $override: Boolean\n ) {\n mergeRequestUpdate(\n input: {\n projectPath: $projectPath\n iid: $iid\n overrideRequestedChanges: $override\n }\n ) {\n mergeRequest {\n id\n iid\n title\n detailedMergeStatus\n }\n errors\n }\n }\n`;\n\nconst RESOLVE_DISCUSSION_MUTATION = `\n mutation resolveDiscussion($discussionId: DiscussionID!, $resolve: Boolean!) {\n discussionToggleResolve(input: { id: $discussionId, resolve: $resolve }) {\n discussion {\n id\n resolved\n resolvedAt\n resolvedBy {\n id\n username\n name\n }\n }\n errors\n }\n }\n`;\n\n/**\n * GitLab API client for Merge Request operations\n */\nexport class MergeRequestsClient extends GitLabApiClient {\n async getMergeRequest(projectId: string, mrIid: number, includeChanges?: boolean) {\n const encodedProject = this.encodeProjectId(projectId);\n let path = `/projects/${encodedProject}/merge_requests/${mrIid}`;\n if (includeChanges) {\n path += '?include_diverged_commits_count=true';\n }\n return this.fetch<Record<string, unknown>>('GET', path);\n }\n\n async listMergeRequests(options: {\n projectId?: string;\n state?: string;\n scope?: string;\n search?: string;\n labels?: string;\n limit?: number;\n page?: number;\n }): Promise<PaginatedResponse<Record<string, unknown>[]>> {\n const params = new URLSearchParams();\n params.set('per_page', String(options.limit || 20));\n if (options.page) params.set('page', String(options.page));\n\n if (options.state) params.set('state', options.state);\n if (options.scope) params.set('scope', options.scope);\n if (options.search) params.set('search', options.search);\n if (options.labels) params.set('labels', options.labels);\n\n let path: string;\n if (options.projectId) {\n const encodedProject = this.encodeProjectId(options.projectId);\n path = `/projects/${encodedProject}/merge_requests?${params}`;\n } else {\n path = `/merge_requests?${params}`;\n }\n\n return this.fetchWithPagination<Record<string, unknown>[]>('GET', path);\n }\n\n async getMrChanges(projectId: string, mrIid: number) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/merge_requests/${mrIid}/changes`\n );\n }\n\n /**\n * List notes on a merge request using GraphQL API with pagination support\n */\n async listMrNotes(\n projectId: string,\n mrIid: number,\n options?: NotesPaginationOptions\n ): Promise<NotesResult> {\n const variables: Record<string, unknown> = {\n projectPath: projectId,\n mrIid: String(mrIid),\n ...buildPaginationVariables(options),\n };\n\n const result = await this.fetchGraphQL<{\n project: {\n mergeRequest: {\n notes: NotesConnection;\n };\n };\n }>(LIST_MR_NOTES_QUERY, variables);\n\n const notes = result.project?.mergeRequest?.notes;\n if (!notes) {\n throw new Error('Merge request not found or access denied');\n }\n\n return {\n notes,\n pageInfo: notes.pageInfo,\n totalCount: notes.count,\n };\n }\n\n /**\n * List discussions on a merge request using GraphQL API with pagination support\n */\n async listMrDiscussions(\n projectId: string,\n mrIid: number,\n options?: DiscussionsPaginationOptions\n ): Promise<DiscussionsResult> {\n const variables: Record<string, unknown> = {\n projectPath: projectId,\n mrIid: String(mrIid),\n ...buildDiscussionsPaginationVariables(options),\n };\n\n const result = await this.fetchGraphQL<{\n project: {\n mergeRequest: {\n discussions: DiscussionsConnection;\n };\n };\n }>(LIST_MR_DISCUSSIONS_QUERY, variables);\n\n const discussions = result.project?.mergeRequest?.discussions;\n if (!discussions) {\n throw new Error('Merge request not found or access denied');\n }\n\n return { discussions };\n }\n\n async getMrDiscussion(projectId: string, mrIid: number, discussionId: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/merge_requests/${mrIid}/discussions/${discussionId}`\n );\n }\n\n async resolveMrDiscussion(projectId: string, mrIid: number, discussionId: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/projects/${encodedProject}/merge_requests/${mrIid}/discussions/${discussionId}`,\n { resolved: true }\n );\n }\n\n async unresolveMrDiscussion(projectId: string, mrIid: number, discussionId: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/projects/${encodedProject}/merge_requests/${mrIid}/discussions/${discussionId}`,\n { resolved: false }\n );\n }\n\n /**\n * Resolve or unresolve a discussion using GraphQL API.\n * This works for all discussions including outdated ones (resolved: null)\n * which the REST API cannot handle.\n *\n * @param discussionId - The discussion ID (can be short ID or full gid://gitlab/Discussion/ID format)\n * @param resolve - Whether to resolve (true) or unresolve (false) the discussion\n */\n async toggleDiscussionResolved(discussionId: string, resolve: boolean) {\n const gid = discussionId.startsWith('gid://')\n ? discussionId\n : `gid://gitlab/Discussion/${discussionId}`;\n\n const result = await this.fetchGraphQL<{\n discussionToggleResolve: {\n discussion: {\n id: string;\n resolved: boolean;\n resolvedAt: string | null;\n resolvedBy: {\n id: string;\n username: string;\n name: string;\n } | null;\n } | null;\n errors: string[];\n };\n }>(RESOLVE_DISCUSSION_MUTATION, {\n discussionId: gid,\n resolve,\n });\n\n if (result.discussionToggleResolve.errors.length > 0) {\n throw new Error(\n `Failed to ${resolve ? 'resolve' : 'unresolve'} discussion: ${result.discussionToggleResolve.errors.join(', ')}`\n );\n }\n\n if (!result.discussionToggleResolve.discussion) {\n throw new Error(\n `Failed to ${resolve ? 'resolve' : 'unresolve'} discussion: No discussion returned`\n );\n }\n\n return result.discussionToggleResolve.discussion;\n }\n\n async createMrDiscussion(\n projectId: string,\n mrIid: number,\n body: string,\n position?: {\n base_sha: string;\n start_sha: string;\n head_sha: string;\n position_type: 'text' | 'image';\n new_path?: string;\n old_path?: string;\n new_line?: number;\n old_line?: number;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const requestBody: Record<string, unknown> = { body };\n if (position) {\n requestBody.position = position;\n }\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/merge_requests/${mrIid}/discussions`,\n requestBody\n );\n }\n\n async createMrNote(projectId: string, mrIid: number, body: string, discussionId?: string) {\n const encodedProject = this.encodeProjectId(projectId);\n if (discussionId) {\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/merge_requests/${mrIid}/discussions/${discussionId}/notes`,\n { body }\n );\n }\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/merge_requests/${mrIid}/notes`,\n { body }\n );\n }\n\n async updateMrNote(projectId: string, mrIid: number, noteId: number, body: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/projects/${encodedProject}/merge_requests/${mrIid}/notes/${noteId}`,\n { body }\n );\n }\n\n async createMergeRequest(\n projectId: string,\n options: {\n source_branch: string;\n target_branch: string;\n title: string;\n description?: string;\n assignee_ids?: number[];\n reviewer_ids?: number[];\n labels?: string;\n milestone_id?: number;\n remove_source_branch?: boolean;\n squash?: boolean;\n allow_collaboration?: boolean;\n target_project_id?: number;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/merge_requests`,\n options\n );\n }\n\n async updateMergeRequest(\n projectId: string,\n mrIid: number,\n options: {\n title?: string;\n description?: string;\n state_event?: string;\n assignee_ids?: number[];\n reviewer_ids?: number[];\n labels?: string;\n milestone_id?: number;\n remove_source_branch?: boolean;\n squash?: boolean;\n target_branch?: string;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/projects/${encodedProject}/merge_requests/${mrIid}`,\n options\n );\n }\n\n async getMrCommits(projectId: string, mrIid: number) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/merge_requests/${mrIid}/commits`\n );\n }\n\n async getMrPipelines(projectId: string, mrIid: number) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/merge_requests/${mrIid}/pipelines`\n );\n }\n\n /**\n * Add a reviewer to a merge request without affecting existing reviewers\n */\n async addReviewer(projectId: string, mrIid: number, reviewerId: number) {\n const mr = await this.getMergeRequest(projectId, mrIid);\n const currentReviewers = (mr.reviewers as Array<{ id: number }>) || [];\n const currentReviewerIds = currentReviewers.map((r) => r.id);\n\n if (currentReviewerIds.includes(reviewerId)) {\n return mr;\n }\n\n const newReviewerIds = [...currentReviewerIds, reviewerId];\n return this.updateMergeRequest(projectId, mrIid, { reviewer_ids: newReviewerIds });\n }\n\n /**\n * Remove a reviewer from a merge request without affecting other reviewers\n */\n async removeReviewer(projectId: string, mrIid: number, reviewerId: number) {\n const mr = await this.getMergeRequest(projectId, mrIid);\n const currentReviewers = (mr.reviewers as Array<{ id: number }>) || [];\n const currentReviewerIds = currentReviewers.map((r) => r.id);\n\n if (!currentReviewerIds.includes(reviewerId)) {\n return mr;\n }\n\n const newReviewerIds = currentReviewerIds.filter((id) => id !== reviewerId);\n return this.updateMergeRequest(projectId, mrIid, { reviewer_ids: newReviewerIds });\n }\n\n async listMergeRequestDiffs(\n projectId: string,\n mrIid: number,\n options: {\n page?: number;\n per_page?: number;\n } = {}\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const params = new URLSearchParams();\n\n if (options.page) params.append('page', options.page.toString());\n if (options.per_page) params.append('per_page', options.per_page.toString());\n\n const query = params.toString();\n const path = `/projects/${encodedProject}/merge_requests/${mrIid}/diffs${query ? `?${query}` : ''}`;\n\n return this.fetch<Record<string, unknown>[]>('GET', path);\n }\n\n /**\n * Set auto-merge (MWPS) on a merge request using GraphQL API\n * Uses the mergeRequestAccept mutation with a merge strategy\n */\n async setAutoMerge(\n projectId: string,\n mrIid: number,\n sha: string,\n strategy:\n | 'MERGE_WHEN_CHECKS_PASS'\n | 'ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS' = 'MERGE_WHEN_CHECKS_PASS',\n retries = 3\n ) {\n // GitLab rejects the mergeRequestAccept mutation while a merge request's\n // mergeability is still being (re)computed, returning a transient error\n // such as \"mergeability is being checked\" or \"cannot be merged\". This is\n // not a real failure: the check settles within a second or two. Retry a\n // few times with backoff on those transient errors before giving up.\n let lastError: Error | null = null;\n for (let attempt = 0; attempt <= retries; attempt++) {\n const result = await this.fetchGraphQL<{\n mergeRequestAccept: {\n mergeRequest: {\n id: string;\n iid: string;\n title: string;\n autoMergeEnabled: boolean;\n autoMergeStrategy: string;\n } | null;\n errors: string[];\n };\n }>(SET_AUTO_MERGE_MUTATION, {\n projectPath: projectId,\n iid: String(mrIid),\n sha: sha,\n strategy: strategy,\n });\n\n if (result.mergeRequestAccept.errors.length > 0) {\n const message = result.mergeRequestAccept.errors.join(', ');\n lastError = new Error(`Failed to set auto-merge: ${message}`);\n if (attempt < retries && MergeRequestsClient.isTransientMergeError(message)) {\n await MergeRequestsClient.delay(750 * (attempt + 1));\n continue;\n }\n throw lastError;\n }\n\n if (!result.mergeRequestAccept.mergeRequest) {\n lastError = new Error('Failed to set auto-merge: No merge request returned');\n if (attempt < retries) {\n await MergeRequestsClient.delay(750 * (attempt + 1));\n continue;\n }\n throw lastError;\n }\n\n return result.mergeRequestAccept.mergeRequest;\n }\n\n // Unreachable in practice (the loop either returns or throws), but keeps\n // the type checker happy and surfaces the last transient error if it ever\n // falls through.\n throw lastError ?? new Error('Failed to set auto-merge: exhausted retries');\n }\n\n /**\n * True for GitLab merge errors that are transient because mergeability is\n * still being (re)computed. Such errors clear on their own within a second\n * or two, so callers should retry rather than treat them as real failures.\n */\n private static isTransientMergeError(message: string): boolean {\n const m = message.toLowerCase();\n return (\n m.includes('being checked') ||\n m.includes('being recomputed') ||\n m.includes('cannot be merged') ||\n m.includes('not mergeable') ||\n m.includes('merge failed') ||\n m.includes('try again')\n );\n }\n\n /** Small awaitable delay helper (ms). */\n private static delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n /**\n * Override (or clear an override of) requested changes on a merge request.\n *\n * When a reviewer formally requests changes, the \"Change requests must be\n * approved by the requesting user\" merge check blocks the merge. Setting the\n * persistent `override_requested_changes` flag downgrades that check from a\n * blocking failure to a non-blocking warning, which is what the \"Bypass\"\n * button in the merge request widget does. This is distinct from\n * `mergeRequestDestroyRequestedChanges`, which only clears the calling user's\n * own requested-changes review.\n *\n * Requires permission to merge to the target branch (otherwise GitLab\n * silently ignores the flag).\n *\n * @param projectId Project ID or URL-encoded path\n * @param mrIid Internal ID of the merge request\n * @param override true to bypass requested changes, false to re-enable the block\n * @returns The updated merge request (id, iid, title, detailedMergeStatus)\n */\n async overrideRequestedChanges(projectId: string, mrIid: number, override: boolean = true) {\n const result = await this.fetchGraphQL<{\n mergeRequestUpdate: {\n mergeRequest: {\n id: string;\n iid: string;\n title: string;\n detailedMergeStatus: string;\n } | null;\n errors: string[];\n };\n }>(OVERRIDE_REQUESTED_CHANGES_MUTATION, {\n projectPath: projectId,\n iid: String(mrIid),\n override,\n });\n\n if (result.mergeRequestUpdate.errors.length > 0) {\n throw new Error(\n `Failed to override requested changes: ${result.mergeRequestUpdate.errors.join(', ')}`\n );\n }\n\n if (!result.mergeRequestUpdate.mergeRequest) {\n throw new Error('Failed to override requested changes: No merge request returned');\n }\n\n return result.mergeRequestUpdate.mergeRequest;\n }\n\n /**\n * Approve a merge request\n * Requires at least Developer role on the project\n */\n async approveMergeRequest(projectId: string, mrIid: number, sha?: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/merge_requests/${mrIid}/approve`,\n sha ? { sha } : undefined\n );\n }\n\n /**\n * Unapprove (revoke approval from) a merge request\n * Only removes the current user's approval\n */\n async unapproveMergeRequest(projectId: string, mrIid: number) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/merge_requests/${mrIid}/unapprove`\n );\n }\n\n /**\n * Merge a merge request immediately\n * Requires the MR to be in a mergeable state (approved, pipeline passed, no conflicts)\n */\n async mergeMergeRequest(\n projectId: string,\n mrIid: number,\n options?: {\n sha?: string;\n squash?: boolean;\n shouldRemoveSourceBranch?: boolean;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const body: Record<string, unknown> = {};\n if (options?.sha) body.sha = options.sha;\n if (options?.squash !== undefined) body.squash = options.squash;\n if (options?.shouldRemoveSourceBranch !== undefined) {\n body.should_remove_source_branch = options.shouldRemoveSourceBranch;\n }\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/projects/${encodedProject}/merge_requests/${mrIid}/merge`,\n Object.keys(body).length > 0 ? body : undefined\n );\n }\n\n /**\n * Resolve the auto-merge strategy for a project.\n *\n * When the caller does not specify a strategy, projects with merge trains\n * enabled require ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS; otherwise\n * MERGE_WHEN_CHECKS_PASS is correct. Using the wrong one causes auto-merge to\n * fail with an opaque \"The merge failed\" error. Falls back to\n * MERGE_WHEN_CHECKS_PASS if the project setting cannot be read.\n *\n * Returns both the chosen strategy and how it was arrived at, so the caller\n * can thread a breadcrumb into its result. A bare fallback would collapse a\n * 401, a network timeout, and a genuine 404 all into a silent MWPS default,\n * reintroducing the opaque \"The merge failed\" this behaviour exists to\n * eliminate; `detection` makes that observable without changing the fallback.\n */\n private async resolveAutoMergeStrategy(projectId: string): Promise<{\n strategy: 'MERGE_WHEN_CHECKS_PASS' | 'ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS';\n detection: 'merge_trains_enabled' | 'merge_trains_disabled' | 'defaulted_after_error';\n reason?: string;\n }> {\n try {\n const encodedProject = this.encodeProjectId(projectId);\n const project = await this.fetch<{ merge_trains_enabled?: boolean }>(\n 'GET',\n `/projects/${encodedProject}`\n );\n return project.merge_trains_enabled\n ? {\n strategy: 'ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS',\n detection: 'merge_trains_enabled',\n }\n : { strategy: 'MERGE_WHEN_CHECKS_PASS', detection: 'merge_trains_disabled' };\n } catch (error) {\n return {\n strategy: 'MERGE_WHEN_CHECKS_PASS',\n detection: 'defaulted_after_error',\n reason: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n /**\n * Smart merge: merge immediately if checks pass, otherwise set auto-merge\n * Returns detailed context about what happened.\n *\n * If `strategy` is omitted, it is auto-detected from the project's merge\n * train settings (merge-train projects need ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS).\n */\n async smartMerge(\n projectId: string,\n mrIid: number,\n sha: string,\n strategy?: 'MERGE_WHEN_CHECKS_PASS' | 'ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS'\n ): Promise<{\n action: 'merged' | 'auto_merge_enabled' | 'failed';\n message: string;\n mergeRequest?: Record<string, unknown>;\n context?: {\n state: string;\n detailedMergeStatus: string;\n pipelineStatus: string | null;\n hasConflicts: boolean;\n hasAnyApproval: boolean;\n strategyDetection?: string;\n };\n }> {\n type SmartMergeMr = {\n state: string;\n detailed_merge_status: string;\n has_conflicts: boolean;\n sha: string;\n head_pipeline?: { status: string };\n approved_by?: unknown[];\n };\n\n let mr = (await this.getMergeRequest(projectId, mrIid)) as SmartMergeMr;\n\n // GitLab reports detailed_merge_status = 'checking' while it (re)computes\n // mergeability, which happens right after a push or when the MR is first\n // opened. Firing the auto-merge mutation during this window fails\n // transiently even though the MR is fine. Wait for the status to settle\n // into a terminal value before deciding how to merge, so we route to a\n // direct merge / auto-merge / clear failure based on the REAL state.\n if (mr.detailed_merge_status === 'checking') {\n for (let attempt = 0; attempt < 5 && mr.detailed_merge_status === 'checking'; attempt++) {\n await MergeRequestsClient.delay(1000 * (attempt + 1));\n mr = (await this.getMergeRequest(projectId, mrIid)) as SmartMergeMr;\n }\n }\n\n const context: {\n state: string;\n detailedMergeStatus: string;\n pipelineStatus: string | null;\n hasConflicts: boolean;\n hasAnyApproval: boolean;\n strategyDetection?: string;\n } = {\n state: mr.state,\n detailedMergeStatus: mr.detailed_merge_status,\n pipelineStatus: mr.head_pipeline?.status || null,\n hasConflicts: mr.has_conflicts,\n hasAnyApproval: (mr.approved_by?.length || 0) > 0,\n };\n\n if (mr.state !== 'opened') {\n return {\n action: 'failed',\n message: `MR is not open (state: ${mr.state})`,\n context,\n };\n }\n\n if (mr.has_conflicts) {\n return {\n action: 'failed',\n message: 'MR has merge conflicts that must be resolved',\n context,\n };\n }\n\n if (mr.detailed_merge_status === 'mergeable') {\n try {\n const result = await this.mergeMergeRequest(projectId, mrIid, { sha: mr.sha });\n return {\n action: 'merged',\n message: 'MR merged successfully',\n mergeRequest: result,\n context,\n };\n } catch (error) {\n return {\n action: 'failed',\n message: `Direct merge failed: ${error instanceof Error ? error.message : String(error)}`,\n context,\n };\n }\n }\n\n // 'checking' is intentionally NOT here: it is resolved to a terminal\n // status above before we get this far. Auto-merge is only appropriate when\n // the merge is genuinely pending (pipeline running or approval outstanding).\n const autoMergeStatuses = ['ci_still_running', 'not_approved'];\n if (autoMergeStatuses.includes(mr.detailed_merge_status)) {\n let resolvedStrategy: 'MERGE_WHEN_CHECKS_PASS' | 'ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS';\n if (strategy) {\n resolvedStrategy = strategy;\n context.strategyDetection = `explicit: ${strategy}`;\n } else {\n const detected = await this.resolveAutoMergeStrategy(projectId);\n resolvedStrategy = detected.strategy;\n context.strategyDetection =\n detected.detection === 'defaulted_after_error'\n ? `failed, defaulted to MERGE_WHEN_CHECKS_PASS${detected.reason ? ` (${detected.reason})` : ''}`\n : `auto-detected (${detected.detection}): ${detected.strategy}`;\n }\n try {\n const result = await this.setAutoMerge(projectId, mrIid, sha, resolvedStrategy);\n const autoMergeMessages: Record<string, string> = {\n ci_still_running: 'pipeline passes',\n not_approved: 'approved',\n };\n return {\n action: 'auto_merge_enabled',\n message: `Auto-merge enabled (${resolvedStrategy}). MR will merge when ${autoMergeMessages[mr.detailed_merge_status]}.`,\n mergeRequest: result as unknown as Record<string, unknown>,\n context,\n };\n } catch (error) {\n return {\n action: 'failed',\n message: `Failed to enable auto-merge: ${error instanceof Error ? error.message : String(error)}. MR status: ${mr.detailed_merge_status}, pipeline: ${mr.head_pipeline?.status || 'none'}`,\n context,\n };\n }\n }\n\n const statusHints: Record<string, string> = {\n discussions_not_resolved: 'Resolve all open discussion threads before merging.',\n draft_status: 'MR is in draft. Mark as ready before merging.',\n need_rebase: 'Source branch needs to be rebased onto the target branch.',\n requested_changes: 'A reviewer requested changes that must be addressed.',\n policies_denied: 'Merge is blocked by a security/compliance policy.',\n external_status_checks: 'External status checks must pass before merging.',\n jira_association_missing: 'MR must be linked to a Jira issue.',\n conflict: 'MR has merge conflicts that must be resolved.',\n };\n\n return {\n action: 'failed',\n message: statusHints[mr.detailed_merge_status] ?? `Cannot merge: ${mr.detailed_merge_status}`,\n context,\n };\n }\n}\n","import { GitLabApiClient, PaginatedResponse } from './base.js';\nimport {\n NotesResult,\n NotesConnection,\n NotesPaginationOptions,\n NOTES_FRAGMENT,\n NOTES_CONNECTION_FRAGMENT,\n buildPaginationVariables,\n} from './notes-types.js';\nimport {\n DiscussionsResult,\n DiscussionsConnection,\n DiscussionsPaginationOptions,\n DISCUSSION_NOTE_FRAGMENT,\n DISCUSSION_FRAGMENT,\n DISCUSSIONS_CONNECTION_FRAGMENT,\n buildDiscussionsPaginationVariables,\n} from './discussions-types.js';\n\nconst LIST_ISSUE_NOTES_QUERY = `\n ${NOTES_FRAGMENT}\n ${NOTES_CONNECTION_FRAGMENT}\n query listIssueNotes(\n $projectPath: ID!\n $issueIid: String!\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n project(fullPath: $projectPath) {\n issue(iid: $issueIid) {\n notes(\n first: $first\n after: $after\n last: $last\n before: $before\n ) {\n ...NotesConnectionFields\n }\n }\n }\n }\n`;\n\nconst LIST_ISSUE_DISCUSSIONS_QUERY = `\n ${DISCUSSION_NOTE_FRAGMENT}\n ${DISCUSSION_FRAGMENT}\n ${DISCUSSIONS_CONNECTION_FRAGMENT}\n query listIssueDiscussions(\n $projectPath: ID!\n $issueIid: String!\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n project(fullPath: $projectPath) {\n issue(iid: $issueIid) {\n discussions(\n first: $first\n after: $after\n last: $last\n before: $before\n ) {\n ...DiscussionsConnectionFields\n }\n }\n }\n }\n`;\n\n/**\n * GitLab API client for Issue operations\n */\nexport class IssuesClient extends GitLabApiClient {\n async createIssue(\n projectId: string,\n title: string,\n options?: {\n description?: string;\n assignee_ids?: number[];\n milestone_id?: number;\n labels?: string;\n due_date?: string;\n confidential?: boolean;\n weight?: number;\n epic_id?: number;\n issue_type?: string;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const body: Record<string, unknown> = {\n title,\n ...Object.fromEntries(\n Object.entries(options || {}).filter(([_, value]) => value !== undefined)\n ),\n };\n\n return this.fetch<Record<string, unknown>>('POST', `/projects/${encodedProject}/issues`, body);\n }\n\n async getIssue(projectId: string, issueIid: number) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/issues/${issueIid}`\n );\n }\n\n async listIssues(options: {\n projectId?: string;\n state?: string;\n scope?: string;\n search?: string;\n labels?: string;\n milestone?: string;\n limit?: number;\n page?: number;\n }): Promise<PaginatedResponse<Record<string, unknown>[]>> {\n const params = new URLSearchParams();\n params.set('per_page', String(options.limit || 20));\n if (options.page) params.set('page', String(options.page));\n\n if (options.state) params.set('state', options.state);\n if (options.scope) params.set('scope', options.scope);\n if (options.search) params.set('search', options.search);\n if (options.labels) params.set('labels', options.labels);\n if (options.milestone) params.set('milestone', options.milestone);\n\n let path: string;\n if (options.projectId) {\n const encodedProject = this.encodeProjectId(options.projectId);\n path = `/projects/${encodedProject}/issues?${params}`;\n } else {\n path = `/issues?${params}`;\n }\n\n return this.fetchWithPagination<Record<string, unknown>[]>('GET', path);\n }\n\n /**\n * List notes on an issue using GraphQL API with pagination support\n */\n async listIssueNotes(\n projectId: string,\n issueIid: number,\n options?: NotesPaginationOptions\n ): Promise<NotesResult> {\n const variables: Record<string, unknown> = {\n projectPath: projectId,\n issueIid: String(issueIid),\n ...buildPaginationVariables(options),\n };\n\n const result = await this.fetchGraphQL<{\n project: {\n issue: {\n notes: NotesConnection;\n };\n };\n }>(LIST_ISSUE_NOTES_QUERY, variables);\n\n const notes = result.project?.issue?.notes;\n if (!notes) {\n throw new Error('Issue not found or access denied');\n }\n\n return {\n notes,\n pageInfo: notes.pageInfo,\n totalCount: notes.count,\n };\n }\n\n /**\n * List discussions on an issue using GraphQL API with pagination support\n */\n async listIssueDiscussions(\n projectId: string,\n issueIid: number,\n options?: DiscussionsPaginationOptions\n ): Promise<DiscussionsResult> {\n const variables: Record<string, unknown> = {\n projectPath: projectId,\n issueIid: String(issueIid),\n ...buildDiscussionsPaginationVariables(options),\n };\n\n const result = await this.fetchGraphQL<{\n project: {\n issue: {\n discussions: DiscussionsConnection;\n };\n };\n }>(LIST_ISSUE_DISCUSSIONS_QUERY, variables);\n\n const discussions = result.project?.issue?.discussions;\n if (!discussions) {\n throw new Error('Issue not found or access denied');\n }\n\n return { discussions };\n }\n\n async getIssueDiscussion(projectId: string, issueIid: number, discussionId: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/issues/${issueIid}/discussions/${discussionId}`\n );\n }\n\n async createIssueNote(projectId: string, issueIid: number, body: string, discussionId?: string) {\n const encodedProject = this.encodeProjectId(projectId);\n if (discussionId) {\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/issues/${issueIid}/discussions/${discussionId}/notes`,\n { body }\n );\n }\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/issues/${issueIid}/notes`,\n { body }\n );\n }\n\n async resolveIssueDiscussion(projectId: string, issueIid: number, discussionId: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/projects/${encodedProject}/issues/${issueIid}/discussions/${discussionId}`,\n { resolved: true }\n );\n }\n\n async unresolveIssueDiscussion(projectId: string, issueIid: number, discussionId: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/projects/${encodedProject}/issues/${issueIid}/discussions/${discussionId}`,\n { resolved: false }\n );\n }\n\n async getIssueNote(projectId: string, issueIid: number, noteId: number) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/issues/${issueIid}/notes/${noteId}`\n );\n }\n\n async updateIssueNote(projectId: string, issueIid: number, noteId: number, body: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/projects/${encodedProject}/issues/${issueIid}/notes/${noteId}`,\n { body }\n );\n }\n}\n","import { GitLabApiClient } from './base.js';\n\nfunction toGid(type: string, id: string | number): string {\n return `gid://gitlab/${type}/${id}`;\n}\n\nconst WORK_ITEM_WIDGETS_FRAGMENT = `\n widgets {\n type\n ... on WorkItemWidgetAssignees {\n assignees {\n nodes {\n id\n username\n name\n }\n }\n }\n ... on WorkItemWidgetLabels {\n labels {\n nodes {\n id\n title\n color\n }\n }\n }\n }\n`;\n\nconst WORK_ITEM_FIELDS = `\n id\n iid\n title\n description\n state\n createdAt\n updatedAt\n confidential\n workItemType {\n id\n name\n }\n author {\n id\n username\n name\n }\n webUrl\n ${WORK_ITEM_WIDGETS_FRAGMENT}\n`;\n\nconst GET_WORK_ITEM_QUERY = `\n query getWorkItem($fullPath: ID!, $iid: String!) {\n workspace: project(fullPath: $fullPath) {\n workItems(iid: $iid, first: 1) {\n nodes {\n ${WORK_ITEM_FIELDS}\n }\n }\n }\n }\n`;\n\nconst LIST_WORK_ITEMS_QUERY = `\n query listWorkItems(\n $fullPath: ID!\n $state: WorkItemState\n $search: String\n $types: [WorkItemTypeEnum!]\n $labelNames: [String!]\n $first: Int\n ) {\n workspace: project(fullPath: $fullPath) {\n workItems(\n state: $state\n search: $search\n types: $types\n labelName: $labelNames\n first: $first\n ) {\n nodes {\n ${WORK_ITEM_FIELDS}\n }\n }\n }\n }\n`;\n\nconst LIST_GROUP_WORK_ITEMS_QUERY = `\n query listGroupWorkItems(\n $fullPath: ID!\n $state: WorkItemState\n $search: String\n $types: [WorkItemTypeEnum!]\n $labelNames: [String!]\n $first: Int\n ) {\n workspace: group(fullPath: $fullPath) {\n workItems(\n state: $state\n search: $search\n types: $types\n labelName: $labelNames\n first: $first\n ) {\n nodes {\n ${WORK_ITEM_FIELDS}\n }\n }\n }\n }\n`;\n\nconst GET_WORK_ITEM_NOTES_QUERY = `\n query getWorkItemNotes($fullPath: ID!, $iid: String!) {\n workspace: project(fullPath: $fullPath) {\n workItems(iid: $iid, first: 1) {\n nodes {\n id\n iid\n widgets {\n type\n ... on WorkItemWidgetNotes {\n discussions {\n nodes {\n id\n notes {\n nodes {\n id\n body\n createdAt\n updatedAt\n author {\n id\n username\n name\n }\n system\n resolvable\n resolved\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n`;\n\n// The widget inputs (labelsWidget, assigneesWidget) declare their id lists as\n// non-null (`[LabelID!]!` / `[UserID!]!`) on the create path. Threading a\n// nullable variable into them fails GraphQL variable-usage validation before\n// any value is bound. To stay compatible, the whole input object is built in\n// the client (see createWorkItem/updateWorkItem) and passed as a single\n// `$input` variable, omitting any widget the caller did not provide.\nconst CREATE_WORK_ITEM_MUTATION = `\n mutation createWorkItem($input: WorkItemCreateInput!) {\n workItemCreate(input: $input) {\n workItem {\n ${WORK_ITEM_FIELDS}\n }\n errors\n }\n }\n`;\n\nconst UPDATE_WORK_ITEM_MUTATION = `\n mutation updateWorkItem($input: WorkItemUpdateInput!) {\n workItemUpdate(input: $input) {\n workItem {\n ${WORK_ITEM_FIELDS}\n }\n errors\n }\n }\n`;\n\nconst CREATE_NOTE_MUTATION = `\n mutation createWorkItemNote($noteableId: NoteableID!, $body: String!) {\n createNote(input: { noteableId: $noteableId, body: $body }) {\n note {\n id\n body\n createdAt\n author {\n id\n username\n name\n }\n }\n errors\n }\n }\n`;\n\n// workItemUpdate and createNote mutations require the global GID (WorkItemID! / NoteableID!),\n// not the iid. This query resolves the iid to the GID before the mutation.\nconst GET_WORK_ITEM_GID_QUERY = `\n query getWorkItemGid($fullPath: ID!, $iid: String!) {\n workspace: project(fullPath: $fullPath) {\n workItems(iid: $iid, first: 1) {\n nodes {\n id\n }\n }\n }\n }\n`;\n\ntype WorkItemWidget = { type: string } & Record<string, unknown>;\n\nfunction flattenWidgets(raw: Record<string, unknown>): Record<string, unknown> {\n const widgets = raw.widgets as WorkItemWidget[] | undefined;\n if (!widgets) return raw;\n\n const assigneesWidget = widgets.find((w) => w.type === 'ASSIGNEES') as\n | { assignees?: { nodes: unknown[] } }\n | undefined;\n const labelsWidget = widgets.find((w) => w.type === 'LABELS') as\n | { labels?: { nodes: unknown[] } }\n | undefined;\n\n const { widgets: _w, ...rest } = raw;\n return {\n ...rest,\n assignees: assigneesWidget?.assignees?.nodes ?? [],\n labels: labelsWidget?.labels?.nodes ?? [],\n };\n}\n\nexport class WorkItemsClient extends GitLabApiClient {\n async getWorkItem(projectId: string, workItemIid: number) {\n const result = await this.fetchGraphQL<{\n workspace: {\n workItems: { nodes: Record<string, unknown>[] };\n };\n }>(GET_WORK_ITEM_QUERY, {\n fullPath: projectId,\n iid: String(workItemIid),\n });\n\n const workItem = result.workspace?.workItems?.nodes?.[0];\n if (!workItem) {\n throw new Error(`Work item with iid ${workItemIid} not found in project ${projectId}`);\n }\n return flattenWidgets(workItem);\n }\n\n async listWorkItems(options: {\n projectId?: string;\n groupId?: string;\n state?: string;\n search?: string;\n labels?: string;\n work_item_type?: string;\n limit?: number;\n }) {\n const variables: Record<string, unknown> = {\n state: options.state ? options.state.toUpperCase() : undefined,\n search: options.search,\n types: options.work_item_type ? [options.work_item_type.toUpperCase()] : undefined,\n labelNames: options.labels ? options.labels.split(',').map((l) => l.trim()) : undefined,\n first: options.limit || 20,\n };\n\n if (options.projectId) {\n const result = await this.fetchGraphQL<{\n workspace: {\n workItems: { nodes: Record<string, unknown>[] };\n };\n }>(LIST_WORK_ITEMS_QUERY, { fullPath: options.projectId, ...variables });\n\n return (result.workspace?.workItems?.nodes ?? []).map(flattenWidgets);\n } else if (options.groupId) {\n const result = await this.fetchGraphQL<{\n workspace: {\n workItems: { nodes: Record<string, unknown>[] };\n };\n }>(LIST_GROUP_WORK_ITEMS_QUERY, { fullPath: options.groupId, ...variables });\n\n return (result.workspace?.workItems?.nodes ?? []).map(flattenWidgets);\n } else {\n throw new Error('Either projectId or groupId must be provided');\n }\n }\n\n async getWorkItemNotes(projectId: string, workItemIid: number) {\n const result = await this.fetchGraphQL<{\n workspace: {\n workItems: {\n nodes: {\n id: string;\n iid: string;\n widgets: (WorkItemWidget & {\n discussions?: {\n nodes: { id: string; notes: { nodes: Record<string, unknown>[] } }[];\n };\n })[];\n }[];\n };\n };\n }>(GET_WORK_ITEM_NOTES_QUERY, {\n fullPath: projectId,\n iid: String(workItemIid),\n });\n\n const workItem = result.workspace?.workItems?.nodes?.[0];\n if (!workItem) {\n throw new Error(`Work item with iid ${workItemIid} not found in project ${projectId}`);\n }\n\n const notesWidget = workItem.widgets?.find((w) => w.type === 'NOTES');\n const discussions = notesWidget?.discussions?.nodes ?? [];\n return discussions.flatMap((d) => d.notes?.nodes ?? []);\n }\n\n async createWorkItem(\n projectId: string,\n options: {\n title: string;\n work_item_type_id: number;\n description?: string;\n labels?: string[];\n assignee_ids?: number[];\n }\n ) {\n const labelIds = options.labels?.map((l) => toGid('Label', l));\n const assigneeIds = options.assignee_ids?.map((id) => toGid('User', id));\n\n const input: Record<string, unknown> = {\n projectPath: projectId,\n title: options.title,\n workItemTypeId: toGid('WorkItems::Type', options.work_item_type_id),\n };\n\n if (options.description !== undefined) {\n input.descriptionWidget = { description: options.description };\n }\n if (labelIds?.length) {\n input.labelsWidget = { labelIds };\n }\n if (assigneeIds?.length) {\n input.assigneesWidget = { assigneeIds };\n }\n\n const result = await this.fetchGraphQL<{\n workItemCreate: {\n workItem: Record<string, unknown>;\n errors: string[];\n };\n }>(CREATE_WORK_ITEM_MUTATION, { input });\n\n if (result.workItemCreate.errors.length > 0) {\n throw new Error(`Failed to create work item: ${result.workItemCreate.errors.join(', ')}`);\n }\n\n return flattenWidgets(result.workItemCreate.workItem);\n }\n\n async updateWorkItem(\n projectId: string,\n workItemIid: number,\n options: {\n title?: string;\n description?: string;\n state_event?: string;\n labels?: string[];\n assignee_ids?: number[];\n }\n ) {\n const gidResult = await this.fetchGraphQL<{\n workspace: { workItems: { nodes: { id: string }[] } };\n }>(GET_WORK_ITEM_GID_QUERY, {\n fullPath: projectId,\n iid: String(workItemIid),\n });\n\n const gid = gidResult.workspace?.workItems?.nodes?.[0]?.id;\n if (!gid) {\n throw new Error(`Work item with iid ${workItemIid} not found in project ${projectId}`);\n }\n\n const stateEvent = options.state_event\n ? options.state_event === 'close'\n ? 'CLOSE'\n : 'REOPEN'\n : undefined;\n\n const labelIds = options.labels?.map((l) => toGid('Label', l));\n const assigneeIds = options.assignee_ids?.map((id) => toGid('User', id));\n\n const input: Record<string, unknown> = { id: gid };\n\n if (options.title !== undefined) {\n input.title = options.title;\n }\n if (options.description !== undefined) {\n input.descriptionWidget = { description: options.description };\n }\n if (stateEvent !== undefined) {\n input.stateEvent = stateEvent;\n }\n if (labelIds?.length) {\n // The update labels widget (WorkItemWidgetLabelsUpdateInput) exposes\n // addLabelIds/removeLabelIds rather than the create widget's labelIds.\n input.labelsWidget = { addLabelIds: labelIds };\n }\n if (assigneeIds?.length) {\n input.assigneesWidget = { assigneeIds };\n }\n\n const result = await this.fetchGraphQL<{\n workItemUpdate: {\n workItem: Record<string, unknown>;\n errors: string[];\n };\n }>(UPDATE_WORK_ITEM_MUTATION, { input });\n\n if (result.workItemUpdate.errors.length > 0) {\n throw new Error(`Failed to update work item: ${result.workItemUpdate.errors.join(', ')}`);\n }\n\n return flattenWidgets(result.workItemUpdate.workItem);\n }\n\n async createWorkItemNote(projectId: string, workItemIid: number, body: string) {\n const gidResult = await this.fetchGraphQL<{\n workspace: { workItems: { nodes: { id: string }[] } };\n }>(GET_WORK_ITEM_GID_QUERY, {\n fullPath: projectId,\n iid: String(workItemIid),\n });\n\n const gid = gidResult.workspace?.workItems?.nodes?.[0]?.id;\n if (!gid) {\n throw new Error(`Work item with iid ${workItemIid} not found in project ${projectId}`);\n }\n\n const result = await this.fetchGraphQL<{\n createNote: {\n note: Record<string, unknown>;\n errors: string[];\n };\n }>(CREATE_NOTE_MUTATION, {\n noteableId: gid,\n body,\n });\n\n if (result.createNote.errors.length > 0) {\n throw new Error(`Failed to create note: ${result.createNote.errors.join(', ')}`);\n }\n\n return result.createNote.note;\n }\n}\n","import { GitLabApiClient } from './base.js';\n\nexport class PipelinesClient extends GitLabApiClient {\n async listPipelines(\n projectId: string,\n options?: { status?: string; ref?: string; limit?: number }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const params = new URLSearchParams();\n params.set('per_page', String(options?.limit || 20));\n\n if (options?.status) params.set('status', options.status);\n if (options?.ref) params.set('ref', options.ref);\n\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/pipelines?${params}`\n );\n }\n\n async getPipeline(projectId: string, pipelineId: number) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/pipelines/${pipelineId}`\n );\n }\n\n async listPipelineJobs(projectId: string, pipelineId: number, scope?: string) {\n const encodedProject = this.encodeProjectId(projectId);\n const params = new URLSearchParams();\n if (scope) params.set('scope[]', scope);\n\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/pipelines/${pipelineId}/jobs?${params}`\n );\n }\n\n async getJobLog(projectId: string, jobId: number) {\n const encodedProject = this.encodeProjectId(projectId);\n const log = await this.fetchText('GET', `/projects/${encodedProject}/jobs/${jobId}/trace`);\n // Truncate very long logs\n const maxLength = 50000;\n if (log.length > maxLength) {\n return `[Log truncated, showing last ${maxLength} characters]\\n\\n${log.slice(-maxLength)}`;\n }\n return log;\n }\n\n async retryJob(projectId: string, jobId: number) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/jobs/${jobId}/retry`\n );\n }\n\n async getPipelineFailingJobs(projectId: string, pipelineId: number) {\n const encodedProject = this.encodeProjectId(projectId);\n const jobs = await this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/pipelines/${pipelineId}/jobs?scope[]=failed`\n );\n return jobs;\n }\n\n /**\n * Validate a CI/CD configuration\n * @param projectId - The project ID or URL-encoded path\n * @param content - The CI/CD configuration content (YAML as string)\n * @param options - Optional parameters\n * @param options.dry_run - Run pipeline creation simulation (default: false)\n * @param options.include_jobs - Include list of jobs in response (default: false)\n * @param options.ref - Branch or tag context for validation (defaults to project's default branch)\n * @returns Validation result with errors, warnings, and optionally merged YAML and jobs\n */\n async lintCiConfig(\n projectId: string,\n content: string,\n options?: {\n dry_run?: boolean;\n include_jobs?: boolean;\n ref?: string;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const body: Record<string, unknown> = {\n content,\n };\n\n if (options?.dry_run !== undefined) body.dry_run = options.dry_run;\n if (options?.include_jobs !== undefined) body.include_jobs = options.include_jobs;\n if (options?.ref) body.ref = options.ref;\n\n return this.fetch<{\n valid: boolean;\n errors: string[];\n warnings: string[];\n merged_yaml?: string;\n includes?: Array<{\n type: string;\n location: string;\n blob?: string;\n raw?: string;\n extra?: Record<string, unknown>;\n context_project?: string;\n context_sha?: string;\n }>;\n jobs?: Array<{\n name: string;\n stage: string;\n before_script: string[];\n script: string[];\n after_script: string[];\n tag_list: string[];\n only: Record<string, unknown> | null;\n except: Record<string, unknown> | null;\n environment: string | null;\n when: string;\n allow_failure: boolean;\n needs: unknown;\n }>;\n }>('POST', `/projects/${encodedProject}/ci/lint`, body);\n }\n\n /**\n * Validate an existing CI/CD configuration from the repository\n * @param projectId - The project ID or URL-encoded path\n * @param options - Optional parameters\n * @param options.content_ref - Commit SHA, branch or tag to get CI config from (defaults to default branch)\n * @param options.dry_run - Run pipeline creation simulation (default: false)\n * @param options.dry_run_ref - Branch or tag context for validation (defaults to project's default branch)\n * @param options.include_jobs - Include list of jobs in response (default: false)\n * @returns Validation result with errors, warnings, and optionally merged YAML and jobs\n */\n async lintExistingCiConfig(\n projectId: string,\n options?: {\n content_ref?: string;\n dry_run?: boolean;\n dry_run_ref?: string;\n include_jobs?: boolean;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const params = new URLSearchParams();\n\n if (options?.content_ref) params.set('content_ref', options.content_ref);\n if (options?.dry_run !== undefined) params.set('dry_run', String(options.dry_run));\n if (options?.dry_run_ref) params.set('dry_run_ref', options.dry_run_ref);\n if (options?.include_jobs !== undefined)\n params.set('include_jobs', String(options.include_jobs));\n\n const queryString = params.toString();\n const path = queryString\n ? `/projects/${encodedProject}/ci/lint?${queryString}`\n : `/projects/${encodedProject}/ci/lint`;\n\n return this.fetch<{\n valid: boolean;\n errors: string[];\n warnings: string[];\n merged_yaml?: string;\n includes?: Array<{\n type: string;\n location: string;\n blob?: string;\n raw?: string;\n extra?: Record<string, unknown>;\n context_project?: string;\n context_sha?: string;\n }>;\n jobs?: Array<{\n name: string;\n stage: string;\n before_script: string[];\n script: string[];\n after_script: string[];\n tag_list: string[];\n only: Record<string, unknown> | null;\n except: Record<string, unknown> | null;\n environment: string | null;\n when: string;\n allow_failure: boolean;\n needs: unknown;\n }>;\n }>('GET', path);\n }\n}\n","import { GitLabApiClient } from './base.js';\n\nexport class RepositoryClient extends GitLabApiClient {\n async getFile(projectId: string, filePath: string, ref?: string) {\n const encodedProject = this.encodeProjectId(projectId);\n const encodedPath = encodeURIComponent(filePath);\n\n // Build URL with optional ref parameter\n // When ref is omitted, GitLab API automatically uses the project's default branch\n let url = `/projects/${encodedProject}/repository/files/${encodedPath}`;\n if (ref) {\n url += `?ref=${encodeURIComponent(ref)}`;\n }\n\n const file = await this.fetch<{ content: string; encoding: string }>('GET', url);\n\n // Decode base64 content\n if (file.encoding === 'base64') {\n return Buffer.from(file.content, 'base64').toString('utf-8');\n }\n return file.content;\n }\n\n async listCommits(\n projectId: string,\n options?: { ref?: string; path?: string; since?: string; until?: string; limit?: number }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const params = new URLSearchParams();\n params.set('per_page', String(options?.limit || 20));\n\n if (options?.ref) params.set('ref_name', options.ref);\n if (options?.path) params.set('path', options.path);\n if (options?.since) params.set('since', options.since);\n if (options?.until) params.set('until', options.until);\n\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/repository/commits?${params}`\n );\n }\n\n async getCommit(projectId: string, sha: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/repository/commits/${sha}`\n );\n }\n\n async getCommitDiff(projectId: string, sha: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/repository/commits/${sha}/diff`\n );\n }\n\n async createCommit(\n projectId: string,\n options: {\n branch: string;\n commit_message: string;\n actions: Array<{\n action: 'create' | 'delete' | 'move' | 'update' | 'chmod';\n file_path: string;\n content?: string;\n encoding?: 'text' | 'base64';\n previous_path?: string;\n execute_filemode?: boolean;\n }>;\n author_email?: string;\n author_name?: string;\n start_branch?: string;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/repository/commits`,\n options\n );\n }\n\n async listRepositoryTree(\n projectId: string,\n options?: {\n path?: string;\n ref?: string;\n recursive?: boolean;\n per_page?: number;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const params = new URLSearchParams();\n\n if (options?.path) params.set('path', options.path);\n if (options?.ref) params.set('ref', options.ref);\n if (options?.recursive) params.set('recursive', 'true');\n if (options?.per_page) params.set('per_page', String(options.per_page));\n\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/repository/tree?${params}`\n );\n }\n\n async listBranches(projectId: string, search?: string) {\n const encodedProject = this.encodeProjectId(projectId);\n const params = new URLSearchParams();\n if (search) params.set('search', search);\n\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/repository/branches?${params}`\n );\n }\n\n // ========== Commit Discussion Methods ==========\n\n async listCommitDiscussions(projectId: string, sha: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/repository/commits/${sha}/discussions`\n );\n }\n\n async getCommitDiscussion(projectId: string, sha: string, discussionId: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/repository/commits/${sha}/discussions/${discussionId}`\n );\n }\n\n async createCommitNote(\n projectId: string,\n sha: string,\n body: string,\n options?: {\n discussion_id?: string;\n path?: string;\n line?: number;\n line_type?: 'new' | 'old';\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n // If discussion_id is provided, add note to existing discussion thread\n if (options?.discussion_id) {\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/repository/commits/${sha}/discussions/${options.discussion_id}/notes`,\n { body }\n );\n }\n // Otherwise create a new note (optionally positioned on a specific line)\n const requestBody: Record<string, unknown> = { body };\n if (options?.path) requestBody.path = options.path;\n if (options?.line) requestBody.line = options.line;\n if (options?.line_type) requestBody.line_type = options.line_type;\n\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/repository/commits/${sha}/comments`,\n requestBody\n );\n }\n\n async createCommitDiscussion(\n projectId: string,\n sha: string,\n body: string,\n position?: {\n base_sha: string;\n start_sha: string;\n head_sha: string;\n position_type: 'text' | 'image';\n new_path?: string;\n old_path?: string;\n new_line?: number;\n old_line?: number;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const requestBody: Record<string, unknown> = { body };\n if (position) {\n requestBody.position = position;\n }\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/repository/commits/${sha}/discussions`,\n requestBody\n );\n }\n\n /**\n * Get comments on a specific commit\n * API: GET /projects/:id/repository/commits/:sha/comments\n */\n async getCommitComments(projectId: string, sha: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/repository/commits/${sha}/comments`\n );\n }\n}\n","import { GitLabApiClient } from './base.js';\n\ninterface SearchOptions {\n state?: string;\n order_by?: string;\n sort?: string;\n ref?: string;\n limit?: number;\n}\n\nexport class SearchClient extends GitLabApiClient {\n async search(scope: string, searchQuery: string, projectId?: string, limit?: number) {\n const params = new URLSearchParams();\n params.set('scope', scope);\n params.set('search', searchQuery);\n params.set('per_page', String(limit || 20));\n\n let path: string;\n if (projectId) {\n const encodedProject = this.encodeProjectId(projectId);\n path = `/projects/${encodedProject}/search?${params}`;\n } else {\n path = `/search?${params}`;\n }\n\n return this.fetch<Record<string, unknown>[]>('GET', path);\n }\n\n /**\n * Search for commits in a project or globally\n * @param searchQuery - The search term\n * @param projectId - Optional project ID to limit search\n * @param options - Optional search parameters\n */\n async searchCommits(searchQuery: string, projectId?: string, options?: SearchOptions) {\n const params = new URLSearchParams();\n params.set('scope', 'commits');\n params.set('search', searchQuery);\n params.set('per_page', String(options?.limit || 20));\n\n if (options?.ref) params.set('ref', options.ref);\n if (options?.order_by) params.set('order_by', options.order_by);\n if (options?.sort) params.set('sort', options.sort);\n\n let path: string;\n if (projectId) {\n const encodedProject = this.encodeProjectId(projectId);\n path = `/projects/${encodedProject}/search?${params}`;\n } else {\n path = `/search?${params}`;\n }\n\n return this.fetch<Record<string, unknown>[]>('GET', path);\n }\n\n /**\n * Search for projects within a specific group\n * @param groupId - The group ID or URL-encoded path\n * @param searchQuery - The search term\n * @param options - Optional search parameters\n */\n async searchGroupProjects(groupId: string, searchQuery: string, options?: SearchOptions) {\n const encodedGroup = this.encodeProjectId(groupId);\n const params = new URLSearchParams();\n params.set('scope', 'projects');\n params.set('search', searchQuery);\n params.set('per_page', String(options?.limit || 20));\n\n if (options?.order_by) params.set('order_by', options.order_by);\n if (options?.sort) params.set('sort', options.sort);\n\n return this.fetch<Record<string, unknown>[]>('GET', `/groups/${encodedGroup}/search?${params}`);\n }\n\n /**\n * Search for milestones in a project or globally\n * @param searchQuery - The search term\n * @param projectId - Optional project ID to limit search\n * @param options - Optional search parameters\n */\n async searchMilestones(searchQuery: string, projectId?: string, options?: SearchOptions) {\n const params = new URLSearchParams();\n params.set('scope', 'milestones');\n params.set('search', searchQuery);\n params.set('per_page', String(options?.limit || 20));\n\n if (options?.state) params.set('state', options.state);\n if (options?.order_by) params.set('order_by', options.order_by);\n if (options?.sort) params.set('sort', options.sort);\n\n let path: string;\n if (projectId) {\n const encodedProject = this.encodeProjectId(projectId);\n path = `/projects/${encodedProject}/search?${params}`;\n } else {\n path = `/search?${params}`;\n }\n\n return this.fetch<Record<string, unknown>[]>('GET', path);\n }\n\n /**\n * Search for notes/comments in a project\n * @param searchQuery - The search term\n * @param projectId - The project ID to search in\n * @param options - Optional search parameters\n */\n async searchNotes(searchQuery: string, projectId: string, options?: SearchOptions) {\n const encodedProject = this.encodeProjectId(projectId);\n const params = new URLSearchParams();\n params.set('scope', 'notes');\n params.set('search', searchQuery);\n params.set('per_page', String(options?.limit || 20));\n\n if (options?.order_by) params.set('order_by', options.order_by);\n if (options?.sort) params.set('sort', options.sort);\n\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/search?${params}`\n );\n }\n\n /**\n * Search for users by name or email\n * @param searchQuery - The search term (name or email)\n * @param projectId - Optional project ID to limit search\n * @param options - Optional search parameters\n */\n async searchUsers(searchQuery: string, projectId?: string, options?: SearchOptions) {\n const params = new URLSearchParams();\n params.set('scope', 'users');\n params.set('search', searchQuery);\n params.set('per_page', String(options?.limit || 20));\n\n if (options?.order_by) params.set('order_by', options.order_by);\n if (options?.sort) params.set('sort', options.sort);\n\n let path: string;\n if (projectId) {\n const encodedProject = this.encodeProjectId(projectId);\n path = `/projects/${encodedProject}/search?${params}`;\n } else {\n path = `/search?${params}`;\n }\n\n return this.fetch<Record<string, unknown>[]>('GET', path);\n }\n\n /**\n * Search for wiki blobs (wiki content)\n * @param searchQuery - The search term (supports filters like filename:, path:, extension:)\n * @param projectId - Optional project ID to limit search\n * @param options - Optional search parameters\n */\n async searchWikiBlobs(searchQuery: string, projectId?: string, options?: SearchOptions) {\n const params = new URLSearchParams();\n params.set('scope', 'wiki_blobs');\n params.set('search', searchQuery);\n params.set('per_page', String(options?.limit || 20));\n\n if (options?.ref) params.set('ref', options.ref);\n if (options?.order_by) params.set('order_by', options.order_by);\n if (options?.sort) params.set('sort', options.sort);\n\n let path: string;\n if (projectId) {\n const encodedProject = this.encodeProjectId(projectId);\n path = `/projects/${encodedProject}/search?${params}`;\n } else {\n path = `/search?${params}`;\n }\n\n return this.fetch<Record<string, unknown>[]>('GET', path);\n }\n\n /**\n * Search GitLab documentation\n * Note: This uses the public GitLab docs search API\n * @param searchQuery - The search term\n * @param limit - Maximum number of results (default: 10)\n */\n async searchDocumentation(searchQuery: string, limit?: number) {\n // GitLab documentation search uses the public docs site\n // We'll use the Algolia search API that powers docs.gitlab.com\n const url = `https://docs.gitlab.com/search.json?q=${encodeURIComponent(searchQuery)}&limit=${limit || 10}`;\n\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(`Documentation search error ${response.status}: ${await response.text()}`);\n }\n\n return response.json();\n }\n}\n","import { GitLabApiClient } from './base.js';\n\nexport class ProjectsClient extends GitLabApiClient {\n async getProject(projectId: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>('GET', `/projects/${encodedProject}`);\n }\n\n async listProjectMembers(projectId: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>[]>('GET', `/projects/${encodedProject}/members`);\n }\n}\n","import { GitLabApiClient } from './base.js';\n\nexport interface UserStatus {\n emoji?: string;\n message?: string;\n availability?: 'not_set' | 'busy';\n clear_status_at?: string;\n}\n\nexport interface User {\n id: number;\n username: string;\n name: string;\n state: string;\n locked: boolean;\n avatar_url: string;\n web_url: string;\n created_at?: string;\n bio?: string;\n location?: string;\n public_email?: string;\n job_title?: string;\n pronouns?: string;\n organization?: string;\n bot?: boolean;\n work_information?: string;\n}\n\nexport class UsersClient extends GitLabApiClient {\n async getCurrentUser() {\n return this.fetch<User>('GET', '/user');\n }\n\n /**\n * Get a user by ID\n * @param userId - The user ID\n */\n async getUser(userId: number): Promise<User> {\n return this.fetch<User>('GET', `/users/${userId}`);\n }\n\n /**\n * Find users by username\n * @param username - The username to search for (exact match)\n */\n async getUserByUsername(username: string): Promise<User[]> {\n const params = new URLSearchParams();\n params.set('username', username);\n return this.fetch<User[]>('GET', `/users?${params}`);\n }\n\n /**\n * Get a user's status\n * @param userId - The user ID\n */\n async getUserStatus(userId: number): Promise<UserStatus> {\n return this.fetch<UserStatus>('GET', `/users/${userId}/status`);\n }\n}\n","import { GitLabApiClient } from './base.js';\n\nexport class WikisClient extends GitLabApiClient {\n async getWikiPage(projectId: string, slug: string) {\n const encodedProject = this.encodeProjectId(projectId);\n const encodedSlug = encodeURIComponent(slug);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/wikis/${encodedSlug}`\n );\n }\n}\n","/**\n * Validate GitLab Global ID (GID) format\n * @param gid - The GID to validate\n * @param expectedType - Expected resource type (e.g., 'Vulnerability', 'Issue')\n * @returns true if valid, false otherwise\n */\nexport function isValidGid(gid: string, expectedType?: string): boolean {\n // GID format: gid://gitlab/{ResourceType}/{id}\n const gidPattern = /^gid:\\/\\/gitlab\\/([A-Za-z]+)\\/(\\d+)$/;\n const match = gid.match(gidPattern);\n\n if (!match) {\n return false;\n }\n\n // If expectedType is provided, validate it matches\n if (expectedType && match[1] !== expectedType) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Validate and throw error if GID format is invalid\n * @param gid - The GID to validate\n * @param expectedType - Expected resource type (e.g., 'Vulnerability', 'Issue')\n * @throws Error if GID format is invalid\n */\nexport function validateGid(gid: string, expectedType?: string): void {\n if (!isValidGid(gid, expectedType)) {\n const typeMsg = expectedType ? ` of type '${expectedType}'` : '';\n throw new Error(\n `Invalid GitLab Global ID${typeMsg}: '${gid}'. Expected format: gid://gitlab/${expectedType || 'ResourceType'}/{id}`\n );\n }\n}\n","import { GitLabApiClient } from './base.js';\nimport { validateGid } from '../validation.js';\n\nexport type DismissalReason =\n | 'ACCEPTABLE_RISK'\n | 'FALSE_POSITIVE'\n | 'MITIGATING_CONTROL'\n | 'USED_IN_TESTS'\n | 'NOT_APPLICABLE';\n\nexport type VulnerabilitySeverity = 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW' | 'INFO' | 'UNKNOWN';\n\n// GraphQL mutation constants\nconst CREATE_VULNERABILITY_ISSUE_MUTATION = `\n mutation($projectPath: ID!, $vulnerabilityIds: [VulnerabilityID!]!) {\n createVulnerabilityIssueLink(input: {\n projectPath: $projectPath\n vulnerabilityIds: $vulnerabilityIds\n }) {\n issue {\n id\n iid\n title\n webUrl\n }\n errors\n }\n }\n`;\n\nconst DISMISS_VULNERABILITY_MUTATION = `\n mutation($id: VulnerabilityID!, $reason: VulnerabilityDismissalReason!, $comment: String) {\n vulnerabilityDismiss(input: {\n id: $id\n dismissalReason: $reason\n comment: $comment\n }) {\n vulnerability {\n id\n state\n dismissalReason\n }\n errors\n }\n }\n`;\n\nconst CONFIRM_VULNERABILITY_MUTATION = `\n mutation($id: VulnerabilityID!, $comment: String) {\n vulnerabilityConfirm(input: {\n id: $id\n comment: $comment\n }) {\n vulnerability {\n id\n state\n }\n errors\n }\n }\n`;\n\nconst REVERT_VULNERABILITY_MUTATION = `\n mutation($id: VulnerabilityID!, $comment: String) {\n vulnerabilityRevertToDetected(input: {\n id: $id\n comment: $comment\n }) {\n vulnerability {\n id\n state\n }\n errors\n }\n }\n`;\n\nconst UPDATE_VULNERABILITY_SEVERITY_MUTATION = `\n mutation($ids: [VulnerabilityID!]!, $severity: VulnerabilitySeverity!, $comment: String!) {\n vulnerabilitiesUpdateSeverity(input: {\n ids: $ids\n severity: $severity\n comment: $comment\n }) {\n vulnerabilities {\n id\n severity\n }\n errors\n }\n }\n`;\n\nconst LINK_VULNERABILITY_TO_ISSUE_MUTATION = `\n mutation($issueId: IssueID!, $vulnerabilityIds: [VulnerabilityID!]!) {\n vulnerabilityIssueLinksCreate(input: {\n issueId: $issueId\n vulnerabilityIds: $vulnerabilityIds\n }) {\n issue {\n id\n iid\n title\n webUrl\n }\n errors\n }\n }\n`;\n\nexport class SecurityClient extends GitLabApiClient {\n async listVulnerabilities(\n projectId: string,\n options?: {\n state?: string;\n severity?: string;\n report_type?: string;\n limit?: number;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const params = new URLSearchParams();\n params.set('per_page', String(options?.limit || 20));\n\n if (options?.state) params.set('state', options.state);\n if (options?.severity) params.set('severity', options.severity);\n if (options?.report_type) params.set('report_type', options.report_type);\n\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/vulnerabilities?${params}`\n );\n }\n\n async getVulnerabilityDetails(projectId: string, vulnerabilityId: number) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/vulnerabilities/${vulnerabilityId}`\n );\n }\n\n /**\n * Create an issue linked to one or more vulnerabilities\n * @param projectPath - Full path of the project (e.g., 'group/project')\n * @param vulnerabilityIds - Array of vulnerability IDs in format 'gid://gitlab/Vulnerability/{id}'\n * @returns The created issue\n */\n async createVulnerabilityIssue(projectPath: string, vulnerabilityIds: string[]) {\n // Validate all vulnerability IDs\n vulnerabilityIds.forEach((id) => validateGid(id, 'Vulnerability'));\n\n const result = await this.fetchGraphQL<{\n createVulnerabilityIssueLink: {\n issue: Record<string, unknown>;\n errors: string[];\n };\n }>(CREATE_VULNERABILITY_ISSUE_MUTATION, { projectPath, vulnerabilityIds });\n\n if (result.createVulnerabilityIssueLink.errors.length > 0) {\n throw new Error(\n `Failed to create vulnerability issue: ${result.createVulnerabilityIssueLink.errors.join(', ')}`\n );\n }\n\n return result.createVulnerabilityIssueLink.issue;\n }\n\n /**\n * Dismiss a vulnerability with a reason\n * @param vulnerabilityId - Vulnerability ID in format 'gid://gitlab/Vulnerability/{id}'\n * @param reason - Dismissal reason\n * @param comment - Optional comment explaining the dismissal\n * @returns The updated vulnerability\n */\n async dismissVulnerability(vulnerabilityId: string, reason: DismissalReason, comment?: string) {\n validateGid(vulnerabilityId, 'Vulnerability');\n\n const result = await this.fetchGraphQL<{\n vulnerabilityDismiss: {\n vulnerability: Record<string, unknown>;\n errors: string[];\n };\n }>(DISMISS_VULNERABILITY_MUTATION, { id: vulnerabilityId, reason, comment });\n\n if (result.vulnerabilityDismiss.errors.length > 0) {\n throw new Error(\n `Failed to dismiss vulnerability: ${result.vulnerabilityDismiss.errors.join(', ')}`\n );\n }\n\n return result.vulnerabilityDismiss.vulnerability;\n }\n\n /**\n * Confirm a vulnerability\n * @param vulnerabilityId - Vulnerability ID in format 'gid://gitlab/Vulnerability/{id}'\n * @param comment - Optional comment\n * @returns The updated vulnerability\n */\n async confirmVulnerability(vulnerabilityId: string, comment?: string) {\n validateGid(vulnerabilityId, 'Vulnerability');\n\n const result = await this.fetchGraphQL<{\n vulnerabilityConfirm: {\n vulnerability: Record<string, unknown>;\n errors: string[];\n };\n }>(CONFIRM_VULNERABILITY_MUTATION, { id: vulnerabilityId, comment });\n\n if (result.vulnerabilityConfirm.errors.length > 0) {\n throw new Error(\n `Failed to confirm vulnerability: ${result.vulnerabilityConfirm.errors.join(', ')}`\n );\n }\n\n return result.vulnerabilityConfirm.vulnerability;\n }\n\n /**\n * Revert a vulnerability back to detected state\n * @param vulnerabilityId - Vulnerability ID in format 'gid://gitlab/Vulnerability/{id}'\n * @param comment - Optional comment\n * @returns The updated vulnerability\n */\n async revertVulnerability(vulnerabilityId: string, comment?: string) {\n validateGid(vulnerabilityId, 'Vulnerability');\n\n const result = await this.fetchGraphQL<{\n vulnerabilityRevertToDetected: {\n vulnerability: Record<string, unknown>;\n errors: string[];\n };\n }>(REVERT_VULNERABILITY_MUTATION, { id: vulnerabilityId, comment });\n\n if (result.vulnerabilityRevertToDetected.errors.length > 0) {\n throw new Error(\n `Failed to revert vulnerability: ${result.vulnerabilityRevertToDetected.errors.join(', ')}`\n );\n }\n\n return result.vulnerabilityRevertToDetected.vulnerability;\n }\n\n /**\n * Update the severity of one or more vulnerabilities\n * @param vulnerabilityIds - Array of vulnerability IDs in format 'gid://gitlab/Vulnerability/{id}'\n * @param severity - New severity level\n * @param comment - Comment explaining the severity change\n * @returns Array of updated vulnerabilities\n */\n async updateVulnerabilitySeverity(\n vulnerabilityIds: string[],\n severity: VulnerabilitySeverity,\n comment: string\n ) {\n // Validate all vulnerability IDs\n vulnerabilityIds.forEach((id) => validateGid(id, 'Vulnerability'));\n\n const result = await this.fetchGraphQL<{\n vulnerabilitiesUpdateSeverity: {\n vulnerabilities: Record<string, unknown>[];\n errors: string[];\n };\n }>(UPDATE_VULNERABILITY_SEVERITY_MUTATION, { ids: vulnerabilityIds, severity, comment });\n\n if (result.vulnerabilitiesUpdateSeverity.errors.length > 0) {\n throw new Error(\n `Failed to update vulnerability severity: ${result.vulnerabilitiesUpdateSeverity.errors.join(', ')}`\n );\n }\n\n return result.vulnerabilitiesUpdateSeverity.vulnerabilities;\n }\n\n /**\n * Link an existing issue to one or more vulnerabilities\n * @param issueId - Issue ID in format 'gid://gitlab/Issue/{id}'\n * @param vulnerabilityIds - Array of vulnerability IDs in format 'gid://gitlab/Vulnerability/{id}'\n * @returns The linked issue\n */\n async linkVulnerabilityToIssue(issueId: string, vulnerabilityIds: string[]) {\n validateGid(issueId, 'Issue');\n vulnerabilityIds.forEach((id) => validateGid(id, 'Vulnerability'));\n\n const result = await this.fetchGraphQL<{\n vulnerabilityIssueLinksCreate: {\n issue: Record<string, unknown>;\n errors: string[];\n };\n }>(LINK_VULNERABILITY_TO_ISSUE_MUTATION, { issueId, vulnerabilityIds });\n\n if (result.vulnerabilityIssueLinksCreate.errors.length > 0) {\n throw new Error(\n `Failed to link vulnerability to issue: ${result.vulnerabilityIssueLinksCreate.errors.join(', ')}`\n );\n }\n\n return result.vulnerabilityIssueLinksCreate.issue;\n }\n}\n","import { GitLabApiClient } from './base.js';\n\nexport interface TodosPageInfo {\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n startCursor: string | null;\n endCursor: string | null;\n}\n\nexport interface TodoNode {\n id: string;\n body: string;\n state: string;\n action: string;\n createdAt: string;\n targetType: string;\n targetUrl: string | null;\n snoozedUntil: string | null;\n project: {\n id: string;\n name: string;\n fullPath: string;\n } | null;\n group: {\n id: string;\n name: string;\n fullPath: string;\n } | null;\n author: {\n id: string;\n username: string;\n name: string;\n avatarUrl: string | null;\n };\n}\n\nexport interface TodosConnection {\n nodes: TodoNode[];\n pageInfo: TodosPageInfo;\n count: number;\n}\n\nexport interface TodosResult {\n todos: TodosConnection;\n}\n\nconst LIST_TODOS_QUERY = `\n query listTodos(\n $state: [TodoStateEnum!]\n $action: [TodoActionEnum!]\n $type: [TodoTargetEnum!]\n $projectId: [ID!]\n $groupId: [ID!]\n $authorId: [ID!]\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n currentUser {\n todos(\n state: $state\n action: $action\n type: $type\n projectId: $projectId\n groupId: $groupId\n authorId: $authorId\n first: $first\n after: $after\n last: $last\n before: $before\n ) {\n count\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n nodes {\n id\n body\n state\n action\n createdAt\n targetType\n targetUrl\n snoozedUntil\n project {\n id\n name\n fullPath\n }\n group {\n id\n name\n fullPath\n }\n author {\n id\n username\n name\n avatarUrl\n }\n }\n }\n }\n }\n`;\n\nexport class TodosClient extends GitLabApiClient {\n async listTodos(options?: {\n action?: string;\n author_id?: number;\n project_id?: string;\n group_id?: string;\n state?: string;\n type?: string;\n first?: number;\n after?: string;\n last?: number;\n before?: string;\n }): Promise<TodosResult> {\n if (options?.first !== undefined && options?.last !== undefined) {\n throw new Error(\n 'Cannot specify both \"first\" and \"last\" pagination parameters. Use \"first\"/\"after\" for forward pagination or \"last\"/\"before\" for backward pagination.'\n );\n }\n\n const variables: Record<string, unknown> = {};\n\n if (options?.first !== undefined) {\n variables.first = options.first;\n } else if (options?.last === undefined) {\n variables.first = 20;\n }\n\n if (options?.after) variables.after = options.after;\n if (options?.last !== undefined) variables.last = options.last;\n if (options?.before) variables.before = options.before;\n\n if (options?.action) {\n variables.action = [this.mapTodoAction(options.action)];\n }\n if (options?.author_id) {\n variables.authorId = [`gid://gitlab/User/${options.author_id}`];\n }\n if (options?.project_id) {\n variables.projectId = [options.project_id];\n }\n if (options?.group_id) {\n variables.groupId = [options.group_id];\n }\n if (options?.state) {\n variables.state = [options.state.toLowerCase()];\n }\n if (options?.type) {\n variables.type = [this.mapTodoTargetType(options.type)];\n }\n\n const result = await this.fetchGraphQL<{\n currentUser: {\n todos: TodosConnection;\n };\n }>(LIST_TODOS_QUERY, variables);\n\n const todos = result.currentUser.todos;\n\n return {\n todos,\n };\n }\n\n private mapTodoAction(action: string): string {\n const actionMap: Record<string, string> = {\n assigned: 'ASSIGNED',\n mentioned: 'MENTIONED',\n build_failed: 'BUILD_FAILED',\n marked: 'MARKED',\n approval_required: 'APPROVAL_REQUIRED',\n unmergeable: 'UNMERGEABLE',\n directly_addressed: 'DIRECTLY_ADDRESSED',\n merge_train_removed: 'MERGE_TRAIN_REMOVED',\n review_requested: 'REVIEW_REQUESTED',\n };\n return actionMap[action] || action.toUpperCase();\n }\n\n private mapTodoTargetType(type: string): string {\n const typeMap: Record<string, string> = {\n Issue: 'ISSUE',\n MergeRequest: 'MERGEREQUEST',\n 'DesignManagement::Design': 'DESIGN',\n Alert: 'ALERT',\n Commit: 'COMMIT',\n Epic: 'EPIC',\n };\n return typeMap[type] || type;\n }\n\n async markTodoAsDone(\n todoId: number\n ): Promise<{ success: boolean; todo?: Record<string, unknown>; message?: string }> {\n try {\n const result = await this.fetch<Record<string, unknown>>(\n 'POST',\n `/todos/${todoId}/mark_as_done`\n );\n return { success: true, todo: result };\n } catch (error) {\n if (error instanceof Error && error.message.includes('404')) {\n return {\n success: false,\n message: `Todo ${todoId} not found. It may have already been marked as done or does not exist.`,\n };\n }\n throw error;\n }\n }\n\n async markAllTodosAsDone() {\n return this.fetch<Record<string, unknown>>('POST', '/todos/mark_as_done');\n }\n\n async getTodoCount() {\n const result = await this.fetchGraphQL<{\n currentUser: {\n todos: {\n count: number;\n };\n };\n }>(`query { currentUser { todos(state: [pending]) { count } } }`);\n\n return { count: result.currentUser.todos.count };\n }\n}\n","import { GitLabApiClient } from './base.js';\nimport {\n NotesResult,\n NotesConnection,\n NotesPaginationOptions,\n NOTES_FRAGMENT,\n NOTES_CONNECTION_FRAGMENT,\n buildPaginationVariables,\n} from './notes-types.js';\nimport {\n DiscussionsResult,\n DiscussionsConnection,\n DiscussionsPaginationOptions,\n DISCUSSION_NOTE_FRAGMENT,\n DISCUSSION_FRAGMENT,\n DISCUSSIONS_CONNECTION_FRAGMENT,\n buildDiscussionsPaginationVariables,\n} from './discussions-types.js';\n\nconst LIST_EPIC_NOTES_QUERY = `\n ${NOTES_FRAGMENT}\n ${NOTES_CONNECTION_FRAGMENT}\n query listEpicNotes(\n $groupPath: ID!\n $epicIid: String!\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n group(fullPath: $groupPath) {\n epic(iid: $epicIid) {\n notes(\n first: $first\n after: $after\n last: $last\n before: $before\n ) {\n ...NotesConnectionFields\n }\n }\n }\n }\n`;\n\nconst LIST_EPIC_DISCUSSIONS_QUERY = `\n ${DISCUSSION_NOTE_FRAGMENT}\n ${DISCUSSION_FRAGMENT}\n ${DISCUSSIONS_CONNECTION_FRAGMENT}\n query listEpicDiscussions(\n $groupPath: ID!\n $epicIid: String!\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n group(fullPath: $groupPath) {\n epic(iid: $epicIid) {\n discussions(\n first: $first\n after: $after\n last: $last\n before: $before\n ) {\n ...DiscussionsConnectionFields\n }\n }\n }\n }\n`;\n\nexport class EpicsClient extends GitLabApiClient {\n async getEpic(groupId: string, epicIid: number) {\n const encodedGroup = encodeURIComponent(groupId);\n return this.fetch<Record<string, unknown>>('GET', `/groups/${encodedGroup}/epics/${epicIid}`);\n }\n\n async listEpics(options: {\n groupId: string;\n state?: string;\n author_id?: number;\n labels?: string;\n search?: string;\n limit?: number;\n }) {\n const encodedGroup = encodeURIComponent(options.groupId);\n const params = new URLSearchParams();\n params.set('per_page', String(options.limit || 20));\n\n if (options.state) params.set('state', options.state);\n if (options.author_id) params.set('author_id', String(options.author_id));\n if (options.labels) params.set('labels', options.labels);\n if (options.search) params.set('search', options.search);\n\n return this.fetch<Record<string, unknown>[]>('GET', `/groups/${encodedGroup}/epics?${params}`);\n }\n\n async createEpic(\n groupId: string,\n options: {\n title: string;\n description?: string;\n labels?: string;\n start_date?: string;\n end_date?: string;\n confidential?: boolean;\n }\n ) {\n const encodedGroup = encodeURIComponent(groupId);\n return this.fetch<Record<string, unknown>>('POST', `/groups/${encodedGroup}/epics`, options);\n }\n\n async updateEpic(\n groupId: string,\n epicIid: number,\n options: {\n title?: string;\n description?: string;\n labels?: string;\n start_date?: string;\n end_date?: string;\n state_event?: string;\n confidential?: boolean;\n }\n ) {\n const encodedGroup = encodeURIComponent(groupId);\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/groups/${encodedGroup}/epics/${epicIid}`,\n options\n );\n }\n\n async listEpicIssues(groupId: string, epicIid: number) {\n const encodedGroup = encodeURIComponent(groupId);\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/groups/${encodedGroup}/epics/${epicIid}/issues`\n );\n }\n\n async addIssueToEpic(groupId: string, epicIid: number, issueId: number) {\n const encodedGroup = encodeURIComponent(groupId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/groups/${encodedGroup}/epics/${epicIid}/issues/${issueId}`\n );\n }\n\n async removeIssueFromEpic(groupId: string, epicIid: number, epicIssueId: number) {\n const encodedGroup = encodeURIComponent(groupId);\n return this.fetch<Record<string, unknown>>(\n 'DELETE',\n `/groups/${encodedGroup}/epics/${epicIid}/issues/${epicIssueId}`\n );\n }\n\n /**\n * List notes on an epic using GraphQL API with pagination support\n */\n async listEpicNotes(\n groupId: string,\n epicIid: number,\n options?: NotesPaginationOptions\n ): Promise<NotesResult> {\n const variables: Record<string, unknown> = {\n groupPath: groupId,\n epicIid: String(epicIid),\n ...buildPaginationVariables(options),\n };\n\n const result = await this.fetchGraphQL<{\n group: {\n epic: {\n notes: NotesConnection;\n };\n };\n }>(LIST_EPIC_NOTES_QUERY, variables);\n\n const notes = result.group?.epic?.notes;\n if (!notes) {\n throw new Error('Epic not found or access denied');\n }\n\n return {\n notes,\n pageInfo: notes.pageInfo,\n totalCount: notes.count,\n };\n }\n\n /**\n * List discussions on an epic using GraphQL API with pagination support\n */\n async listEpicDiscussions(\n groupId: string,\n epicIid: number,\n options?: DiscussionsPaginationOptions\n ): Promise<DiscussionsResult> {\n const variables: Record<string, unknown> = {\n groupPath: groupId,\n epicIid: String(epicIid),\n ...buildDiscussionsPaginationVariables(options),\n };\n\n const result = await this.fetchGraphQL<{\n group: {\n epic: {\n discussions: DiscussionsConnection;\n };\n };\n }>(LIST_EPIC_DISCUSSIONS_QUERY, variables);\n\n const discussions = result.group?.epic?.discussions;\n if (!discussions) {\n throw new Error('Epic not found or access denied');\n }\n\n return { discussions };\n }\n\n async getEpicDiscussion(groupId: string, epicIid: number, discussionId: string) {\n const encodedGroup = encodeURIComponent(groupId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/groups/${encodedGroup}/epics/${epicIid}/discussions/${discussionId}`\n );\n }\n\n async createEpicNote(groupId: string, epicIid: number, body: string, discussionId?: string) {\n const encodedGroup = encodeURIComponent(groupId);\n if (discussionId) {\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/groups/${encodedGroup}/epics/${epicIid}/discussions/${discussionId}/notes`,\n { body }\n );\n }\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/groups/${encodedGroup}/epics/${epicIid}/notes`,\n { body }\n );\n }\n\n async getEpicNote(groupId: string, epicIid: number, noteId: number) {\n const encodedGroup = encodeURIComponent(groupId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/groups/${encodedGroup}/epics/${epicIid}/notes/${noteId}`\n );\n }\n\n async updateEpicNote(groupId: string, epicIid: number, noteId: number, body: string) {\n const encodedGroup = encodeURIComponent(groupId);\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/groups/${encodedGroup}/epics/${epicIid}/notes/${noteId}`,\n { body }\n );\n }\n}\n","import { GitLabApiClient } from './base.js';\nimport {\n NotesResult,\n NotesConnection,\n NotesPaginationOptions,\n NOTES_FRAGMENT,\n NOTES_CONNECTION_FRAGMENT,\n buildPaginationVariables,\n} from './notes-types.js';\nimport {\n DiscussionsResult,\n DiscussionsConnection,\n DiscussionsPaginationOptions,\n DISCUSSION_NOTE_FRAGMENT,\n DISCUSSION_FRAGMENT,\n DISCUSSIONS_CONNECTION_FRAGMENT,\n buildDiscussionsPaginationVariables,\n} from './discussions-types.js';\n\nconst LIST_SNIPPET_NOTES_QUERY = `\n ${NOTES_FRAGMENT}\n ${NOTES_CONNECTION_FRAGMENT}\n query listSnippetNotes(\n $snippetGid: SnippetID!\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n snippets(ids: [$snippetGid]) {\n nodes {\n notes(\n first: $first\n after: $after\n last: $last\n before: $before\n ) {\n ...NotesConnectionFields\n }\n }\n }\n }\n`;\n\nconst LIST_SNIPPET_DISCUSSIONS_QUERY = `\n ${DISCUSSION_NOTE_FRAGMENT}\n ${DISCUSSION_FRAGMENT}\n ${DISCUSSIONS_CONNECTION_FRAGMENT}\n query listSnippetDiscussions(\n $snippetGid: SnippetID!\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n snippets(ids: [$snippetGid]) {\n nodes {\n discussions(\n first: $first\n after: $after\n last: $last\n before: $before\n ) {\n ...DiscussionsConnectionFields\n }\n }\n }\n }\n`;\n\n/**\n * GitLab API client for Snippet operations\n */\nexport class SnippetsClient extends GitLabApiClient {\n /**\n * List notes on a snippet using GraphQL API with pagination support\n */\n async listSnippetNotes(\n projectId: string,\n snippetId: number,\n options?: NotesPaginationOptions\n ): Promise<NotesResult> {\n const variables: Record<string, unknown> = {\n snippetGid: `gid://gitlab/ProjectSnippet/${snippetId}`,\n ...buildPaginationVariables(options),\n };\n\n const result = await this.fetchGraphQL<{\n snippets: {\n nodes: Array<{\n notes: NotesConnection;\n }>;\n };\n }>(LIST_SNIPPET_NOTES_QUERY, variables);\n\n const notes = result.snippets.nodes[0]?.notes || {\n nodes: [],\n pageInfo: {\n hasNextPage: false,\n hasPreviousPage: false,\n startCursor: null,\n endCursor: null,\n },\n count: 0,\n };\n\n return {\n notes,\n pageInfo: notes.pageInfo,\n totalCount: notes.count,\n };\n }\n\n /**\n * List discussions on a snippet using GraphQL API with pagination support\n */\n async listSnippetDiscussions(\n projectId: string,\n snippetId: number,\n options?: DiscussionsPaginationOptions\n ): Promise<DiscussionsResult> {\n const variables: Record<string, unknown> = {\n snippetGid: `gid://gitlab/ProjectSnippet/${snippetId}`,\n ...buildDiscussionsPaginationVariables(options),\n };\n\n const result = await this.fetchGraphQL<{\n snippets: {\n nodes: Array<{\n discussions: DiscussionsConnection;\n }>;\n };\n }>(LIST_SNIPPET_DISCUSSIONS_QUERY, variables);\n\n const discussions = result.snippets.nodes[0]?.discussions || {\n nodes: [],\n pageInfo: {\n hasNextPage: false,\n hasPreviousPage: false,\n startCursor: null,\n endCursor: null,\n },\n };\n\n return { discussions };\n }\n\n async getSnippetDiscussion(projectId: string, snippetId: number, discussionId: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/snippets/${snippetId}/discussions/${discussionId}`\n );\n }\n\n async createSnippetNote(\n projectId: string,\n snippetId: number,\n body: string,\n discussionId?: string\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n if (discussionId) {\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/snippets/${snippetId}/discussions/${discussionId}/notes`,\n { body }\n );\n }\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/snippets/${snippetId}/notes`,\n { body }\n );\n }\n\n async createSnippetDiscussion(projectId: string, snippetId: number, body: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/snippets/${snippetId}/discussions`,\n { body }\n );\n }\n\n async updateSnippetNote(projectId: string, snippetId: number, noteId: number, body: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/projects/${encodedProject}/snippets/${snippetId}/notes/${noteId}`,\n { body }\n );\n }\n}\n","import { GitLabApiClient } from './base.js';\n\n/**\n * Resource identifier for discussion operations\n */\nexport interface DiscussionResourceId {\n projectId?: string;\n groupId?: string;\n iid?: number;\n sha?: string;\n snippetId?: number;\n}\n\n/**\n * GitLab API client for universal Discussion operations\n * Provides a consistent interface for discussions across all resource types\n */\nexport class DiscussionsClient extends GitLabApiClient {\n /**\n * Universal method to reply to any discussion thread\n * Supports: merge requests, issues, epics, commits, snippets\n */\n async replyToDiscussion(\n resourceType: 'merge_request' | 'issue' | 'epic' | 'commit' | 'snippet',\n resourceId: DiscussionResourceId,\n discussionId: string,\n body: string\n ): Promise<Record<string, unknown>> {\n switch (resourceType) {\n case 'merge_request': {\n if (!resourceId.projectId || !resourceId.iid) {\n throw new Error('projectId and iid are required for merge_request discussions');\n }\n const encodedProject = this.encodeProjectId(resourceId.projectId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/merge_requests/${resourceId.iid}/discussions/${discussionId}/notes`,\n { body }\n );\n }\n case 'issue': {\n if (!resourceId.projectId || !resourceId.iid) {\n throw new Error('projectId and iid are required for issue discussions');\n }\n const encodedProject = this.encodeProjectId(resourceId.projectId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/issues/${resourceId.iid}/discussions/${discussionId}/notes`,\n { body }\n );\n }\n case 'epic': {\n if (!resourceId.groupId || !resourceId.iid) {\n throw new Error('groupId and iid are required for epic discussions');\n }\n const encodedGroup = encodeURIComponent(resourceId.groupId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/groups/${encodedGroup}/epics/${resourceId.iid}/discussions/${discussionId}/notes`,\n { body }\n );\n }\n case 'commit': {\n if (!resourceId.projectId || !resourceId.sha) {\n throw new Error('projectId and sha are required for commit discussions');\n }\n const encodedProject = this.encodeProjectId(resourceId.projectId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/repository/commits/${resourceId.sha}/discussions/${discussionId}/notes`,\n { body }\n );\n }\n case 'snippet': {\n if (!resourceId.projectId || !resourceId.snippetId) {\n throw new Error('projectId and snippetId are required for snippet discussions');\n }\n const encodedProject = this.encodeProjectId(resourceId.projectId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/snippets/${resourceId.snippetId}/discussions/${discussionId}/notes`,\n { body }\n );\n }\n default:\n throw new Error(`Unsupported resource type: ${resourceType}`);\n }\n }\n\n /**\n * Universal method to get a specific discussion from any resource type\n * Supports: merge requests, issues, epics, commits, snippets\n */\n async getDiscussion(\n resourceType: 'merge_request' | 'issue' | 'epic' | 'commit' | 'snippet',\n resourceId: DiscussionResourceId,\n discussionId: string\n ): Promise<Record<string, unknown>> {\n switch (resourceType) {\n case 'merge_request': {\n if (!resourceId.projectId || !resourceId.iid) {\n throw new Error('projectId and iid are required for merge_request discussions');\n }\n const encodedProject = this.encodeProjectId(resourceId.projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/merge_requests/${resourceId.iid}/discussions/${discussionId}`\n );\n }\n case 'issue': {\n if (!resourceId.projectId || !resourceId.iid) {\n throw new Error('projectId and iid are required for issue discussions');\n }\n const encodedProject = this.encodeProjectId(resourceId.projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/issues/${resourceId.iid}/discussions/${discussionId}`\n );\n }\n case 'epic': {\n if (!resourceId.groupId || !resourceId.iid) {\n throw new Error('groupId and iid are required for epic discussions');\n }\n const encodedGroup = encodeURIComponent(resourceId.groupId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/groups/${encodedGroup}/epics/${resourceId.iid}/discussions/${discussionId}`\n );\n }\n case 'commit': {\n if (!resourceId.projectId || !resourceId.sha) {\n throw new Error('projectId and sha are required for commit discussions');\n }\n const encodedProject = this.encodeProjectId(resourceId.projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/repository/commits/${resourceId.sha}/discussions/${discussionId}`\n );\n }\n case 'snippet': {\n if (!resourceId.projectId || !resourceId.snippetId) {\n throw new Error('projectId and snippetId are required for snippet discussions');\n }\n const encodedProject = this.encodeProjectId(resourceId.projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/snippets/${resourceId.snippetId}/discussions/${discussionId}`\n );\n }\n default:\n throw new Error(`Unsupported resource type: ${resourceType}`);\n }\n }\n}\n","import { GitLabApiClient } from './base.js';\n\nexport interface AuditEvent {\n id: number;\n author_id: number;\n entity_id: number;\n entity_type: string;\n details: Record<string, unknown>;\n created_at: string;\n author_name?: string;\n ip_address?: string;\n target_details?: string;\n target_type?: string;\n target_id?: number;\n}\n\nexport interface AuditEventOptions {\n created_after?: string; // ISO 8601 format\n created_before?: string; // ISO 8601 format\n entity_type?: string;\n entity_id?: number;\n author_id?: number;\n per_page?: number;\n page?: number;\n}\n\n/**\n * Client for GitLab Audit Events API\n * Note: Requires appropriate permissions (project/group owner or instance admin)\n */\nexport class AuditClient extends GitLabApiClient {\n /**\n * List audit events for a project\n * Requires: Project owner role\n * API: GET /projects/:id/audit_events\n */\n async listProjectAuditEvents(\n projectId: string,\n options: AuditEventOptions = {}\n ): Promise<AuditEvent[]> {\n const encodedId = this.encodeProjectId(projectId);\n const params = new URLSearchParams();\n\n if (options.created_after) params.append('created_after', options.created_after);\n if (options.created_before) params.append('created_before', options.created_before);\n if (options.entity_type) params.append('entity_type', options.entity_type);\n if (options.entity_id) params.append('entity_id', options.entity_id.toString());\n if (options.author_id) params.append('author_id', options.author_id.toString());\n if (options.per_page) params.append('per_page', options.per_page.toString());\n if (options.page) params.append('page', options.page.toString());\n\n const query = params.toString();\n const path = `/projects/${encodedId}/audit_events${query ? `?${query}` : ''}`;\n\n return this.fetch<AuditEvent[]>('GET', path);\n }\n\n /**\n * List audit events for a group\n * Requires: Group owner role\n * API: GET /groups/:id/audit_events\n */\n async listGroupAuditEvents(\n groupId: string,\n options: AuditEventOptions = {}\n ): Promise<AuditEvent[]> {\n const encodedId = encodeURIComponent(groupId);\n const params = new URLSearchParams();\n\n if (options.created_after) params.append('created_after', options.created_after);\n if (options.created_before) params.append('created_before', options.created_before);\n if (options.entity_type) params.append('entity_type', options.entity_type);\n if (options.entity_id) params.append('entity_id', options.entity_id.toString());\n if (options.author_id) params.append('author_id', options.author_id.toString());\n if (options.per_page) params.append('per_page', options.per_page.toString());\n if (options.page) params.append('page', options.page.toString());\n\n const query = params.toString();\n const path = `/groups/${encodedId}/audit_events${query ? `?${query}` : ''}`;\n\n return this.fetch<AuditEvent[]>('GET', path);\n }\n\n /**\n * List instance-level audit events\n * Requires: Administrator access\n * API: GET /audit_events\n */\n async listInstanceAuditEvents(options: AuditEventOptions = {}): Promise<AuditEvent[]> {\n const params = new URLSearchParams();\n\n if (options.created_after) params.append('created_after', options.created_after);\n if (options.created_before) params.append('created_before', options.created_before);\n if (options.entity_type) params.append('entity_type', options.entity_type);\n if (options.entity_id) params.append('entity_id', options.entity_id.toString());\n if (options.author_id) params.append('author_id', options.author_id.toString());\n if (options.per_page) params.append('per_page', options.per_page.toString());\n if (options.page) params.append('page', options.page.toString());\n\n const query = params.toString();\n const path = `/audit_events${query ? `?${query}` : ''}`;\n\n return this.fetch<AuditEvent[]>('GET', path);\n }\n}\n","import { GitLabApiClient } from './base.js';\n\n/**\n * Award emoji response from GitLab API\n */\nexport interface AwardEmoji {\n id: number;\n name: string;\n user: {\n id: number;\n username: string;\n name: string;\n state: string;\n avatar_url: string;\n web_url: string;\n };\n created_at: string;\n updated_at: string;\n awardable_id: number;\n awardable_type: string;\n}\n\n/**\n * Supported resource types for award emoji\n */\nexport type AwardableResourceType = 'merge_request' | 'issue' | 'snippet';\n\n/**\n * Resource identifier for award emoji operations\n */\nexport interface AwardEmojiResourceId {\n projectId: string;\n resourceType: AwardableResourceType;\n resourceIid: number;\n noteId?: number;\n}\n\n/**\n * GitLab API client for Award Emoji (reactions) operations\n * Supports adding/removing emoji reactions on MRs, issues, snippets and their notes\n *\n * API docs: https://docs.gitlab.com/ee/api/award_emoji.html\n */\nexport class AwardEmojiClient extends GitLabApiClient {\n /**\n * Build the base path for award emoji operations\n */\n private buildAwardEmojiPath(resource: AwardEmojiResourceId): string {\n const encodedProject = this.encodeProjectId(resource.projectId);\n\n let basePath: string;\n switch (resource.resourceType) {\n case 'merge_request':\n basePath = `/projects/${encodedProject}/merge_requests/${resource.resourceIid}`;\n break;\n case 'issue':\n basePath = `/projects/${encodedProject}/issues/${resource.resourceIid}`;\n break;\n case 'snippet':\n basePath = `/projects/${encodedProject}/snippets/${resource.resourceIid}`;\n break;\n }\n\n if (resource.noteId) {\n return `${basePath}/notes/${resource.noteId}/award_emoji`;\n }\n return `${basePath}/award_emoji`;\n }\n\n /**\n * List all award emoji on a resource or note\n */\n async listAwardEmoji(resource: AwardEmojiResourceId): Promise<AwardEmoji[]> {\n const path = this.buildAwardEmojiPath(resource);\n return this.fetch<AwardEmoji[]>('GET', path);\n }\n\n /**\n * Get a single award emoji by ID\n */\n async getAwardEmoji(resource: AwardEmojiResourceId, awardId: number): Promise<AwardEmoji> {\n const path = `${this.buildAwardEmojiPath(resource)}/${awardId}`;\n return this.fetch<AwardEmoji>('GET', path);\n }\n\n /**\n * Add an award emoji (reaction) to a resource or note\n *\n * @param resource - The resource to add the emoji to\n * @param name - The emoji name without colons (e.g., 'thumbsup', 'rocket', 'eyes')\n */\n async createAwardEmoji(resource: AwardEmojiResourceId, name: string): Promise<AwardEmoji> {\n const path = this.buildAwardEmojiPath(resource);\n return this.fetch<AwardEmoji>('POST', path, { name });\n }\n\n /**\n * Remove an award emoji from a resource or note\n */\n async deleteAwardEmoji(resource: AwardEmojiResourceId, awardId: number): Promise<void> {\n const path = `${this.buildAwardEmojiPath(resource)}/${awardId}`;\n await this.fetch<void>('DELETE', path);\n }\n}\n","import { GitLabApiClient as BaseClient } from './base.js';\nimport { MergeRequestsClient } from './merge-requests.js';\nimport { IssuesClient } from './issues.js';\nimport { WorkItemsClient } from './work-items.js';\nimport { PipelinesClient } from './pipelines.js';\nimport { RepositoryClient } from './repository.js';\nimport { SearchClient } from './search.js';\nimport { ProjectsClient } from './projects.js';\nimport { UsersClient } from './users.js';\nimport { WikisClient } from './wikis.js';\nimport { SecurityClient } from './security.js';\nimport { TodosClient } from './todos.js';\nimport { EpicsClient } from './epics.js';\nimport { SnippetsClient } from './snippets.js';\nimport { DiscussionsClient } from './discussions.js';\nimport { AuditClient } from './audit.js';\nimport { AwardEmojiClient } from './award-emoji.js';\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging\nclass UnifiedGitLabClient extends BaseClient {}\n// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging\ninterface UnifiedGitLabClient\n extends\n MergeRequestsClient,\n IssuesClient,\n WorkItemsClient,\n PipelinesClient,\n RepositoryClient,\n SearchClient,\n ProjectsClient,\n UsersClient,\n WikisClient,\n SecurityClient,\n TodosClient,\n EpicsClient,\n SnippetsClient,\n DiscussionsClient,\n AuditClient,\n AwardEmojiClient {}\n\ntype Constructor = new (...args: never[]) => object;\n\nfunction applyMixins(derivedCtor: Constructor, constructors: Constructor[]) {\n constructors.forEach((baseCtor) => {\n Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => {\n Object.defineProperty(\n derivedCtor.prototype,\n name,\n Object.getOwnPropertyDescriptor(baseCtor.prototype, name) || Object.create(null)\n );\n });\n });\n}\n\napplyMixins(UnifiedGitLabClient, [\n MergeRequestsClient,\n IssuesClient,\n WorkItemsClient,\n PipelinesClient,\n RepositoryClient,\n SearchClient,\n ProjectsClient,\n UsersClient,\n WikisClient,\n SecurityClient,\n TodosClient,\n EpicsClient,\n SnippetsClient,\n DiscussionsClient,\n AuditClient,\n AwardEmojiClient,\n]);\n\nexport { UnifiedGitLabClient as GitLabApiClient };\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const issueTools = {\n gitlab_create_issue: tool({\n description: `Create a new issue in a GitLab project.\nReturns the created issue with all details including IID, web URL, and metadata.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n title: z.string().describe('The title of the issue'),\n description: z\n .string()\n .optional()\n .describe('The description of the issue (supports Markdown)'),\n assignee_ids: z\n .array(z.number())\n .optional()\n .describe('Array of user IDs to assign the issue to'),\n milestone_id: z\n .number()\n .optional()\n .describe('The ID of the milestone to assign the issue to'),\n labels: z\n .string()\n .optional()\n .describe('Comma-separated list of label names (e.g., \"bug,critical\")'),\n due_date: z\n .string()\n .optional()\n .describe('Due date for the issue in YYYY-MM-DD format (e.g., \"2025-12-31\")'),\n confidential: z.boolean().optional().describe('Whether the issue should be confidential'),\n weight: z.number().optional().describe('The weight of the issue (for issue boards)'),\n epic_id: z\n .number()\n .optional()\n .describe('The ID of the epic to add the issue to (Premium/Ultimate)'),\n issue_type: z\n .enum(['issue', 'incident', 'test_case', 'task'])\n .optional()\n .describe('The type of issue (default: issue)'),\n },\n execute: async (\n args: {\n project_id: string;\n title: string;\n description?: string;\n assignee_ids?: number[];\n milestone_id?: number;\n labels?: string;\n due_date?: string;\n confidential?: boolean;\n weight?: number;\n epic_id?: number;\n issue_type?: 'issue' | 'incident' | 'test_case' | 'task';\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const issue = await client.createIssue(args.project_id, args.title, {\n description: args.description,\n assignee_ids: args.assignee_ids,\n milestone_id: args.milestone_id,\n labels: args.labels,\n due_date: args.due_date,\n confidential: args.confidential,\n weight: args.weight,\n epic_id: args.epic_id,\n issue_type: args.issue_type,\n });\n return JSON.stringify(issue, null, 2);\n },\n }),\n\n gitlab_get_issue: tool({\n description: `Get details of a specific issue by project and issue IID.\nReturns: title, description, state, author, assignees, labels, milestone, weight, and comments.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n issue_iid: z.number().describe('The internal ID of the issue within the project'),\n },\n execute: async (args: { project_id: string; issue_iid: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const issue = await client.getIssue(args.project_id, args.issue_iid);\n return JSON.stringify(issue, null, 2);\n },\n }),\n\n gitlab_list_issues: tool({\n description: `List issues for a project or search globally.\nCan filter by state, labels, assignee, milestone.\n\nIMPORTANT: Response includes pagination info. If nextPage exists, there are more results.\nAlways paginate until you get an empty response or no nextPage to ensure you have all data.`,\n args: {\n project_id: z\n .string()\n .optional()\n .describe('The project ID or path. If not provided, searches globally.'),\n state: z\n .enum(['opened', 'closed', 'all'])\n .optional()\n .describe('Filter by issue state (default: opened)'),\n scope: z\n .enum(['assigned_to_me', 'created_by_me', 'all'])\n .optional()\n .describe('Filter by scope'),\n search: z.string().optional().describe('Search issues by title or description'),\n labels: z.string().optional().describe('Comma-separated list of labels to filter by'),\n milestone: z.string().optional().describe('Filter by milestone title'),\n limit: z.number().optional().describe('Maximum number of results per page (default: 20)'),\n page: z.number().optional().describe('Page number for pagination (default: 1)'),\n },\n execute: async (\n args: {\n project_id?: string;\n state?: 'opened' | 'closed' | 'all';\n scope?: 'assigned_to_me' | 'created_by_me' | 'all';\n search?: string;\n labels?: string;\n milestone?: string;\n limit?: number;\n page?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const result = await client.listIssues({\n projectId: args.project_id,\n state: args.state,\n scope: args.scope,\n search: args.search,\n labels: args.labels,\n milestone: args.milestone,\n limit: args.limit,\n page: args.page,\n });\n return JSON.stringify(result, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\n/**\n * Helper to return validation errors in a consistent format.\n */\nfunction validationError(message: string): string {\n return JSON.stringify({ error: message }, null, 2);\n}\n\nexport const epicTools = {\n gitlab_get_epic: tool({\n description: `Get details of a specific epic by group and epic IID.\nReturns: title, description, state, author, start/end dates, labels, associated issues, and child epics.`,\n args: {\n group_id: z\n .string()\n .describe(\n 'The group ID or URL-encoded path (e.g., \"gitlab-org\" or \"my-group/my-subgroup\")'\n ),\n epic_iid: z.number().describe('The internal ID of the epic within the group'),\n },\n execute: async (args: { group_id: string; epic_iid: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const epic = await client.getEpic(args.group_id, args.epic_iid);\n return JSON.stringify(epic, null, 2);\n },\n }),\n\n gitlab_list_epics: tool({\n description: `List epics for a group with filtering capabilities.\nCan filter by state (opened, closed, all), author, labels, and search query.`,\n args: {\n group_id: z.string().describe('The group ID or URL-encoded path'),\n state: z\n .enum(['opened', 'closed', 'all'])\n .optional()\n .describe('Filter by epic state (default: opened)'),\n author_id: z.number().optional().describe('Filter by author user ID'),\n labels: z.string().optional().describe('Comma-separated list of labels to filter by'),\n search: z.string().optional().describe('Search epics by title or description'),\n limit: z.number().optional().describe('Maximum number of results (default: 20)'),\n },\n execute: async (\n args: {\n group_id: string;\n state?: 'opened' | 'closed' | 'all';\n author_id?: number;\n labels?: string;\n search?: string;\n limit?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const epics = await client.listEpics({\n groupId: args.group_id,\n state: args.state,\n author_id: args.author_id,\n labels: args.labels,\n search: args.search,\n limit: args.limit,\n });\n return JSON.stringify(epics, null, 2);\n },\n }),\n\n gitlab_create_epic: tool({\n description: `Create a new epic in a group.\nReturns the created epic with all details.`,\n args: {\n group_id: z.string().describe('The group ID or URL-encoded path'),\n title: z.string().describe('The title of the epic'),\n description: z\n .string()\n .optional()\n .describe('The description of the epic (supports Markdown)'),\n labels: z.string().optional().describe('Comma-separated list of labels'),\n start_date: z.string().optional().describe('Start date in YYYY-MM-DD format'),\n end_date: z.string().optional().describe('Due/end date in YYYY-MM-DD format'),\n confidential: z\n .boolean()\n .optional()\n .describe('Whether the epic is confidential (default: false)'),\n },\n execute: async (\n args: {\n group_id: string;\n title: string;\n description?: string;\n labels?: string;\n start_date?: string;\n end_date?: string;\n confidential?: boolean;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const epic = await client.createEpic(args.group_id, {\n title: args.title,\n description: args.description,\n labels: args.labels,\n start_date: args.start_date,\n end_date: args.end_date,\n confidential: args.confidential,\n });\n return JSON.stringify(epic, null, 2);\n },\n }),\n\n gitlab_update_epic: tool({\n description: `Update an existing epic.\nCan update title, description, labels, dates, state, and confidentiality.`,\n args: {\n group_id: z.string().describe('The group ID or URL-encoded path'),\n epic_iid: z.number().describe('The internal ID of the epic'),\n title: z.string().optional().describe('The new title'),\n description: z.string().optional().describe('The new description (supports Markdown)'),\n labels: z.string().optional().describe('Comma-separated list of labels'),\n start_date: z.string().optional().describe('Start date in YYYY-MM-DD format'),\n end_date: z.string().optional().describe('Due/end date in YYYY-MM-DD format'),\n state_event: z\n .enum(['close', 'reopen'])\n .optional()\n .describe('Change the state (close or reopen)'),\n confidential: z.boolean().optional().describe('Whether the epic is confidential'),\n },\n execute: async (\n args: {\n group_id: string;\n epic_iid: number;\n title?: string;\n description?: string;\n labels?: string;\n start_date?: string;\n end_date?: string;\n state_event?: 'close' | 'reopen';\n confidential?: boolean;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const epic = await client.updateEpic(args.group_id, args.epic_iid, {\n title: args.title,\n description: args.description,\n labels: args.labels,\n start_date: args.start_date,\n end_date: args.end_date,\n state_event: args.state_event,\n confidential: args.confidential,\n });\n return JSON.stringify(epic, null, 2);\n },\n }),\n\n gitlab_manage_epic_issues: tool({\n description: `Manage issues linked to a GitLab epic.\n\nActions:\n- list: Get all issues associated with the epic\n- add: Link an existing issue to the epic (issue can be from any project within the group hierarchy)\n- remove: Unlink an issue from the epic\n\nExamples:\n- List issues: action=\"list\", group_id=\"gitlab-org\", epic_iid=123\n- Add issue: action=\"add\", group_id=\"gitlab-org\", epic_iid=123, issue_id=456\n- Remove issue: action=\"remove\", group_id=\"gitlab-org\", epic_iid=123, epic_issue_id=789\n\nNote: The epic_issue_id (for remove) is the ID of the epic-issue association, which can be obtained from the list action response.`,\n args: {\n action: z.enum(['list', 'add', 'remove']).describe('The action to perform'),\n group_id: z.string().describe('The group ID or URL-encoded path'),\n epic_iid: z.number().describe('The internal ID of the epic within the group'),\n issue_id: z\n .number()\n .optional()\n .describe('The global ID of the issue to add (required for \"add\" action)'),\n epic_issue_id: z\n .number()\n .optional()\n .describe(\n 'The ID of the epic-issue association to remove (required for \"remove\" action, from list response)'\n ),\n },\n execute: async (\n args: {\n action: 'list' | 'add' | 'remove';\n group_id: string;\n epic_iid: number;\n issue_id?: number;\n epic_issue_id?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n\n switch (args.action) {\n case 'list': {\n const issues = await client.listEpicIssues(args.group_id, args.epic_iid);\n return JSON.stringify(issues, null, 2);\n }\n case 'add': {\n if (args.issue_id === undefined) {\n return validationError('issue_id is required for \"add\" action');\n }\n const result = await client.addIssueToEpic(args.group_id, args.epic_iid, args.issue_id);\n return JSON.stringify(result, null, 2);\n }\n case 'remove': {\n if (args.epic_issue_id === undefined) {\n return validationError('epic_issue_id is required for \"remove\" action');\n }\n const result = await client.removeIssueFromEpic(\n args.group_id,\n args.epic_iid,\n args.epic_issue_id\n );\n return JSON.stringify(result, null, 2);\n }\n }\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const pipelineTools = {\n gitlab_list_pipelines: tool({\n description: `List pipelines for a project.\nCan filter by status, ref (branch/tag), username.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n status: z\n .enum(['running', 'pending', 'success', 'failed', 'canceled', 'skipped', 'manual'])\n .optional()\n .describe('Filter by pipeline status'),\n ref: z.string().optional().describe('Filter by branch or tag name'),\n limit: z.number().optional().describe('Maximum number of results (default: 20)'),\n },\n execute: async (\n args: {\n project_id: string;\n status?: 'running' | 'pending' | 'success' | 'failed' | 'canceled' | 'skipped' | 'manual';\n ref?: string;\n limit?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const pipelines = await client.listPipelines(args.project_id, {\n status: args.status,\n ref: args.ref,\n limit: args.limit,\n });\n return JSON.stringify(pipelines, null, 2);\n },\n }),\n\n gitlab_get_pipeline: tool({\n description: `Get details of a specific pipeline including its jobs.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n pipeline_id: z.number().describe('The ID of the pipeline'),\n },\n execute: async (args: { project_id: string; pipeline_id: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const pipeline = await client.getPipeline(args.project_id, args.pipeline_id);\n return JSON.stringify(pipeline, null, 2);\n },\n }),\n\n gitlab_list_pipeline_jobs: tool({\n description: `List jobs for a pipeline, optionally filter by scope (failed, success, etc).`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n pipeline_id: z.number().describe('The ID of the pipeline'),\n scope: z\n .enum([\n 'created',\n 'pending',\n 'running',\n 'failed',\n 'success',\n 'canceled',\n 'skipped',\n 'manual',\n ])\n .optional()\n .describe('Filter jobs by scope/status'),\n },\n execute: async (\n args: {\n project_id: string;\n pipeline_id: number;\n scope?:\n | 'created'\n | 'pending'\n | 'running'\n | 'failed'\n | 'success'\n | 'canceled'\n | 'skipped'\n | 'manual';\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const jobs = await client.listPipelineJobs(args.project_id, args.pipeline_id, args.scope);\n return JSON.stringify(jobs, null, 2);\n },\n }),\n\n gitlab_get_job_log: tool({\n description: `Get the log/trace output of a specific CI job.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n job_id: z.number().describe('The ID of the job'),\n },\n execute: async (args: { project_id: string; job_id: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n return client.getJobLog(args.project_id, args.job_id);\n },\n }),\n\n gitlab_retry_job: tool({\n description: `Retry a failed or canceled CI job.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n job_id: z.number().describe('The ID of the job to retry'),\n },\n execute: async (args: { project_id: string; job_id: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const job = await client.retryJob(args.project_id, args.job_id);\n return JSON.stringify(job, null, 2);\n },\n }),\n\n gitlab_get_pipeline_failing_jobs: tool({\n description: `Get all failed jobs in a pipeline.\nReturns only the jobs that have failed, making it easier to debug pipeline failures.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n pipeline_id: z.number().describe('The ID of the pipeline'),\n },\n execute: async (args: { project_id: string; pipeline_id: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const jobs = await client.getPipelineFailingJobs(args.project_id, args.pipeline_id);\n return JSON.stringify(jobs, null, 2);\n },\n }),\n\n gitlab_lint_ci_config: tool({\n description: `Validate a CI/CD YAML configuration against GitLab CI syntax rules.\nThis validates the configuration in the context of the project, including:\n- Using the project's CI/CD variables\n- Searching the project's files for include:local entries\n- Optionally simulating pipeline creation (dry_run)\n- Optionally including the list of jobs that would be created\n\nModes:\n- content: Validate provided YAML content (requires 'content' parameter)\n- existing: Validate the existing .gitlab-ci.yml from the repository\n\nReturns validation result with:\n- valid: boolean indicating if configuration is valid\n- errors: array of error messages\n- warnings: array of warning messages\n- merged_yaml: the final merged YAML after processing includes (optional)\n- includes: list of included files (for existing mode)\n- jobs: list of jobs that would be created (optional, requires include_jobs=true)\n\nExamples:\n- Validate content: mode=\"content\", project_id=\"group/project\", content=\"stages: [build]...\"\n- Validate existing: mode=\"existing\", project_id=\"group/project\"`,\n args: {\n mode: z\n .enum(['content', 'existing'])\n .describe('Validation mode: \"content\" for provided YAML, \"existing\" for repo file'),\n project_id: z.string().describe('The project ID or URL-encoded path'),\n content: z\n .string()\n .optional()\n .describe('The CI/CD configuration content (YAML as string) - required for mode=\"content\"'),\n dry_run: z\n .boolean()\n .optional()\n .describe('Run pipeline creation simulation instead of just static check (default: false)'),\n include_jobs: z\n .boolean()\n .optional()\n .describe('Include list of jobs that would be created in the response (default: false)'),\n ref: z\n .string()\n .optional()\n .describe(\n 'Branch or tag context to use for validation (defaults to project default branch)'\n ),\n content_ref: z\n .string()\n .optional()\n .describe(\n 'For mode=\"existing\": Commit SHA, branch or tag to get CI config from (defaults to project default branch)'\n ),\n },\n execute: async (\n args: {\n mode: 'content' | 'existing';\n project_id: string;\n content?: string;\n dry_run?: boolean;\n include_jobs?: boolean;\n ref?: string;\n content_ref?: string;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n\n switch (args.mode) {\n case 'content': {\n if (!args.content) {\n return JSON.stringify({ error: 'content is required when mode is \"content\"' }, null, 2);\n }\n const result = await client.lintCiConfig(args.project_id, args.content, {\n dry_run: args.dry_run,\n include_jobs: args.include_jobs,\n ref: args.ref,\n });\n return JSON.stringify(result, null, 2);\n }\n case 'existing': {\n const result = await client.lintExistingCiConfig(args.project_id, {\n content_ref: args.content_ref,\n dry_run: args.dry_run,\n dry_run_ref: args.ref,\n include_jobs: args.include_jobs,\n });\n return JSON.stringify(result, null, 2);\n }\n }\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const repositoryTools = {\n gitlab_get_file: tool({\n description: `Get the contents of a file from a repository.\nSupports fetching files from any branch, tag, or commit SHA.\nIf ref is not specified, uses the project's default branch.\nNote: Invalid refs will result in a 404 error from the GitLab API.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n file_path: z.string().describe('Path to the file in the repository'),\n ref: z\n .string()\n .optional()\n .describe(\n 'Branch name, tag, or commit SHA to fetch the file from. ' +\n 'Supports full or short commit SHAs. ' +\n 'If omitted, uses the project\\'s default branch (e.g., \"main\" or \"master\").'\n ),\n },\n execute: async (\n args: { project_id: string; file_path: string; ref?: string },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n return client.getFile(args.project_id, args.file_path, args.ref);\n },\n }),\n\n gitlab_get_commit: tool({\n description: `Get a single commit with full details.\nReturns commit metadata including author, message, stats, and parent commits.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n sha: z.string().describe('The commit SHA'),\n },\n execute: async (args: { project_id: string; sha: string }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const commit = await client.getCommit(args.project_id, args.sha);\n return JSON.stringify(commit, null, 2);\n },\n }),\n\n gitlab_list_commits: tool({\n description: `List commits in a repository. Can filter by branch/ref and path.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n ref: z.string().optional().describe('Branch or tag name'),\n path: z.string().optional().describe('File or directory path to filter commits'),\n since: z.string().optional().describe('Only commits after this date (ISO 8601 format)'),\n until: z.string().optional().describe('Only commits before this date (ISO 8601 format)'),\n limit: z.number().optional().describe('Maximum number of results (default: 20)'),\n },\n execute: async (\n args: {\n project_id: string;\n ref?: string;\n path?: string;\n since?: string;\n until?: string;\n limit?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const commits = await client.listCommits(args.project_id, {\n ref: args.ref,\n path: args.path,\n since: args.since,\n until: args.until,\n limit: args.limit,\n });\n return JSON.stringify(commits, null, 2);\n },\n }),\n\n gitlab_get_commit_diff: tool({\n description: `Get the diff for a specific commit.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n sha: z.string().describe('The commit SHA'),\n },\n execute: async (args: { project_id: string; sha: string }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const diff = await client.getCommitDiff(args.project_id, args.sha);\n return JSON.stringify(diff, null, 2);\n },\n }),\n\n gitlab_list_repository_tree: tool({\n description: `List files and directories in a repository.\nReturns the tree structure of the repository at a given path and ref.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n path: z.string().optional().describe('Path inside repository (default: root)'),\n ref: z.string().optional().describe('Branch, tag, or commit SHA (default: default branch)'),\n recursive: z.boolean().optional().describe('Get recursive tree (default: false)'),\n per_page: z.number().optional().describe('Number of results per page (default: 20)'),\n },\n execute: async (\n args: {\n project_id: string;\n path?: string;\n ref?: string;\n recursive?: boolean;\n per_page?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const tree = await client.listRepositoryTree(args.project_id, {\n path: args.path,\n ref: args.ref,\n recursive: args.recursive,\n per_page: args.per_page,\n });\n return JSON.stringify(tree, null, 2);\n },\n }),\n\n gitlab_list_branches: tool({\n description: `List branches in a repository.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n search: z.string().optional().describe('Search branches by name'),\n },\n execute: async (args: { project_id: string; search?: string }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const branches = await client.listBranches(args.project_id, args.search);\n return JSON.stringify(branches, null, 2);\n },\n }),\n\n gitlab_get_commit_comments: tool({\n description: `Get all comments on a specific commit.\nReturns all comments (notes) that have been added to a commit, including line-specific comments.\nThis is different from discussions - it returns individual comments in a flat structure.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n sha: z.string().describe('The commit SHA'),\n },\n execute: async (args: { project_id: string; sha: string }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const comments = await client.getCommitComments(args.project_id, args.sha);\n return JSON.stringify(comments, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\n/**\n * All supported search scopes\n */\ntype SearchScope =\n | 'projects'\n | 'issues'\n | 'merge_requests'\n | 'milestones'\n | 'users'\n | 'blobs'\n | 'commits'\n | 'notes'\n | 'wiki_blobs'\n | 'group_projects';\n\n/**\n * Scopes that use the generic search API\n */\nconst GENERIC_SEARCH_SCOPES = ['projects', 'issues', 'merge_requests', 'blobs'] as const;\n\n/**\n * Scopes that use specialized client methods\n */\nconst SPECIALIZED_SCOPES = [\n 'milestones',\n 'users',\n 'commits',\n 'notes',\n 'wiki_blobs',\n 'group_projects',\n] as const;\n\n/**\n * All valid search scopes\n */\nconst ALL_SCOPES = [...GENERIC_SEARCH_SCOPES, ...SPECIALIZED_SCOPES] as const;\n\n/**\n * Scopes that support the 'ref' parameter\n */\nconst REF_SUPPORTED_SCOPES = ['commits', 'wiki_blobs'] as const;\n\n/**\n * Scopes that support the 'state' parameter\n */\nconst STATE_SUPPORTED_SCOPES = ['milestones'] as const;\n\n/**\n * Create a standardized validation error message\n */\nfunction validationError(param: string, scope: string): Error {\n return new Error(`Missing required parameter: '${param}' is required for scope '${scope}'`);\n}\n\n/**\n * Create an error for invalid parameter usage\n */\nfunction invalidParamError(param: string, validScopes: readonly string[]): Error {\n return new Error(\n `Invalid parameter: '${param}' is only valid for scopes: ${validScopes.join(', ')}`\n );\n}\n\n/**\n * Validate scope-specific required parameters and parameter combinations\n *\n * @example\n * // Valid: notes scope with project_id\n * validateSearchParams('notes', { project_id: 'my/project' });\n *\n * @example\n * // Invalid: ref with issues scope\n * validateSearchParams('issues', { ref: 'main' }); // throws error\n */\nfunction validateSearchParams(\n scope: SearchScope,\n args: {\n project_id?: string;\n group_id?: string;\n ref?: string;\n state?: string;\n }\n): void {\n // Validate required parameters\n switch (scope) {\n case 'notes':\n if (!args.project_id) throw validationError('project_id', scope);\n break;\n case 'group_projects':\n if (!args.group_id) throw validationError('group_id', scope);\n break;\n }\n\n // Validate scope-specific parameter combinations\n if (args.ref && !REF_SUPPORTED_SCOPES.includes(scope as (typeof REF_SUPPORTED_SCOPES)[number])) {\n throw invalidParamError('ref', REF_SUPPORTED_SCOPES);\n }\n\n if (\n args.state &&\n !STATE_SUPPORTED_SCOPES.includes(scope as (typeof STATE_SUPPORTED_SCOPES)[number])\n ) {\n throw invalidParamError('state', STATE_SUPPORTED_SCOPES);\n }\n}\n\nexport const searchTools = {\n /**\n * Unified search across all GitLab resources\n *\n * @example\n * // Search for issues in a project\n * gitlab_search({ scope: \"issues\", search: \"bug\", project_id: \"my-group/project\" })\n *\n * @example\n * // Search commits on specific branch\n * gitlab_search({ scope: \"commits\", search: \"fix\", ref: \"main\" })\n *\n * @example\n * // Search for projects within a group\n * gitlab_search({ scope: \"group_projects\", group_id: \"gitlab-org\", search: \"runner\" })\n *\n * @example\n * // Search notes/comments in a project\n * gitlab_search({ scope: \"notes\", search: \"LGTM\", project_id: \"my-group/project\" })\n */\n gitlab_search: tool({\n description: `Search across GitLab for various resources with scope-specific options.\n\nScopes and their requirements:\n- projects: Search projects by name/description\n- issues: Search issues by title/description\n- merge_requests: Search MRs by title/description\n- milestones: Search milestones (supports state filter)\n- users: Search users by name/email\n- blobs: Search file content (code search)\n- commits: Search commits by message/author/SHA (supports ref filter)\n- notes: Search comments/notes (requires project_id)\n- wiki_blobs: Search wiki content (supports ref filter)\n- group_projects: Search projects within a group (requires group_id)\n\nExamples:\n- Issues: scope=\"issues\", search=\"bug\", project_id=\"my-group/my-project\"\n- Code: scope=\"blobs\", search=\"function calculateTotal\"\n- Commits: scope=\"commits\", search=\"fix login\", ref=\"main\"\n- Group projects: scope=\"group_projects\", group_id=\"gitlab-org\", search=\"runner\"\n- Notes: scope=\"notes\", search=\"LGTM\", project_id=\"my-group/my-project\"`,\n args: {\n scope: z\n .enum([\n 'projects',\n 'issues',\n 'merge_requests',\n 'milestones',\n 'users',\n 'blobs',\n 'commits',\n 'notes',\n 'wiki_blobs',\n 'group_projects',\n ])\n .describe('The type of resource to search'),\n search: z.string().describe('The search query'),\n // Context parameters\n project_id: z\n .string()\n .optional()\n .describe('Limit search to a specific project. Required for notes scope'),\n group_id: z\n .string()\n .optional()\n .describe('Group ID or path. Required for group_projects scope'),\n // Common options\n limit: z.number().optional().describe('Maximum number of results (default: 20)'),\n order_by: z\n .enum(['created_at'])\n .optional()\n .describe(\n 'Order results by field (for milestones, users, commits, notes, wiki_blobs, group_projects)'\n ),\n sort: z\n .enum(['asc', 'desc'])\n .optional()\n .describe('Sort order (for milestones, users, commits, notes, wiki_blobs, group_projects)'),\n // Scope-specific options\n ref: z.string().optional().describe('Branch or tag name (for commits, wiki_blobs scopes)'),\n state: z\n .enum(['active', 'closed', 'all'])\n .optional()\n .describe('Filter by state (for milestones scope)'),\n },\n execute: async (\n args: {\n scope: SearchScope;\n search: string;\n project_id?: string;\n group_id?: string;\n limit?: number;\n order_by?: 'created_at';\n sort?: 'asc' | 'desc';\n ref?: string;\n state?: 'active' | 'closed' | 'all';\n },\n _ctx: ToolContext\n ) => {\n // Validate scope-specific requirements and parameter combinations\n validateSearchParams(args.scope, {\n project_id: args.project_id,\n group_id: args.group_id,\n ref: args.ref,\n state: args.state,\n });\n\n const client = getGitLabClient();\n const commonOptions = {\n order_by: args.order_by,\n sort: args.sort,\n limit: args.limit,\n };\n\n switch (args.scope) {\n // Generic search API scopes\n case 'projects':\n case 'issues':\n case 'merge_requests':\n case 'blobs':\n return JSON.stringify(\n await client.search(args.scope, args.search, args.project_id, args.limit),\n null,\n 2\n );\n\n // Specialized scopes with dedicated client methods\n case 'milestones':\n return JSON.stringify(\n await client.searchMilestones(args.search, args.project_id, {\n ...commonOptions,\n state: args.state,\n }),\n null,\n 2\n );\n\n case 'users':\n return JSON.stringify(\n await client.searchUsers(args.search, args.project_id, commonOptions),\n null,\n 2\n );\n\n case 'commits':\n return JSON.stringify(\n await client.searchCommits(args.search, args.project_id, {\n ...commonOptions,\n ref: args.ref,\n }),\n null,\n 2\n );\n\n case 'notes':\n return JSON.stringify(\n await client.searchNotes(args.search, args.project_id!, commonOptions),\n null,\n 2\n );\n\n case 'wiki_blobs':\n return JSON.stringify(\n await client.searchWikiBlobs(args.search, args.project_id, {\n ...commonOptions,\n ref: args.ref,\n }),\n null,\n 2\n );\n\n case 'group_projects':\n return JSON.stringify(\n await client.searchGroupProjects(args.group_id!, args.search, commonOptions),\n null,\n 2\n );\n\n default:\n throw new Error(\n `Invalid scope '${args.scope}'. Must be one of: ${ALL_SCOPES.join(', ')}`\n );\n }\n },\n }),\n\n /**\n * Search GitLab official documentation\n * Separate tool because it uses a completely different API (docs.gitlab.com)\n */\n gitlab_documentation_search: tool({\n description: `Search GitLab official documentation at docs.gitlab.com.\nReturns relevant documentation pages matching the search query.\n\nUseful for:\n- Finding GitLab feature documentation\n- Learning about GitLab APIs and integrations\n- Discovering best practices and guides\n- Troubleshooting GitLab issues\n\nNote: This searches the public GitLab documentation site, not your instance's documentation.`,\n args: {\n search: z.string().describe('The search query (documentation topic or keyword)'),\n limit: z.number().optional().describe('Maximum number of results (default: 10)'),\n },\n execute: async (args: { search: string; limit?: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const results = await client.searchDocumentation(args.search, args.limit);\n return JSON.stringify(results, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const projectTools = {\n gitlab_get_project: tool({\n description: `Get details of a specific project.`,\n args: {\n project_id: z\n .string()\n .describe('The project ID or URL-encoded path (e.g., \"gitlab-org/gitlab\")'),\n },\n execute: async (args: { project_id: string }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const project = await client.getProject(args.project_id);\n return JSON.stringify(project, null, 2);\n },\n }),\n\n gitlab_list_project_members: tool({\n description: `List members of a project.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n },\n execute: async (args: { project_id: string }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const members = await client.listProjectMembers(args.project_id);\n return JSON.stringify(members, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const userTools = {\n gitlab_get_current_user: tool({\n description: `Get current user information.\nReturns details about the authenticated user including username, email, and permissions.`,\n args: {},\n execute: async (_args: Record<string, never>, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const user = await client.getCurrentUser();\n return JSON.stringify(user, null, 2);\n },\n }),\n\n gitlab_get_user: tool({\n description: `Get a user by their ID.\nReturns user details including username, name, state, and profile information.`,\n args: {\n user_id: z.number().describe('The user ID'),\n },\n execute: async (args: { user_id: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const user = await client.getUser(args.user_id);\n return JSON.stringify(user, null, 2);\n },\n }),\n\n gitlab_get_user_by_username: tool({\n description: `Find a user by their username.\nReturns user details including ID, name, state, and profile information.\nUseful for looking up a user's ID when you only know their username.`,\n args: {\n username: z.string().describe('The username to look up (without @ prefix)'),\n },\n execute: async (args: { username: string }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const username = args.username.replace(/^@/, '');\n const users = await client.getUserByUsername(username);\n if (users.length === 0) {\n return JSON.stringify({ error: `No user found with username: ${username}` });\n }\n if (users.length > 1) {\n return JSON.stringify(\n {\n warning: `Multiple users found for username: ${username}`,\n users,\n },\n null,\n 2\n );\n }\n return JSON.stringify(users[0], null, 2);\n },\n }),\n\n gitlab_get_user_status: tool({\n description: `Get a user's status including availability.\nReturns the user's status emoji, message, and availability (e.g., \"busy\").\nUseful for checking if someone is available before requesting a review.`,\n args: {\n user_id: z.number().describe('The user ID'),\n },\n execute: async (args: { user_id: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const status = await client.getUserStatus(args.user_id);\n return JSON.stringify(status, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const securityTools = {\n gitlab_list_vulnerabilities: tool({\n description: `List persisted vulnerabilities for a project.\nReturns security vulnerabilities detected in the project.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n state: z\n .enum(['detected', 'confirmed', 'dismissed', 'resolved'])\n .optional()\n .describe('Filter by vulnerability state'),\n severity: z\n .enum(['undefined', 'info', 'unknown', 'low', 'medium', 'high', 'critical'])\n .optional()\n .describe('Filter by severity level'),\n report_type: z\n .enum([\n 'sast',\n 'dast',\n 'dependency_scanning',\n 'container_scanning',\n 'secret_detection',\n 'coverage_fuzzing',\n 'api_fuzzing',\n ])\n .optional()\n .describe('Filter by report type'),\n limit: z.number().optional().describe('Maximum number of results (default: 20)'),\n },\n execute: async (\n args: {\n project_id: string;\n state?: 'detected' | 'confirmed' | 'dismissed' | 'resolved';\n severity?: 'undefined' | 'info' | 'unknown' | 'low' | 'medium' | 'high' | 'critical';\n report_type?:\n | 'sast'\n | 'dast'\n | 'dependency_scanning'\n | 'container_scanning'\n | 'secret_detection'\n | 'coverage_fuzzing'\n | 'api_fuzzing';\n limit?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const vulnerabilities = await client.listVulnerabilities(args.project_id, {\n state: args.state,\n severity: args.severity,\n report_type: args.report_type,\n limit: args.limit,\n });\n return JSON.stringify(vulnerabilities, null, 2);\n },\n }),\n\n gitlab_get_vulnerability_details: tool({\n description: `Get details for a specific vulnerability.\nReturns full information about a security vulnerability including description, location, and remediation.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n vulnerability_id: z.number().describe('The ID of the vulnerability'),\n },\n execute: async (args: { project_id: string; vulnerability_id: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const vulnerability = await client.getVulnerabilityDetails(\n args.project_id,\n args.vulnerability_id\n );\n return JSON.stringify(vulnerability, null, 2);\n },\n }),\n\n gitlab_create_vulnerability_issue: tool({\n description: `Create a new issue linked to one or more security vulnerabilities.\nThis creates an issue in the project and automatically links it to the specified vulnerabilities.\nRequires Developer role or higher.`,\n args: {\n project_path: z\n .string()\n .describe('Full path of the project (e.g., \"group/project\" or \"group/subgroup/project\")'),\n vulnerability_ids: z\n .array(z.string())\n .describe(\n 'Array of vulnerability IDs in format \"gid://gitlab/Vulnerability/{id}\". Get these from gitlab_list_vulnerabilities.'\n ),\n },\n execute: async (\n args: { project_path: string; vulnerability_ids: string[] },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const issue = await client.createVulnerabilityIssue(\n args.project_path,\n args.vulnerability_ids\n );\n return JSON.stringify(issue, null, 2);\n },\n }),\n\n gitlab_dismiss_vulnerability: tool({\n description: `Dismiss a security vulnerability with a reason.\nUse this when a vulnerability is not applicable, is a false positive, or has been mitigated.\nRequires Developer role or higher.`,\n args: {\n vulnerability_id: z\n .string()\n .describe(\n 'Vulnerability ID in format \"gid://gitlab/Vulnerability/{id}\". Get this from gitlab_list_vulnerabilities.'\n ),\n reason: z\n .enum([\n 'ACCEPTABLE_RISK',\n 'FALSE_POSITIVE',\n 'MITIGATING_CONTROL',\n 'USED_IN_TESTS',\n 'NOT_APPLICABLE',\n ])\n .describe('Reason for dismissing the vulnerability'),\n comment: z.string().optional().describe('Optional comment explaining the dismissal'),\n },\n execute: async (\n args: {\n vulnerability_id: string;\n reason:\n | 'ACCEPTABLE_RISK'\n | 'FALSE_POSITIVE'\n | 'MITIGATING_CONTROL'\n | 'USED_IN_TESTS'\n | 'NOT_APPLICABLE';\n comment?: string;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const vulnerability = await client.dismissVulnerability(\n args.vulnerability_id,\n args.reason,\n args.comment\n );\n return JSON.stringify(vulnerability, null, 2);\n },\n }),\n\n gitlab_confirm_vulnerability: tool({\n description: `Confirm a security vulnerability.\nUse this to acknowledge that a vulnerability is valid and needs attention.\nRequires Developer role or higher.`,\n args: {\n vulnerability_id: z\n .string()\n .describe(\n 'Vulnerability ID in format \"gid://gitlab/Vulnerability/{id}\". Get this from gitlab_list_vulnerabilities.'\n ),\n comment: z.string().optional().describe('Optional comment about the confirmation'),\n },\n execute: async (args: { vulnerability_id: string; comment?: string }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const vulnerability = await client.confirmVulnerability(args.vulnerability_id, args.comment);\n return JSON.stringify(vulnerability, null, 2);\n },\n }),\n\n gitlab_revert_vulnerability_to_detected: tool({\n description: `Revert a vulnerability back to detected state.\nUse this to undo a previous confirmation or dismissal.\nRequires Developer role or higher.`,\n args: {\n vulnerability_id: z\n .string()\n .describe(\n 'Vulnerability ID in format \"gid://gitlab/Vulnerability/{id}\". Get this from gitlab_list_vulnerabilities.'\n ),\n comment: z.string().optional().describe('Optional comment about reverting the state'),\n },\n execute: async (args: { vulnerability_id: string; comment?: string }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const vulnerability = await client.revertVulnerability(args.vulnerability_id, args.comment);\n return JSON.stringify(vulnerability, null, 2);\n },\n }),\n\n gitlab_update_vulnerability_severity: tool({\n description: `Update the severity level of one or more vulnerabilities.\nUse this to adjust the severity rating based on your assessment.\nRequires Developer role or higher.`,\n args: {\n vulnerability_ids: z\n .array(z.string())\n .describe(\n 'Array of vulnerability IDs in format \"gid://gitlab/Vulnerability/{id}\". Get these from gitlab_list_vulnerabilities.'\n ),\n severity: z\n .enum(['CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'INFO', 'UNKNOWN'])\n .describe('New severity level for the vulnerabilities'),\n comment: z.string().describe('Comment explaining the severity change (required)'),\n },\n execute: async (\n args: {\n vulnerability_ids: string[];\n severity: 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW' | 'INFO' | 'UNKNOWN';\n comment: string;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const vulnerabilities = await client.updateVulnerabilitySeverity(\n args.vulnerability_ids,\n args.severity,\n args.comment\n );\n return JSON.stringify(vulnerabilities, null, 2);\n },\n }),\n\n gitlab_link_vulnerability_to_issue: tool({\n description: `Link an existing issue to one or more vulnerabilities.\nUse this to associate vulnerabilities with an existing issue for tracking.\nRequires Developer role or higher.`,\n args: {\n issue_id: z\n .string()\n .describe(\n 'Issue ID in format \"gid://gitlab/Issue/{id}\". You can construct this from the issue IID.'\n ),\n vulnerability_ids: z\n .array(z.string())\n .describe(\n 'Array of vulnerability IDs in format \"gid://gitlab/Vulnerability/{id}\". Get these from gitlab_list_vulnerabilities.'\n ),\n },\n execute: async (args: { issue_id: string; vulnerability_ids: string[] }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const issue = await client.linkVulnerabilityToIssue(args.issue_id, args.vulnerability_ids);\n return JSON.stringify(issue, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const todoTools = {\n gitlab_list_todos: tool({\n description: `List TODO items for the current user using GraphQL API with pagination support.\nReturns a list of pending or done TODO items assigned to the authenticated user.\nTODOs are created when you are assigned to an issue/MR, mentioned in a comment, or when someone requests your review.\n\nThe response includes pagination information (pageInfo) with cursors for fetching additional pages.\nUse 'after' with the 'endCursor' from pageInfo to get the next page.\nUse 'before' with the 'startCursor' from pageInfo to get the previous page.`,\n args: {\n action: z\n .enum([\n 'assigned',\n 'mentioned',\n 'build_failed',\n 'marked',\n 'approval_required',\n 'unmergeable',\n 'directly_addressed',\n 'merge_train_removed',\n 'review_requested',\n ])\n .optional()\n .describe('Filter by action type'),\n author_id: z.number().optional().describe('Filter by author ID'),\n project_id: z.string().optional().describe('Filter by project ID or path'),\n group_id: z.string().optional().describe('Filter by group ID'),\n state: z.enum(['pending', 'done']).optional().describe('Filter by state (default: pending)'),\n type: z\n .enum(['Issue', 'MergeRequest', 'DesignManagement::Design', 'Alert', 'Epic', 'Commit'])\n .optional()\n .describe('Filter by target type'),\n first: z\n .number()\n .optional()\n .describe('Number of items to return from the beginning (default: 20, max: 100)'),\n after: z\n .string()\n .optional()\n .describe('Cursor for forward pagination - use endCursor from previous response'),\n last: z\n .number()\n .optional()\n .describe('Number of items to return from the end (for backward pagination)'),\n before: z\n .string()\n .optional()\n .describe('Cursor for backward pagination - use startCursor from previous response'),\n },\n execute: async (\n args: {\n action?:\n | 'assigned'\n | 'mentioned'\n | 'build_failed'\n | 'marked'\n | 'approval_required'\n | 'unmergeable'\n | 'directly_addressed'\n | 'merge_train_removed'\n | 'review_requested';\n author_id?: number;\n project_id?: string;\n group_id?: string;\n state?: 'pending' | 'done';\n type?: 'Issue' | 'MergeRequest' | 'DesignManagement::Design' | 'Alert' | 'Epic' | 'Commit';\n first?: number;\n after?: string;\n last?: number;\n before?: string;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const result = await client.listTodos({\n action: args.action,\n author_id: args.author_id,\n project_id: args.project_id,\n group_id: args.group_id,\n state: args.state,\n type: args.type,\n first: args.first,\n after: args.after,\n last: args.last,\n before: args.before,\n });\n return JSON.stringify(result, null, 2);\n },\n }),\n\n gitlab_mark_todo_done: tool({\n description: `Mark TODO items as done.\n\nActions:\n- one: Mark a specific TODO item as done (requires todo_id)\n- all: Mark all pending TODO items as done\n\nExamples:\n- Mark one: action=\"one\", todo_id=123\n- Mark all: action=\"all\"`,\n args: {\n action: z\n .enum(['one', 'all'])\n .describe('Action to perform: \"one\" for single TODO, \"all\" for all TODOs'),\n todo_id: z\n .number()\n .optional()\n .describe('The ID of the TODO item (required for action=\"one\")'),\n },\n execute: async (args: { action: 'one' | 'all'; todo_id?: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n\n switch (args.action) {\n case 'one': {\n if (args.todo_id === undefined) {\n return JSON.stringify({ error: 'todo_id is required when action is \"one\"' }, null, 2);\n }\n const result = await client.markTodoAsDone(args.todo_id);\n if (!result.success) {\n return JSON.stringify(\n {\n success: false,\n message: result.message,\n },\n null,\n 2\n );\n }\n return JSON.stringify(\n {\n success: true,\n todo: result.todo,\n },\n null,\n 2\n );\n }\n case 'all': {\n const result = await client.markAllTodosAsDone();\n return JSON.stringify(result, null, 2);\n }\n }\n },\n }),\n\n gitlab_get_todo_count: tool({\n description: `Get the count of pending TODO items.\nReturns the total number of pending TODOs for the current user.`,\n args: {},\n execute: async (_args: Record<string, never>, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const count = await client.getTodoCount();\n return JSON.stringify(count, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const wikiTools = {\n gitlab_get_wiki_page: tool({\n description: `Get a wiki page with its content.\nReturns the wiki page content and metadata.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n slug: z.string().describe('The slug (URL-friendly name) of the wiki page'),\n },\n execute: async (args: { project_id: string; slug: string }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const page = await client.getWikiPage(args.project_id, args.slug);\n return JSON.stringify(page, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const workItemTools = {\n gitlab_get_work_item: tool({\n description: `Get a single work item (issue, epic, task, etc.).\nWork items are the new unified model for issues, epics, tasks, and other work tracking items in GitLab.`,\n args: {\n project_id: z.string().describe('The project ID or full path (e.g. \"gitlab-org/gitlab\")'),\n work_item_id: z\n .number()\n .describe(\n 'The IID of the work item — the number visible in the GitLab URL (e.g. for https://gitlab.com/group/project/-/work_items/52, use 52). This is NOT the global database ID.'\n ),\n },\n execute: async (args: { project_id: string; work_item_id: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const workItem = await client.getWorkItem(args.project_id, args.work_item_id);\n return JSON.stringify(workItem, null, 2);\n },\n }),\n\n gitlab_list_work_items: tool({\n description: `List work items in a project or group.\nWork items include issues, epics, tasks, and other work tracking items.`,\n args: {\n project_id: z.string().optional().describe('The project ID or URL-encoded path'),\n group_id: z.string().optional().describe('The group ID or URL-encoded path'),\n state: z\n .enum(['opened', 'closed', 'all'])\n .optional()\n .describe('Filter by state (default: opened)'),\n search: z.string().optional().describe('Search work items by title or description'),\n labels: z.string().optional().describe('Comma-separated list of labels to filter by'),\n work_item_type: z\n .string()\n .optional()\n .describe(\"Filter by work item type (e.g., 'Issue', 'Epic', 'Task')\"),\n limit: z.number().optional().describe('Maximum number of results (default: 20)'),\n },\n execute: async (\n args: {\n project_id?: string;\n group_id?: string;\n state?: 'opened' | 'closed' | 'all';\n search?: string;\n labels?: string;\n work_item_type?: string;\n limit?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const workItems = await client.listWorkItems({\n projectId: args.project_id,\n groupId: args.group_id,\n state: args.state,\n search: args.search,\n labels: args.labels,\n work_item_type: args.work_item_type,\n limit: args.limit,\n });\n return JSON.stringify(workItems, null, 2);\n },\n }),\n\n gitlab_get_work_item_notes: tool({\n description: `Get all comments for a work item.\nReturns all notes/comments on the work item in chronological order.`,\n args: {\n project_id: z.string().describe('The project ID or full path (e.g. \"gitlab-org/gitlab\")'),\n work_item_id: z\n .number()\n .describe(\n 'The IID of the work item — the number visible in the GitLab URL (e.g. for https://gitlab.com/group/project/-/work_items/52, use 52). This is NOT the global database ID.'\n ),\n },\n execute: async (args: { project_id: string; work_item_id: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const notes = await client.getWorkItemNotes(args.project_id, args.work_item_id);\n return JSON.stringify(notes, null, 2);\n },\n }),\n\n gitlab_create_work_item: tool({\n description: `Create a new work item (issue, task, etc.).\nWork items are the new unified model for issues, epics, tasks, and other work tracking items.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n title: z.string().describe('The title of the work item'),\n work_item_type_id: z\n .number()\n .describe('The ID of the work item type (e.g., 1 for Issue, 2 for Task)'),\n description: z\n .string()\n .optional()\n .describe('The description of the work item (supports Markdown)'),\n labels: z.array(z.string()).optional().describe('Array of label names'),\n assignee_ids: z.array(z.number()).optional().describe('Array of user IDs to assign'),\n },\n execute: async (\n args: {\n project_id: string;\n title: string;\n work_item_type_id: number;\n description?: string;\n labels?: string[];\n assignee_ids?: number[];\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const workItem = await client.createWorkItem(args.project_id, {\n title: args.title,\n work_item_type_id: args.work_item_type_id,\n description: args.description,\n labels: args.labels,\n assignee_ids: args.assignee_ids,\n });\n return JSON.stringify(workItem, null, 2);\n },\n }),\n\n gitlab_update_work_item: tool({\n description: `Update an existing work item.\nCan update title, description, state, labels, and assignees.`,\n args: {\n project_id: z.string().describe('The project ID or full path (e.g. \"gitlab-org/gitlab\")'),\n work_item_id: z\n .number()\n .describe(\n 'The IID of the work item — the number visible in the GitLab URL (e.g. for https://gitlab.com/group/project/-/work_items/52, use 52). This is NOT the global database ID.'\n ),\n title: z.string().optional().describe('The new title'),\n description: z.string().optional().describe('The new description (supports Markdown)'),\n state_event: z\n .enum(['close', 'reopen'])\n .optional()\n .describe('Change the state (close or reopen)'),\n labels: z.array(z.string()).optional().describe('Array of label names'),\n assignee_ids: z.array(z.number()).optional().describe('Array of user IDs to assign'),\n },\n execute: async (\n args: {\n project_id: string;\n work_item_id: number;\n title?: string;\n description?: string;\n state_event?: 'close' | 'reopen';\n labels?: string[];\n assignee_ids?: number[];\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const workItem = await client.updateWorkItem(args.project_id, args.work_item_id, {\n title: args.title,\n description: args.description,\n state_event: args.state_event,\n labels: args.labels,\n assignee_ids: args.assignee_ids,\n });\n return JSON.stringify(workItem, null, 2);\n },\n }),\n\n gitlab_create_work_item_note: tool({\n description: `Create a comment on a work item.`,\n args: {\n project_id: z.string().describe('The project ID or full path (e.g. \"gitlab-org/gitlab\")'),\n work_item_id: z\n .number()\n .describe(\n 'The IID of the work item — the number visible in the GitLab URL (e.g. for https://gitlab.com/group/project/-/work_items/52, use 52). This is NOT the global database ID.'\n ),\n body: z.string().describe('The content of the note/comment (supports Markdown)'),\n },\n execute: async (\n args: { project_id: string; work_item_id: number; body: string },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const note = await client.createWorkItemNote(args.project_id, args.work_item_id, args.body);\n return JSON.stringify(note, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\nimport type { DiscussionsResult } from '../client/discussions-types.js';\n\nconst z = tool.schema;\n\n/**\n * Supported resource types for discussions\n */\ntype ResourceType = 'merge_request' | 'issue' | 'epic' | 'commit' | 'snippet';\n\n/**\n * Helper to normalize resolved parameter which might come as string from some frameworks\n */\nfunction normalizeBoolean(value: unknown): boolean | undefined {\n if (typeof value === 'boolean') return value;\n if (value === 'true') return true;\n if (value === 'false') return false;\n return undefined;\n}\n\n/**\n * Helper to apply client-side resolved filter to discussions\n * Note: GitLab API doesn't support server-side filtering by resolved status\n *\n * When filtering:\n * - resolved=true: Returns only resolved resolvable discussions\n * - resolved=false: Returns only unresolved resolvable discussions\n * - Only resolvable discussions are included (system notes with resolvable=false are excluded)\n */\nfunction filterDiscussionsByResolved(\n result: DiscussionsResult,\n resolved?: boolean | string\n): DiscussionsResult {\n const normalizedResolved = normalizeBoolean(resolved);\n if (normalizedResolved === undefined) {\n return result;\n }\n return {\n discussions: {\n ...result.discussions,\n nodes: result.discussions.nodes.filter(\n (d) => d.resolvable && d.resolved === normalizedResolved\n ),\n },\n };\n}\n\n/**\n * Supported resource types for resolve/unresolve operations\n */\ntype ResolvableResourceType = 'merge_request' | 'issue';\n\n/**\n * Position object for code-specific comments on MRs and commits\n */\nconst positionSchema = z.object({\n base_sha: z.string().describe('SHA of the base commit'),\n start_sha: z.string().describe('SHA of the start commit'),\n head_sha: z.string().describe('SHA of the head commit'),\n position_type: z.enum(['text', 'image']).describe('Type of position'),\n old_path: z.string().optional().describe('Path of the file before changes'),\n new_path: z.string().optional().describe('Path of the file after changes'),\n old_line: z.number().optional().describe('Line number in the old version'),\n new_line: z.number().optional().describe('Line number in the new version'),\n});\n\n/**\n * Helper to validate required parameters based on resource type\n */\nfunction validateResourceParams(\n resourceType: ResourceType,\n args: {\n project_id?: string;\n group_id?: string;\n iid?: number;\n sha?: string;\n snippet_id?: number;\n }\n): void {\n switch (resourceType) {\n case 'merge_request':\n case 'issue':\n if (!args.project_id) throw new Error(`project_id is required for ${resourceType}`);\n if (args.iid == null) throw new Error(`iid is required for ${resourceType}`);\n break;\n case 'epic':\n if (!args.group_id) throw new Error('group_id is required for epic');\n if (args.iid == null) throw new Error('iid is required for epic');\n break;\n case 'commit':\n if (!args.project_id) throw new Error('project_id is required for commit');\n if (!args.sha) throw new Error('sha is required for commit');\n break;\n case 'snippet':\n if (!args.project_id) throw new Error('project_id is required for snippet');\n if (args.snippet_id == null) throw new Error('snippet_id is required for snippet');\n break;\n }\n}\n\nexport const discussionsUnifiedTools = {\n /**\n * List discussions for any GitLab resource type\n */\n gitlab_list_discussions: tool({\n description: `List discussions (comment threads) on any GitLab resource.\nSupports: merge_requests, issues, epics, commits, snippets.\n\nReturns discussion threads with nested notes. Each discussion contains \na 'notes' array with individual comments.\n\nFor pagination, use 'after' with the 'endCursor' from pageInfo to get the next page.\n\nExamples:\n- MR: resource_type=\"merge_request\", project_id=\"group/project\", iid=123\n- Issue: resource_type=\"issue\", project_id=\"group/project\", iid=456 \n- Epic: resource_type=\"epic\", group_id=\"my-group\", iid=1\n- Commit: resource_type=\"commit\", project_id=\"group/project\", sha=\"abc123\"\n- Snippet: resource_type=\"snippet\", project_id=\"group/project\", snippet_id=789`,\n args: {\n resource_type: z\n .enum(['merge_request', 'issue', 'epic', 'commit', 'snippet'])\n .describe('Type of GitLab resource'),\n project_id: z\n .string()\n .optional()\n .describe('Project ID or path. Required for merge_request, issue, commit, snippet'),\n group_id: z.string().optional().describe('Group ID or path. Required for epic'),\n iid: z\n .number()\n .optional()\n .describe('Internal ID of the resource (for merge_request, issue, epic)'),\n sha: z.string().optional().describe('Commit SHA (required for commit)'),\n snippet_id: z.number().optional().describe('Snippet ID (required for snippet)'),\n // Filtering\n resolved: z\n .boolean()\n .optional()\n .describe(\n 'Filter by resolved status: true for resolved, false for unresolved. Only returns resolvable discussions (excludes system notes). Client-side filtering.'\n ),\n // Pagination\n first: z.number().optional().describe('Number of items to return (default: 20)'),\n after: z\n .string()\n .optional()\n .describe('Cursor for pagination - use endCursor from previous response'),\n before: z.string().optional().describe('Cursor for backward pagination'),\n last: z.number().optional().describe('Number of items from the end'),\n },\n execute: async (\n args: {\n resource_type: ResourceType;\n project_id?: string;\n group_id?: string;\n iid?: number;\n sha?: string;\n snippet_id?: number;\n resolved?: boolean | string;\n first?: number;\n after?: string;\n before?: string;\n last?: number;\n },\n _ctx: ToolContext\n ) => {\n validateResourceParams(args.resource_type, args);\n\n const client = getGitLabClient();\n const paginationOptions = {\n first: args.first,\n after: args.after,\n before: args.before,\n last: args.last,\n };\n\n let result: DiscussionsResult;\n\n switch (args.resource_type) {\n case 'merge_request':\n result = await client.listMrDiscussions(args.project_id!, args.iid!, paginationOptions);\n break;\n case 'issue':\n result = await client.listIssueDiscussions(\n args.project_id!,\n args.iid!,\n paginationOptions\n );\n break;\n case 'epic':\n result = await client.listEpicDiscussions(args.group_id!, args.iid!, paginationOptions);\n break;\n case 'commit':\n // Commit discussions use REST API - return as-is (different structure)\n return JSON.stringify(\n await client.listCommitDiscussions(args.project_id!, args.sha!),\n null,\n 2\n );\n case 'snippet':\n result = await client.listSnippetDiscussions(\n args.project_id!,\n args.snippet_id!,\n paginationOptions\n );\n break;\n default:\n throw new Error(`Unsupported resource type: ${args.resource_type}`);\n }\n\n // Apply client-side filtering if resolved parameter is specified\n const filteredResult = filterDiscussionsByResolved(result, args.resolved);\n return JSON.stringify(filteredResult, null, 2);\n },\n }),\n\n /**\n * Get a specific discussion thread from any GitLab resource\n */\n gitlab_get_discussion: tool({\n description: `Get a specific discussion thread with all its replies.\nReturns the discussion with its 'notes' array containing all comments.\n\nUse this to get full context of a specific conversation.\n\nRequired parameters vary by resource type:\n- merge_request: project_id, iid, discussion_id\n- issue: project_id, iid, discussion_id \n- epic: group_id, iid, discussion_id\n- commit: project_id, sha, discussion_id\n- snippet: project_id, snippet_id, discussion_id`,\n args: {\n resource_type: z\n .enum(['merge_request', 'issue', 'epic', 'commit', 'snippet'])\n .describe('Type of GitLab resource'),\n discussion_id: z.string().describe('The ID of the discussion thread'),\n project_id: z.string().optional().describe('Project ID or path'),\n group_id: z.string().optional().describe('Group ID or path (for epic)'),\n iid: z.number().optional().describe('Internal ID (for merge_request, issue, epic)'),\n sha: z.string().optional().describe('Commit SHA (for commit)'),\n snippet_id: z.number().optional().describe('Snippet ID (for snippet)'),\n },\n execute: async (\n args: {\n resource_type: ResourceType;\n discussion_id: string;\n project_id?: string;\n group_id?: string;\n iid?: number;\n sha?: string;\n snippet_id?: number;\n },\n _ctx: ToolContext\n ) => {\n validateResourceParams(args.resource_type, args);\n\n const client = getGitLabClient();\n\n switch (args.resource_type) {\n case 'merge_request':\n return JSON.stringify(\n await client.getMrDiscussion(args.project_id!, args.iid!, args.discussion_id),\n null,\n 2\n );\n case 'issue':\n return JSON.stringify(\n await client.getIssueDiscussion(args.project_id!, args.iid!, args.discussion_id),\n null,\n 2\n );\n case 'epic':\n return JSON.stringify(\n await client.getEpicDiscussion(args.group_id!, args.iid!, args.discussion_id),\n null,\n 2\n );\n case 'commit':\n return JSON.stringify(\n await client.getCommitDiscussion(args.project_id!, args.sha!, args.discussion_id),\n null,\n 2\n );\n case 'snippet':\n return JSON.stringify(\n await client.getSnippetDiscussion(\n args.project_id!,\n args.snippet_id!,\n args.discussion_id\n ),\n null,\n 2\n );\n default:\n throw new Error(`Unsupported resource type: ${args.resource_type}`);\n }\n },\n }),\n\n /**\n * Create a new discussion thread or reply to an existing one\n */\n gitlab_create_discussion: tool({\n description: `Create a new discussion thread or reply to an existing one.\n\nREPLYING TO EXISTING THREADS:\nTo reply to an existing discussion, provide the discussion_id parameter.\nThis is the recommended way to reply in-thread rather than creating a standalone comment.\n\nSTARTING A NEW DISCUSSION:\nOmit discussion_id to create a new thread. For code-specific comments on MRs/commits, provide position information.\n\nExamples:\n- Reply to thread: resource_type=\"merge_request\", project_id=\"group/project\", iid=123, discussion_id=\"abc123def\", body=\"Thanks for the feedback!\"\n- New comment: resource_type=\"merge_request\", project_id=\"group/project\", iid=123, body=\"General comment\"\n- Code comment: resource_type=\"merge_request\", project_id=\"group/project\", iid=123, body=\"...\", position={base_sha, head_sha, new_path, new_line, ...}`,\n args: {\n resource_type: z\n .enum(['merge_request', 'issue', 'epic', 'commit', 'snippet'])\n .describe('Type of GitLab resource'),\n body: z.string().describe('The comment text (Markdown supported)'),\n project_id: z.string().optional().describe('Project ID or path'),\n group_id: z.string().optional().describe('Group ID or path (for epic)'),\n iid: z.number().optional().describe('Internal ID (for merge_request, issue, epic)'),\n sha: z.string().optional().describe('Commit SHA (for commit)'),\n snippet_id: z.number().optional().describe('Snippet ID (for snippet)'),\n discussion_id: z\n .string()\n .optional()\n .describe('If provided, replies to existing discussion. If omitted, creates new thread'),\n position: positionSchema\n .optional()\n .describe('Position for code-specific comments (MR/commit only)'),\n },\n execute: async (\n args: {\n resource_type: ResourceType;\n body: string;\n project_id?: string;\n group_id?: string;\n iid?: number;\n sha?: string;\n snippet_id?: number;\n discussion_id?: string;\n position?: {\n base_sha: string;\n start_sha: string;\n head_sha: string;\n position_type: 'text' | 'image';\n old_path?: string;\n new_path?: string;\n old_line?: number;\n new_line?: number;\n };\n },\n _ctx: ToolContext\n ) => {\n validateResourceParams(args.resource_type, args);\n\n const client = getGitLabClient();\n\n // If discussion_id is provided, this is a reply to existing thread\n if (args.discussion_id) {\n const note = await client.replyToDiscussion(\n args.resource_type,\n {\n projectId: args.project_id,\n groupId: args.group_id,\n iid: args.iid,\n sha: args.sha,\n snippetId: args.snippet_id,\n },\n args.discussion_id,\n args.body\n );\n return JSON.stringify(note, null, 2);\n }\n\n // Otherwise, create a new discussion\n switch (args.resource_type) {\n case 'merge_request':\n return JSON.stringify(\n await client.createMrDiscussion(args.project_id!, args.iid!, args.body, args.position),\n null,\n 2\n );\n case 'issue':\n // Issues don't support position-based discussions, create a note that starts a discussion\n return JSON.stringify(\n await client.createIssueNote(args.project_id!, args.iid!, args.body),\n null,\n 2\n );\n case 'epic':\n return JSON.stringify(\n await client.createEpicNote(args.group_id!, args.iid!, args.body),\n null,\n 2\n );\n case 'commit':\n return JSON.stringify(\n await client.createCommitDiscussion(\n args.project_id!,\n args.sha!,\n args.body,\n args.position\n ),\n null,\n 2\n );\n case 'snippet':\n return JSON.stringify(\n await client.createSnippetDiscussion(args.project_id!, args.snippet_id!, args.body),\n null,\n 2\n );\n default:\n throw new Error(`Unsupported resource type: ${args.resource_type}`);\n }\n },\n }),\n\n /**\n * Resolve or unresolve a discussion thread\n */\n gitlab_resolve_discussion: tool({\n description: `Mark a discussion thread as resolved or unresolve it.\nOnly works for resolvable discussions (MRs and issues only).\n\nUses GraphQL API which handles all discussion types including outdated discussions\n(those with resolved: null) that the REST API cannot handle.\n\nUse after addressing feedback to indicate the discussion is complete.`,\n args: {\n resource_type: z\n .enum(['merge_request', 'issue'])\n .describe('Type of resource (only MR and issue discussions can be resolved)'),\n action: z.enum(['resolve', 'unresolve']).describe('Whether to resolve or unresolve'),\n discussion_id: z.string().describe('The ID of the discussion thread'),\n project_id: z.string().describe('Project ID or path'),\n iid: z.number().describe('Internal ID of the MR or issue'),\n },\n execute: async (\n args: {\n resource_type: ResolvableResourceType;\n action: 'resolve' | 'unresolve';\n discussion_id: string;\n project_id: string;\n iid: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const resolve = args.action === 'resolve';\n\n // Use GraphQL API which handles all discussion types including outdated ones\n return JSON.stringify(\n await client.toggleDiscussionResolved(args.discussion_id, resolve),\n null,\n 2\n );\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\nimport type { NotesResult } from '../client/notes-types.js';\n\nconst z = tool.schema;\n\n/**\n * Helper to normalize resolved parameter which might come as string from some frameworks\n */\nfunction normalizeBoolean(value: unknown): boolean | undefined {\n if (typeof value === 'boolean') return value;\n if (value === 'true') return true;\n if (value === 'false') return false;\n return undefined;\n}\n\n/**\n * Helper to apply client-side resolved filter to notes\n * Note: GitLab API doesn't support server-side filtering by resolved status\n *\n * When filtering:\n * - resolved=true: Returns only resolved resolvable notes\n * - resolved=false: Returns only unresolved resolvable notes\n * - Only resolvable notes are included (system notes with resolvable=false are excluded)\n */\nfunction filterNotesByResolved(result: NotesResult, resolved?: boolean | string): NotesResult {\n const normalizedResolved = normalizeBoolean(resolved);\n if (normalizedResolved === undefined) {\n return result;\n }\n return {\n ...result,\n notes: {\n ...result.notes,\n nodes: result.notes.nodes.filter((n) => n.resolvable && n.resolved === normalizedResolved),\n },\n };\n}\n\n/**\n * Supported resource types for listing notes\n */\ntype ListNotesResourceType = 'merge_request' | 'issue' | 'epic' | 'snippet';\n\n/**\n * Supported resource types for getting a single note\n * Note: MR notes are accessed via discussions API, not individual note fetch\n */\ntype GetNoteResourceType = 'issue' | 'epic';\n\n/**\n * Supported resource types for creating notes\n */\ntype CreateNoteResourceType = 'merge_request' | 'issue' | 'epic' | 'snippet';\n\n/**\n * Supported resource types for updating notes\n */\ntype UpdateNoteResourceType = 'merge_request' | 'issue' | 'epic' | 'snippet';\n\n/**\n * Resource types supported by list/create/update operations (all four)\n */\nconst NOTE_RESOURCE_TYPES = ['merge_request', 'issue', 'epic', 'snippet'] as const;\n\n/**\n * Resource types supported by getting a single note (issue/epic only)\n */\nconst GET_NOTE_RESOURCE_TYPES = ['issue', 'epic'] as const;\n\n/**\n * Create a standardized validation error message\n */\nfunction validationError(param: string, resourceType: string): Error {\n return new Error(\n `Missing required parameter: '${param}' is required for resource_type '${resourceType}'`\n );\n}\n\n/**\n * Common arg shape accepted by note validators.\n * All fields are optional so a single validator can serve list/create/update/get.\n */\ninterface NoteValidationArgs {\n project_id?: string;\n group_id?: string;\n iid?: number;\n snippet_id?: number;\n note_id?: number;\n}\n\n/**\n * Unified validator for note tool parameters.\n *\n * - `allowedTypes` controls which resource types are valid (e.g. get supports only issue/epic).\n * - `requireNoteId` is set true for get/update operations.\n *\n * Per-resource-type required field rules are enforced for everyone:\n * merge_request: project_id + iid\n * issue: project_id + iid\n * epic: group_id + iid\n * snippet: project_id + snippet_id\n */\nfunction validateNoteParams(\n resourceType: string,\n args: NoteValidationArgs,\n opts: { allowedTypes: readonly string[]; requireNoteId?: boolean }\n): void {\n if (!opts.allowedTypes.includes(resourceType)) {\n throw new Error(\n `Invalid resource_type '${resourceType}'. Must be one of: ${opts.allowedTypes.join(', ')}`\n );\n }\n\n if (opts.requireNoteId && args.note_id == null) {\n throw validationError('note_id', resourceType);\n }\n\n switch (resourceType) {\n case 'merge_request':\n case 'issue':\n if (!args.project_id) throw validationError('project_id', resourceType);\n if (args.iid == null) throw validationError('iid', resourceType);\n break;\n case 'epic':\n if (!args.group_id) throw validationError('group_id', resourceType);\n if (args.iid == null) throw validationError('iid', resourceType);\n break;\n case 'snippet':\n if (!args.project_id) throw validationError('project_id', resourceType);\n if (args.snippet_id == null) throw validationError('snippet_id', resourceType);\n break;\n }\n}\n\nexport const notesUnifiedTools = {\n /**\n * List notes/comments for any GitLab resource type\n */\n gitlab_list_notes: tool({\n description: `List all notes/comments on any GitLab resource using GraphQL API with pagination support.\nReturns all comments including system notes in chronological order.\nThis is easier to read than discussions which have nested structure.\n\nThe response includes pagination information (pageInfo) with cursors for fetching additional pages.\nUse 'after' with the 'endCursor' from pageInfo to get the next page.\nUse 'before' with the 'startCursor' from pageInfo to get the previous page.\n\nExamples:\n- MR: resource_type=\"merge_request\", project_id=\"group/project\", iid=123\n- Issue: resource_type=\"issue\", project_id=\"group/project\", iid=456 \n- Epic: resource_type=\"epic\", group_id=\"my-group\", iid=1\n- Snippet: resource_type=\"snippet\", project_id=\"group/project\", snippet_id=789`,\n args: {\n resource_type: z\n .enum(['merge_request', 'issue', 'epic', 'snippet'])\n .describe('Type of GitLab resource'),\n project_id: z\n .string()\n .optional()\n .describe('Project ID or path. Required for merge_request, issue, snippet'),\n group_id: z.string().optional().describe('Group ID or path. Required for epic'),\n iid: z\n .number()\n .optional()\n .describe('Internal ID of the resource (for merge_request, issue, epic)'),\n snippet_id: z.number().optional().describe('Snippet ID (required for snippet)'),\n // Filtering\n resolved: z\n .boolean()\n .optional()\n .describe(\n 'Filter by resolved status: true for resolved, false for unresolved. Only returns resolvable notes (excludes system notes). Client-side filtering.'\n ),\n // Pagination\n first: z\n .number()\n .optional()\n .describe('Number of items to return from the beginning (default: 20, max: 100)'),\n after: z\n .string()\n .optional()\n .describe('Cursor for forward pagination - use endCursor from previous response'),\n last: z\n .number()\n .optional()\n .describe('Number of items to return from the end (for backward pagination)'),\n before: z\n .string()\n .optional()\n .describe('Cursor for backward pagination - use startCursor from previous response'),\n },\n execute: async (\n args: {\n resource_type: ListNotesResourceType;\n project_id?: string;\n group_id?: string;\n iid?: number;\n snippet_id?: number;\n resolved?: boolean | string;\n first?: number;\n after?: string;\n last?: number;\n before?: string;\n },\n _ctx: ToolContext\n ) => {\n validateNoteParams(args.resource_type, args, { allowedTypes: NOTE_RESOURCE_TYPES });\n\n const client = getGitLabClient();\n const paginationOptions = {\n first: args.first,\n after: args.after,\n last: args.last,\n before: args.before,\n };\n\n let result: NotesResult;\n\n switch (args.resource_type) {\n case 'merge_request':\n result = await client.listMrNotes(args.project_id!, args.iid!, paginationOptions);\n break;\n case 'issue':\n result = await client.listIssueNotes(args.project_id!, args.iid!, paginationOptions);\n break;\n case 'epic':\n result = await client.listEpicNotes(args.group_id!, args.iid!, paginationOptions);\n break;\n case 'snippet':\n result = await client.listSnippetNotes(\n args.project_id!,\n args.snippet_id!,\n paginationOptions\n );\n break;\n default:\n throw new Error(`Unsupported resource type: ${args.resource_type}`);\n }\n\n // Apply client-side filtering if resolved parameter is specified\n const filteredResult = filterNotesByResolved(result, args.resolved);\n return JSON.stringify(filteredResult, null, 2);\n },\n }),\n\n /**\n * Get a single note/comment by its ID\n */\n gitlab_get_note: tool({\n description: `Get a single note/comment from an issue or epic by its ID.\nReturns the full details of a specific note including author, body, timestamps, and metadata.\nUseful when you need to retrieve a specific comment without fetching all notes.\n\nSupports: issues, epics (MR notes use discussions API)\n\nExamples:\n- Issue note: resource_type=\"issue\", project_id=\"group/project\", iid=456, note_id=123\n- Epic note: resource_type=\"epic\", group_id=\"my-group\", iid=1, note_id=456`,\n args: {\n resource_type: z\n .enum(['issue', 'epic'])\n .describe('Type of GitLab resource (issue or epic only)'),\n note_id: z.number().describe('The ID of the note to retrieve'),\n project_id: z.string().optional().describe('Project ID or path. Required for issue'),\n group_id: z.string().optional().describe('Group ID or path. Required for epic'),\n iid: z.number().describe('Internal ID of the issue or epic'),\n },\n execute: async (\n args: {\n resource_type: GetNoteResourceType;\n note_id: number;\n project_id?: string;\n group_id?: string;\n iid: number;\n },\n _ctx: ToolContext\n ) => {\n validateNoteParams(args.resource_type, args, {\n allowedTypes: GET_NOTE_RESOURCE_TYPES,\n requireNoteId: true,\n });\n\n const client = getGitLabClient();\n\n switch (args.resource_type) {\n case 'issue':\n return JSON.stringify(\n await client.getIssueNote(args.project_id!, args.iid, args.note_id),\n null,\n 2\n );\n case 'epic':\n return JSON.stringify(\n await client.getEpicNote(args.group_id!, args.iid, args.note_id),\n null,\n 2\n );\n default:\n throw new Error(`Unsupported resource type: ${args.resource_type}`);\n }\n },\n }),\n\n /**\n * Create a simple note/comment on any GitLab resource\n */\n gitlab_create_note: tool({\n description: `Add a simple comment/note to any GitLab resource.\nCreates a standalone comment (not part of a thread).\n\nFor replying to existing discussion threads, use gitlab_create_discussion \nwith discussion_id parameter instead.\n\nExamples:\n- MR comment: resource_type=\"merge_request\", project_id=\"group/project\", iid=123, body=\"LGTM!\"\n- Issue comment: resource_type=\"issue\", project_id=\"group/project\", iid=456, body=\"Working on this\"\n- Epic comment: resource_type=\"epic\", group_id=\"my-group\", iid=1, body=\"Planning complete\"\n- Snippet comment: resource_type=\"snippet\", project_id=\"group/project\", snippet_id=789, body=\"Nice code!\"`,\n args: {\n resource_type: z\n .enum(['merge_request', 'issue', 'epic', 'snippet'])\n .describe('Type of GitLab resource'),\n body: z.string().describe('The content of the note/comment (supports Markdown)'),\n project_id: z\n .string()\n .optional()\n .describe('Project ID or path. Required for merge_request, issue, snippet'),\n group_id: z.string().optional().describe('Group ID or path. Required for epic'),\n iid: z\n .number()\n .optional()\n .describe('Internal ID of the resource (for merge_request, issue, epic)'),\n snippet_id: z.number().optional().describe('Snippet ID (required for snippet)'),\n },\n execute: async (\n args: {\n resource_type: CreateNoteResourceType;\n body: string;\n project_id?: string;\n group_id?: string;\n iid?: number;\n snippet_id?: number;\n },\n _ctx: ToolContext\n ) => {\n validateNoteParams(args.resource_type, args, { allowedTypes: NOTE_RESOURCE_TYPES });\n\n const client = getGitLabClient();\n\n switch (args.resource_type) {\n case 'merge_request':\n return JSON.stringify(\n await client.createMrNote(args.project_id!, args.iid!, args.body),\n null,\n 2\n );\n case 'issue':\n return JSON.stringify(\n await client.createIssueNote(args.project_id!, args.iid!, args.body),\n null,\n 2\n );\n case 'epic':\n return JSON.stringify(\n await client.createEpicNote(args.group_id!, args.iid!, args.body),\n null,\n 2\n );\n case 'snippet':\n return JSON.stringify(\n await client.createSnippetNote(args.project_id!, args.snippet_id!, args.body),\n null,\n 2\n );\n default:\n throw new Error(`Unsupported resource type: ${args.resource_type}`);\n }\n },\n }),\n\n /**\n * Update an existing note/comment on any GitLab resource\n */\n gitlab_update_note: tool({\n description: `Update an existing note/comment on any GitLab resource.\nModifies the body content of an existing note. You can only update notes you authored.\n\nExamples:\n- MR note: resource_type=\"merge_request\", project_id=\"group/project\", iid=123, note_id=456, body=\"Updated comment\"\n- Issue note: resource_type=\"issue\", project_id=\"group/project\", iid=456, note_id=789, body=\"Updated comment\"\n- Epic note: resource_type=\"epic\", group_id=\"my-group\", iid=1, note_id=456, body=\"Updated comment\"\n- Snippet note: resource_type=\"snippet\", project_id=\"group/project\", snippet_id=789, note_id=123, body=\"Updated comment\"`,\n args: {\n resource_type: z\n .enum(['merge_request', 'issue', 'epic', 'snippet'])\n .describe('Type of GitLab resource'),\n note_id: z.number().describe('The ID of the note to update'),\n body: z.string().describe('The new content for the note (supports Markdown)'),\n project_id: z\n .string()\n .optional()\n .describe('Project ID or path. Required for merge_request, issue, snippet'),\n group_id: z.string().optional().describe('Group ID or path. Required for epic'),\n iid: z\n .number()\n .optional()\n .describe('Internal ID of the resource (for merge_request, issue, epic)'),\n snippet_id: z.number().optional().describe('Snippet ID (required for snippet)'),\n },\n execute: async (\n args: {\n resource_type: UpdateNoteResourceType;\n note_id: number;\n body: string;\n project_id?: string;\n group_id?: string;\n iid?: number;\n snippet_id?: number;\n },\n _ctx: ToolContext\n ) => {\n validateNoteParams(args.resource_type, args, {\n allowedTypes: NOTE_RESOURCE_TYPES,\n requireNoteId: true,\n });\n\n const client = getGitLabClient();\n\n switch (args.resource_type) {\n case 'merge_request':\n return JSON.stringify(\n await client.updateMrNote(args.project_id!, args.iid!, args.note_id, args.body),\n null,\n 2\n );\n case 'issue':\n return JSON.stringify(\n await client.updateIssueNote(args.project_id!, args.iid!, args.note_id, args.body),\n null,\n 2\n );\n case 'epic':\n return JSON.stringify(\n await client.updateEpicNote(args.group_id!, args.iid!, args.note_id, args.body),\n null,\n 2\n );\n case 'snippet':\n return JSON.stringify(\n await client.updateSnippetNote(\n args.project_id!,\n args.snippet_id!,\n args.note_id,\n args.body\n ),\n null,\n 2\n );\n default:\n throw new Error(`Unsupported resource type: ${args.resource_type}`);\n }\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { GitClient } from '../client/git.js';\n\nconst z = tool.schema;\n\n// Singleton instance of GitClient\nlet gitClient: GitClient | null = null;\n\nfunction getGitClient(): GitClient {\n if (!gitClient) {\n gitClient = new GitClient();\n }\n return gitClient;\n}\n\nexport const gitTools = {\n run_git_command: tool({\n description: `Execute safe, read-only git commands in the repository working directory.\n\nSecurity restrictions:\n- Only read-only git commands are allowed (status, log, show, diff, branch, tag, etc.)\n- Destructive operations are forbidden (push, pull, commit, add, rm, reset, merge, etc.)\n- Shell operators and command injection attempts are blocked\n- Commands are executed with a 30-second timeout and 10MB output buffer\n\nAllowed commands include:\n- status: Show working tree status\n- log: Show commit logs\n- show: Show various types of objects\n- diff: Show changes between commits, commit and working tree, etc.\n- branch: List, create, or delete branches (read-only: list only)\n- tag: List tags (read-only: list only)\n- remote: List remote repositories (read-only: list only)\n- ls-files: Show information about files in the index and working tree\n- ls-remote: List references in a remote repository\n- rev-parse: Parse revision (or other objects) names\n- describe: Give an object a human readable name based on an available ref\n- config: Get repository configuration (read-only: --get operations only)\n- blame: Show what revision and author last modified each line of a file\n- shortlog: Summarize git log output\n- reflog: Show reference logs\n- show-ref: List references in a local repository\n- ls-tree: List the contents of a tree object\n- cat-file: Provide content or type and size information for repository objects\n- rev-list: List commit objects in reverse chronological order\n- name-rev: Find symbolic names for given revs\n- show-branch: Show branches and their commits\n- whatchanged: Show logs with difference each commit introduces\n- grep: Print lines matching a pattern\n- annotate: Annotate file lines with commit information\n\nExamples:\n- run_git_command(\"status\", []) - Show working tree status\n- run_git_command(\"log\", [\"--oneline\", \"-10\"]) - Show last 10 commits\n- run_git_command(\"diff\", [\"HEAD~1\", \"HEAD\"]) - Show diff between last two commits\n- run_git_command(\"branch\", [\"-a\"]) - List all branches\n- run_git_command(\"show\", [\"HEAD:README.md\"]) - Show README.md from HEAD commit`,\n args: {\n command: z.string().describe('The git command to execute (without \"git\" prefix)'),\n args: z\n .array(z.string())\n .optional()\n .describe('Array of arguments for the git command (default: [])'),\n working_directory: z\n .string()\n .optional()\n .describe(\n 'Path to the git repository (default: current working directory). Use this to execute git commands in a specific repository.'\n ),\n },\n execute: async (\n args: {\n command: string;\n args?: string[];\n working_directory?: string;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitClient();\n\n // Set working directory if provided\n if (args.working_directory) {\n client.setWorkingDirectory(args.working_directory);\n }\n\n try {\n const output = await client.runGitCommand(args.command, args.args || []);\n return output;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Failed to execute git command: ${error.message}`);\n }\n throw error;\n }\n },\n }),\n};\n","import { execFile } from 'child_process';\nimport { promisify } from 'util';\nimport { existsSync, statSync } from 'fs';\nimport { resolve, join } from 'path';\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Git client for executing git commands in a repository\n * Security: Only allows safe, read-only git commands by default\n */\nexport class GitClient {\n private workingDirectory: string;\n\n // Whitelist of allowed git commands (read-only operations)\n private static readonly ALLOWED_COMMANDS = new Set([\n 'status',\n 'log',\n 'show',\n 'diff',\n 'branch',\n 'tag',\n 'remote',\n 'ls-files',\n 'ls-remote',\n 'rev-parse',\n 'describe',\n 'config',\n 'blame',\n 'shortlog',\n 'reflog',\n 'show-ref',\n 'ls-tree',\n 'cat-file',\n 'rev-list',\n 'name-rev',\n 'show-branch',\n 'whatchanged',\n 'grep',\n 'annotate',\n ]);\n\n // Commands that are explicitly forbidden (destructive operations)\n private static readonly FORBIDDEN_COMMANDS = new Set([\n 'push',\n 'pull',\n 'fetch',\n 'clone',\n 'commit',\n 'add',\n 'rm',\n 'mv',\n 'reset',\n 'rebase',\n 'merge',\n 'cherry-pick',\n 'revert',\n 'clean',\n 'checkout',\n 'switch',\n 'restore',\n 'stash',\n 'submodule',\n 'worktree',\n ]);\n\n // Shell operators that should be blocked\n private static readonly SHELL_OPERATORS = [';', '&&', '||', '|', '`', '$('];\n\n constructor(workingDirectory?: string) {\n this.workingDirectory = workingDirectory || process.cwd();\n }\n\n /**\n * Execute a git command in the repository working directory\n *\n * Security: Uses execFile() instead of exec() to prevent command injection.\n * Arguments are passed directly to git without shell interpretation, making\n * attacks like `--format=\"$(malicious)\"` impossible.\n *\n * @param command - The git command to execute (without 'git' prefix)\n * @param args - Array of arguments for the command\n * @returns Command output\n * @throws Error if command is not allowed or execution fails\n */\n async runGitCommand(command: string, args: string[] = []): Promise<string> {\n // Validate command\n this.validateCommand(command, args);\n\n try {\n // Use execFile instead of exec to avoid shell interpretation\n // This prevents command injection through git's own command substitution features\n const { stdout, stderr } = await execFileAsync('git', [command, ...args], {\n cwd: this.workingDirectory,\n maxBuffer: 10 * 1024 * 1024, // 10MB buffer\n timeout: 30000, // 30 second timeout\n });\n\n // Return stdout, but include stderr if present (git often uses stderr for warnings)\n return stderr ? `${stdout}\\n\\nWarnings/Info:\\n${stderr}` : stdout;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Git command failed: ${error.message}`);\n }\n throw error;\n }\n }\n\n /**\n * Validate that a git command is safe to execute\n * @param command - The git command\n * @param args - Command arguments\n * @throws Error if command is not allowed\n */\n private validateCommand(command: string, args: string[]): void {\n // Check if command is in the forbidden list\n if (GitClient.FORBIDDEN_COMMANDS.has(command)) {\n throw new Error(\n `Git command '${command}' is not allowed. Only read-only operations are permitted.`\n );\n }\n\n // Check if command is in the allowed list\n if (!GitClient.ALLOWED_COMMANDS.has(command)) {\n throw new Error(\n `Git command '${command}' is not in the allowed list. Only safe, read-only operations are permitted.`\n );\n }\n\n // Additional validation for specific commands with potentially dangerous flags\n if (command === 'branch' && args.some((arg) => arg === '-d' || arg === '-D' || arg === '-m')) {\n throw new Error('Branch deletion and renaming operations are not allowed.');\n }\n\n if (command === 'tag' && args.some((arg) => arg === '-d' || arg === '-f')) {\n throw new Error('Tag deletion and force operations are not allowed.');\n }\n\n if (\n command === 'remote' &&\n args.some((arg) => arg === 'add' || arg === 'remove' || arg === 'set-url')\n ) {\n throw new Error('Remote modification operations are not allowed.');\n }\n\n if (command === 'config' && args.length > 0 && !args.some((arg) => arg.startsWith('--get'))) {\n throw new Error('Only git config read operations (--get) are allowed.');\n }\n\n // Check for shell injection attempts\n const allArgs = [command, ...args].join(' ');\n if (GitClient.SHELL_OPERATORS.some((op) => allArgs.includes(op))) {\n throw new Error('Command contains potentially dangerous shell operators.');\n }\n }\n\n /**\n * Validate that a directory exists and is a git repository\n * @param directory - Path to validate\n * @throws Error if directory is invalid or not a git repository\n */\n private validateDirectory(directory: string): void {\n // Resolve to absolute path to prevent directory traversal\n const absolutePath = resolve(directory);\n\n // Check if directory exists\n if (!existsSync(absolutePath)) {\n throw new Error(`Directory does not exist: ${absolutePath}`);\n }\n\n // Check if it's actually a directory\n const stats = statSync(absolutePath);\n if (!stats.isDirectory()) {\n throw new Error(`Path is not a directory: ${absolutePath}`);\n }\n\n // Check if it's a git repository (contains .git directory or file)\n const gitDir = join(absolutePath, '.git');\n if (!existsSync(gitDir)) {\n throw new Error(`Not a git repository: ${absolutePath}`);\n }\n }\n\n /**\n * Get the current working directory\n */\n getWorkingDirectory(): string {\n return this.workingDirectory;\n }\n\n /**\n * Set the working directory for git commands\n * @param directory - Path to the git repository\n * @throws Error if directory is invalid or not a git repository\n */\n setWorkingDirectory(directory: string): void {\n // Validate the directory before setting it\n this.validateDirectory(directory);\n\n // Store as absolute path to prevent traversal attacks\n this.workingDirectory = resolve(directory);\n }\n}\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const auditTools = {\n gitlab_list_project_audit_events: tool({\n description: `List audit events for a project.\nReturns audit events including actions like project settings changes, member additions/removals, and other security-relevant activities.\nNote: Requires project owner role or higher.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n created_after: z\n .string()\n .optional()\n .describe('Return audit events created after this date (ISO 8601 format)'),\n created_before: z\n .string()\n .optional()\n .describe('Return audit events created before this date (ISO 8601 format)'),\n entity_type: z\n .string()\n .optional()\n .describe('Filter by entity type (e.g., \"User\", \"Project\", \"Group\")'),\n entity_id: z.number().optional().describe('Filter by entity ID'),\n author_id: z.number().optional().describe('Filter by author user ID'),\n per_page: z.number().optional().describe('Number of results per page (default: 20)'),\n page: z.number().optional().describe('Page number for pagination (default: 1)'),\n },\n execute: async (\n args: {\n project_id: string;\n created_after?: string;\n created_before?: string;\n entity_type?: string;\n entity_id?: number;\n author_id?: number;\n per_page?: number;\n page?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const events = await client.listProjectAuditEvents(args.project_id, {\n created_after: args.created_after,\n created_before: args.created_before,\n entity_type: args.entity_type,\n entity_id: args.entity_id,\n author_id: args.author_id,\n per_page: args.per_page,\n page: args.page,\n });\n return JSON.stringify(events, null, 2);\n },\n }),\n\n gitlab_list_group_audit_events: tool({\n description: `List audit events for a group.\nReturns audit events including actions like group settings changes, member additions/removals, subgroup operations, and other security-relevant activities.\nNote: Requires group owner role or higher.`,\n args: {\n group_id: z.string().describe('The group ID or URL-encoded path'),\n created_after: z\n .string()\n .optional()\n .describe('Return audit events created after this date (ISO 8601 format)'),\n created_before: z\n .string()\n .optional()\n .describe('Return audit events created before this date (ISO 8601 format)'),\n entity_type: z\n .string()\n .optional()\n .describe('Filter by entity type (e.g., \"User\", \"Project\", \"Group\")'),\n entity_id: z.number().optional().describe('Filter by entity ID'),\n author_id: z.number().optional().describe('Filter by author user ID'),\n per_page: z.number().optional().describe('Number of results per page (default: 20)'),\n page: z.number().optional().describe('Page number for pagination (default: 1)'),\n },\n execute: async (\n args: {\n group_id: string;\n created_after?: string;\n created_before?: string;\n entity_type?: string;\n entity_id?: number;\n author_id?: number;\n per_page?: number;\n page?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const events = await client.listGroupAuditEvents(args.group_id, {\n created_after: args.created_after,\n created_before: args.created_before,\n entity_type: args.entity_type,\n entity_id: args.entity_id,\n author_id: args.author_id,\n per_page: args.per_page,\n page: args.page,\n });\n return JSON.stringify(events, null, 2);\n },\n }),\n\n gitlab_list_instance_audit_events: tool({\n description: `List instance-level audit events.\nReturns audit events for the entire GitLab instance including actions like instance settings changes, user management, license changes, and other system-wide security-relevant activities.\nNote: Requires administrator access.`,\n args: {\n created_after: z\n .string()\n .optional()\n .describe('Return audit events created after this date (ISO 8601 format)'),\n created_before: z\n .string()\n .optional()\n .describe('Return audit events created before this date (ISO 8601 format)'),\n entity_type: z\n .string()\n .optional()\n .describe('Filter by entity type (e.g., \"User\", \"Project\", \"Group\")'),\n entity_id: z.number().optional().describe('Filter by entity ID'),\n author_id: z.number().optional().describe('Filter by author user ID'),\n per_page: z.number().optional().describe('Number of results per page (default: 20)'),\n page: z.number().optional().describe('Page number for pagination (default: 1)'),\n },\n execute: async (\n args: {\n created_after?: string;\n created_before?: string;\n entity_type?: string;\n entity_id?: number;\n author_id?: number;\n per_page?: number;\n page?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const events = await client.listInstanceAuditEvents({\n created_after: args.created_after,\n created_before: args.created_before,\n entity_type: args.entity_type,\n entity_id: args.entity_id,\n author_id: args.author_id,\n per_page: args.per_page,\n page: args.page,\n });\n return JSON.stringify(events, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\nimport type { AwardableResourceType, AwardEmojiResourceId } from '../client/award-emoji.js';\n\nconst z = tool.schema;\n\n/**\n * Helper to validate required parameters for award emoji operations\n */\nfunction validateAwardEmojiParams(args: {\n resource_type: AwardableResourceType;\n project_id: string;\n resource_iid: number;\n}): void {\n if (!args.project_id) {\n throw new Error('project_id is required');\n }\n if (args.resource_iid == null) {\n throw new Error('resource_iid is required');\n }\n}\n\n/**\n * Build the resource ID object from tool arguments\n */\nfunction buildResourceId(args: {\n project_id: string;\n resource_type: AwardableResourceType;\n resource_iid: number;\n note_id?: number;\n}): AwardEmojiResourceId {\n return {\n projectId: args.project_id,\n resourceType: args.resource_type,\n resourceIid: args.resource_iid,\n noteId: args.note_id,\n };\n}\n\nexport const awardEmojiTools = {\n /**\n * Add a reaction (award emoji) to a resource or note\n */\n gitlab_create_award_emoji: tool({\n description: `Add a reaction (award emoji) to a merge request, issue, snippet, or a note/comment on these resources.\n\nCommon emoji names: thumbsup, thumbsdown, smile, tada, rocket, eyes, heart, +1, -1\n\nTo react to a specific comment/note, provide the note_id parameter.\n\nExamples:\n- React to MR: resource_type=\"merge_request\", project_id=\"group/project\", resource_iid=123, name=\"thumbsup\"\n- React to issue comment: resource_type=\"issue\", project_id=\"group/project\", resource_iid=456, note_id=789, name=\"rocket\"`,\n args: {\n resource_type: z\n .enum(['merge_request', 'issue', 'snippet'])\n .describe('Type of resource to add the reaction to'),\n project_id: z.string().describe('Project ID or URL-encoded path'),\n resource_iid: z.number().describe('Internal ID of the merge request, issue, or snippet'),\n name: z\n .string()\n .describe(\n 'Emoji name without colons (e.g., \"thumbsup\", \"rocket\", \"eyes\", \"heart\", \"tada\")'\n ),\n note_id: z\n .number()\n .optional()\n .describe('Note/comment ID to add the reaction to (if reacting to a specific comment)'),\n },\n execute: async (\n args: {\n resource_type: AwardableResourceType;\n project_id: string;\n resource_iid: number;\n name: string;\n note_id?: number;\n },\n _ctx: ToolContext\n ) => {\n validateAwardEmojiParams(args);\n\n const client = getGitLabClient();\n const resource = buildResourceId(args);\n const result = await client.createAwardEmoji(resource, args.name);\n return JSON.stringify(result, null, 2);\n },\n }),\n\n /**\n * List all reactions on a resource or note\n */\n gitlab_list_award_emoji: tool({\n description: `List all reactions (award emoji) on a merge request, issue, snippet, or a specific note/comment.\n\nExamples:\n- List reactions on MR: resource_type=\"merge_request\", project_id=\"group/project\", resource_iid=123\n- List reactions on a comment: resource_type=\"issue\", project_id=\"group/project\", resource_iid=456, note_id=789`,\n args: {\n resource_type: z.enum(['merge_request', 'issue', 'snippet']).describe('Type of resource'),\n project_id: z.string().describe('Project ID or URL-encoded path'),\n resource_iid: z.number().describe('Internal ID of the merge request, issue, or snippet'),\n note_id: z\n .number()\n .optional()\n .describe('Note/comment ID to list reactions for (if listing for a specific comment)'),\n },\n execute: async (\n args: {\n resource_type: AwardableResourceType;\n project_id: string;\n resource_iid: number;\n note_id?: number;\n },\n _ctx: ToolContext\n ) => {\n validateAwardEmojiParams(args);\n\n const client = getGitLabClient();\n const resource = buildResourceId(args);\n const result = await client.listAwardEmoji(resource);\n return JSON.stringify(result, null, 2);\n },\n }),\n\n /**\n * Remove a reaction from a resource or note\n */\n gitlab_delete_award_emoji: tool({\n description: `Remove a reaction (award emoji) from a merge request, issue, snippet, or note/comment.\n\nYou need the award_id which can be found using gitlab_list_award_emoji.\n\nExamples:\n- Remove reaction from MR: resource_type=\"merge_request\", project_id=\"group/project\", resource_iid=123, award_id=456\n- Remove from comment: resource_type=\"issue\", ..., note_id=789, award_id=456`,\n args: {\n resource_type: z.enum(['merge_request', 'issue', 'snippet']).describe('Type of resource'),\n project_id: z.string().describe('Project ID or URL-encoded path'),\n resource_iid: z.number().describe('Internal ID of the merge request, issue, or snippet'),\n award_id: z.number().describe('ID of the award emoji to remove'),\n note_id: z\n .number()\n .optional()\n .describe('Note/comment ID if removing from a specific comment'),\n },\n execute: async (\n args: {\n resource_type: AwardableResourceType;\n project_id: string;\n resource_iid: number;\n award_id: number;\n note_id?: number;\n },\n _ctx: ToolContext\n ) => {\n validateAwardEmojiParams(args);\n\n const client = getGitLabClient();\n const resource = buildResourceId(args);\n await client.deleteAwardEmoji(resource, args.award_id);\n return JSON.stringify({ success: true, message: 'Award emoji removed' }, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\ninterface OrbitStatusResponse {\n status: string;\n version?: string;\n features?: string[];\n [key: string]: unknown;\n}\n\ninterface OrbitSchemaResponse {\n node_types: Array<{\n name: string;\n domain: string;\n properties: Array<{ name: string; type: string }>;\n }>;\n relationship_types: Array<{\n name: string;\n source_types: string[];\n target_types: string[];\n }>;\n [key: string]: unknown;\n}\n\ninterface OrbitQueryResponse {\n result?: {\n format_version: string;\n query_type: string;\n nodes: Array<{\n type: string;\n id: string;\n [key: string]: unknown;\n }>;\n edges: Array<{\n from: string;\n from_id: string;\n to: string;\n to_id: string;\n type: string;\n }>;\n };\n query_type?: string;\n row_count?: number;\n code?: string;\n message?: string;\n [key: string]: unknown;\n}\n\n/**\n * Tools for interacting with GitLab's Orbit Knowledge Graph API.\n *\n * Orbit provides rich SDLC graph data including relationships between\n * projects, users, MRs, pipelines, issues, and more.\n *\n * Note: Orbit is only available on Premium/Ultimate tiers with the feature flag enabled.\n * All tools gracefully handle unavailability with helpful error messages.\n *\n * @example\n * // Check if Orbit is available\n * gitlab_orbit_status()\n *\n * @example\n * // Get neighbors of a merge request\n * gitlab_orbit_neighbors({ entity_type: \"MergeRequest\", entity_id: 377844873 })\n */\nexport const orbitTools = {\n gitlab_orbit_status: tool({\n description: `Check GitLab Orbit Knowledge Graph API availability and health.\n\nReturns the status of the Orbit API for the connected GitLab instance.\nOrbit is GitLab's Knowledge Graph API that provides rich SDLC graph data.\n\nNote: Orbit is only available on Premium/Ultimate tiers and requires the feature flag to be enabled.\nIf unavailable, returns an error with suggestions for REST API alternatives.`,\n args: {},\n execute: async (_args: Record<string, never>, _ctx: ToolContext) => {\n const client = getGitLabClient();\n\n try {\n const status = await client.fetch<OrbitStatusResponse>('GET', '/orbit/status');\n return JSON.stringify(\n {\n ...status,\n available: true,\n message: 'Orbit Knowledge Graph API is available',\n },\n null,\n 2\n );\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n if (errorMessage.includes('404') || errorMessage.includes('not found')) {\n return JSON.stringify(\n {\n available: false,\n error: 'Orbit API not available',\n reason:\n 'The Orbit Knowledge Graph API is not enabled on this GitLab instance. ' +\n 'Orbit requires GitLab Premium/Ultimate tier and the feature flag to be enabled.',\n alternatives: [\n 'Use REST API endpoints for MRs, issues, pipelines',\n 'Use GraphQL API for complex queries',\n 'Use gitlab_search for finding related entities',\n ],\n },\n null,\n 2\n );\n }\n\n if (errorMessage.includes('403') || errorMessage.includes('forbidden')) {\n return JSON.stringify(\n {\n available: false,\n error: 'Orbit API access forbidden',\n reason:\n 'Your access token does not have permission to use the Orbit API. ' +\n 'This may require specific scopes or Premium/Ultimate tier.',\n alternatives: [\n 'Check token scopes include api or read_api',\n 'Verify your GitLab tier supports Orbit',\n 'Use REST/GraphQL APIs as fallback',\n ],\n },\n null,\n 2\n );\n }\n\n if (errorMessage.includes('502')) {\n return JSON.stringify(\n {\n available: false,\n error: 'Orbit API temporarily unavailable',\n reason: 'The Orbit API returned a 502 error. This may be temporary.',\n suggestion: 'Try again later or use REST/GraphQL APIs as fallback.',\n },\n null,\n 2\n );\n }\n\n return JSON.stringify(\n {\n available: false,\n error: 'Orbit API error',\n message: errorMessage,\n alternatives: ['Use REST/GraphQL APIs as fallback'],\n },\n null,\n 2\n );\n }\n },\n }),\n\n gitlab_orbit_schema: tool({\n description: `Get the Orbit Knowledge Graph schema.\n\nReturns the available node types, relationship types, and their properties.\nUse this to understand what entities and relationships can be queried.\n\nNode type domains include:\n- Core: Project, Group, User\n- Source Code: File, Definition, Commit\n- Code Review: MergeRequest, Diff, Review\n- CI/CD: Pipeline, Job, Deployment\n- Planning: WorkItem (issues, epics, tasks)\n- Security: Vulnerability\n\nNote: Requires Orbit API to be available (Premium/Ultimate tier).`,\n args: {},\n execute: async (_args: Record<string, never>, _ctx: ToolContext) => {\n const client = getGitLabClient();\n\n try {\n const schema = await client.fetch<OrbitSchemaResponse>('GET', '/orbit/schema');\n return JSON.stringify(schema, null, 2);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n if (errorMessage.includes('404') || errorMessage.includes('not found')) {\n return JSON.stringify(\n {\n error: 'Orbit API not available',\n suggestion: 'Use gitlab_orbit_status to check API availability',\n },\n null,\n 2\n );\n }\n\n if (errorMessage.includes('502')) {\n return JSON.stringify(\n {\n error: 'Orbit API temporarily unavailable',\n suggestion:\n 'The Orbit API returned a 502 error. This may be temporary - try again later.',\n },\n null,\n 2\n );\n }\n\n throw error;\n }\n },\n }),\n\n gitlab_orbit_query: tool({\n description: `Execute a query against the Orbit Knowledge Graph.\n\nQuery types:\n- traversal: Walk the graph from a starting node\n- neighbors: Get immediate neighbors of a node\n\nIMPORTANT: The query format uses variable names for node references.\n- \"id\" in node definition is a VARIABLE NAME (alias), not the actual entity ID\n- Actual IDs go in \"filters\" with {\"field\": {\"op\": \"eq\", \"value\": X}} format\n\nExample neighbors query to get a project's connections:\n{\n \"query_type\": \"neighbors\",\n \"node\": {\n \"entity\": \"Project\",\n \"id\": \"p\",\n \"filters\": {\"id\": {\"op\": \"eq\", \"value\": 278964}}\n },\n \"neighbors\": {\"node\": \"p\", \"direction\": \"incoming\"},\n \"aggregations\": [],\n \"path\": {\"type\": \"shortest\", \"from\": \"p\", \"to\": \"p\", \"max_depth\": 1}\n}\n\nExample traversal query:\n{\n \"query_type\": \"traversal\",\n \"node\": {\n \"entity\": \"MergeRequest\",\n \"id\": \"mr\",\n \"filters\": {\"id\": {\"op\": \"eq\", \"value\": 377844873}}\n },\n \"neighbors\": {\"node\": \"mr\", \"direction\": \"both\"},\n \"aggregations\": [],\n \"path\": {\"type\": \"shortest\", \"from\": \"mr\", \"to\": \"mr\", \"max_depth\": 1}\n}\n\nNote: Use gitlab_get_merge_request to get the internal ID from an IID.\nReturns nodes array and edges array with relationship types.`,\n args: {\n // Using a JSON string rather than a structured zod schema because the Orbit query\n // format is still evolving. This allows flexibility as the API changes without\n // requiring schema updates for each iteration.\n query: z\n .string()\n .describe(\n 'JSON string containing the full query object. Must include query_type, node, neighbors, aggregations, and path fields. ' +\n 'See description for format details.'\n ),\n limit: z.number().optional().describe('Maximum number of results (default: 30)'),\n },\n execute: async (args: { query: string; limit?: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n\n let queryObj: unknown;\n try {\n queryObj = JSON.parse(args.query);\n } catch {\n return JSON.stringify(\n {\n error: 'Invalid JSON in query parameter',\n suggestion: 'Ensure the query parameter is valid JSON',\n },\n null,\n 2\n );\n }\n\n const requestBody: Record<string, unknown> = {\n query: queryObj,\n };\n if (args.limit) {\n requestBody.limit = args.limit;\n }\n\n try {\n const result = await client.fetch<OrbitQueryResponse>('POST', '/orbit/query', requestBody);\n\n if (result.code) {\n return JSON.stringify(\n {\n error: 'Query compilation error',\n code: result.code,\n message: result.message,\n suggestion:\n 'Check query structure. Node \"id\" is a variable name, actual IDs go in filters.',\n },\n null,\n 2\n );\n }\n\n return JSON.stringify(result, null, 2);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n if (errorMessage.includes('404') || errorMessage.includes('not found')) {\n return JSON.stringify(\n {\n error: 'Orbit API not available',\n suggestion: 'Use gitlab_orbit_status to check API availability',\n },\n null,\n 2\n );\n }\n\n if (errorMessage.includes('502')) {\n return JSON.stringify(\n {\n error: 'Orbit query failed',\n message:\n 'The Orbit API returned a 502 error. This is a known issue with some entity types (e.g., source_code domain).',\n suggestion: 'Try a different entity type or use REST/GraphQL APIs as fallback.',\n },\n null,\n 2\n );\n }\n\n throw error;\n }\n },\n }),\n\n gitlab_orbit_neighbors: tool({\n description: `Get immediate neighbors of a node in the Orbit Knowledge Graph.\n\nThis is a simplified wrapper that builds the query for you.\nReturns nodes directly connected to the specified node.\n\nCommon use cases:\n- Get all connections to a project (users, groups, pipelines, MRs)\n- Get pipelines for an MR\n- Get files changed in a commit\n- Get deployments from a pipeline\n\nNote: Use GitLab internal numeric IDs (not IIDs).\nExample: For MR !123 in gitlab-org/gitlab, first get the internal ID via gitlab_get_merge_request,\nthen use that ID (e.g., 377844873).`,\n args: {\n entity_type: z\n .string()\n .describe(\n 'Type of the entity (e.g., Project, MergeRequest, User, Pipeline, Commit, WorkItem, Group)'\n ),\n entity_id: z\n .number()\n .describe(\n 'GitLab internal numeric ID (not IID). Get this from REST/GraphQL API responses.'\n ),\n direction: z\n .enum(['incoming', 'outgoing', 'both'])\n .optional()\n .describe('Direction of relationships to traverse (default: both)'),\n limit: z.number().optional().describe('Maximum number of neighbors to return (default: 30)'),\n },\n execute: async (\n args: {\n entity_type: string;\n entity_id: number;\n direction?: 'incoming' | 'outgoing' | 'both';\n limit?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n\n const direction = args.direction || 'both';\n const queryObj = {\n query_type: 'neighbors',\n node: {\n entity: args.entity_type,\n id: 'n',\n filters: {\n id: { op: 'eq', value: args.entity_id },\n },\n },\n neighbors: {\n node: 'n',\n direction: direction,\n },\n aggregations: [],\n path: { type: 'shortest', from: 'n', to: 'n', max_depth: 1 },\n };\n\n const requestBody: Record<string, unknown> = {\n query: queryObj,\n };\n if (args.limit) {\n requestBody.limit = args.limit;\n }\n\n try {\n const result = await client.fetch<OrbitQueryResponse>('POST', '/orbit/query', requestBody);\n\n if (result.code) {\n return JSON.stringify(\n {\n error: 'Query error',\n code: result.code,\n message: result.message,\n entity_type: args.entity_type,\n entity_id: args.entity_id,\n },\n null,\n 2\n );\n }\n\n return JSON.stringify(result, null, 2);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n if (errorMessage.includes('404') || errorMessage.includes('not found')) {\n return JSON.stringify(\n {\n error: 'Orbit API not available',\n entity_type: args.entity_type,\n entity_id: args.entity_id,\n suggestion: 'Use gitlab_orbit_status to check API availability',\n },\n null,\n 2\n );\n }\n\n if (errorMessage.includes('502')) {\n return JSON.stringify(\n {\n error: 'Orbit query failed',\n entity_type: args.entity_type,\n entity_id: args.entity_id,\n message:\n 'The Orbit API returned a 502 error. This is a known issue with some entity types.',\n suggestion: 'Try a different entity type or use REST/GraphQL APIs as fallback.',\n },\n null,\n 2\n );\n }\n\n throw error;\n }\n },\n }),\n};\n","import { type Plugin, type PluginInput } from '@opencode-ai/plugin';\n\n// Import all modular tools\nimport { mergeRequestTools } from './tools/merge-requests.js';\nimport { issueTools } from './tools/issues.js';\nimport { epicTools } from './tools/epics.js';\nimport { pipelineTools } from './tools/pipelines.js';\nimport { repositoryTools } from './tools/repository.js';\nimport { searchTools } from './tools/search.js';\nimport { projectTools } from './tools/projects.js';\nimport { userTools } from './tools/users.js';\nimport { securityTools } from './tools/security.js';\nimport { todoTools } from './tools/todos.js';\nimport { wikiTools } from './tools/wikis.js';\nimport { workItemTools } from './tools/work-items.js';\nimport { discussionsUnifiedTools } from './tools/discussions-unified.js';\nimport { notesUnifiedTools } from './tools/notes-unified.js';\nimport { gitTools } from './tools/git.js';\nimport { auditTools } from './tools/audit.js';\nimport { awardEmojiTools } from './tools/award-emoji.js';\nimport { orbitTools } from './tools/orbit.js';\n\n/**\n * GitLab Tools Plugin for OpenCode\n *\n * Provides tools for interacting with GitLab:\n * - Merge requests: get, list, changes, create, update, commits, pipelines, diffs (paginated), auto-merge\n * - Issues: create, get, list\n * - Epics: get, list, create, update, manage issues\n * - Pipelines: list, get, jobs, logs, retry, failing jobs, CI linter\n * - Repository: get file, commits, diff, branches, tree, create commit, commit comments\n * - Search: projects, issues, MRs, blobs, commits, etc.\n * - Projects: get project, list members\n * - Users: get current user\n * - TODOs: list, mark as done, get count\n * - Security: list vulnerabilities, get vulnerability details\n * - Audit: list project/group/instance audit events\n * - Wikis: get wiki page\n * - Work Items: get, list, create, update, notes\n * - Discussions: unified tools for all resource types (list, get, create/reply, resolve)\n * - Notes: list/get notes (flat view) for MR, issue, epic, snippet\n * - Git: execute safe, read-only git commands in repository\n * - Orbit: Knowledge Graph API (status, schema, query, neighbors)\n */\nexport const gitlabPlugin: Plugin = async (\n _input: PluginInput,\n options?: Record<string, unknown>\n) => {\n if (options?.tools === false) {\n return {\n 'experimental.chat.system.transform': async (_input: any, output: any) => {\n output.system.push(\n `## GitLab Tools via lazy-mcp\\n` +\n `GitLab API tools (MRs, issues, pipelines, security, search, repos, users, todos, work items, ` +\n `discussions, notes, audit, git, award emoji) are served via the \"gitlab\" MCP server through lazy-mcp. ` +\n `Use lazy-mcp_list_commands with server \"gitlab\" to discover and call them.\\n` +\n `DAP tools (agents, flows, memory, skills) are on the \"gitlab-dap\" server instead.`\n );\n },\n };\n }\n\n return {\n tool: {\n ...mergeRequestTools,\n ...issueTools,\n ...epicTools,\n ...pipelineTools,\n ...repositoryTools,\n ...searchTools,\n ...projectTools,\n ...userTools,\n ...securityTools,\n ...todoTools,\n ...wikiTools,\n ...workItemTools,\n ...discussionsUnifiedTools,\n ...notesUnifiedTools,\n ...gitTools,\n ...auditTools,\n ...awardEmojiTools,\n ...orbitTools,\n },\n };\n};\n\nexport default gitlabPlugin;\n"],"mappings":"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","names":["path","path","resolve","path","path","path","path","path","tool","z","tool","tool","z","tool","tool","z","tool","tool","z","tool","tool","z","tool","validationError","tool","z","tool","tool","z","tool","tool","z","tool","tool","z","tool","tool","z","tool","tool","z","tool","tool","z","tool","resolve","tool","z","tool","normalizeBoolean","validationError","tool","z","tool","tool","z","tool","tool","z","tool","tool","z","tool","_input"]}
1
+ {"version":3,"sources":["../src/tools/merge-requests.ts","../src/utils.ts","../src/client/base.ts","../src/client/connection-pagination.ts","../src/client/notes-types.ts","../src/client/discussions-types.ts","../src/client/merge-requests.ts","../src/client/issues.ts","../src/client/work-items.ts","../src/client/pipelines.ts","../src/client/repository.ts","../src/client/search.ts","../src/client/projects.ts","../src/client/users.ts","../src/client/wikis.ts","../src/validation.ts","../src/client/security.ts","../src/client/todos.ts","../src/client/epics.ts","../src/client/snippets.ts","../src/client/discussions.ts","../src/client/audit.ts","../src/client/award-emoji.ts","../src/client/index.ts","../src/tools/issues.ts","../src/tools/epics.ts","../src/tools/pipelines.ts","../src/tools/repository.ts","../src/tools/search.ts","../src/tools/projects.ts","../src/tools/users.ts","../src/tools/security.ts","../src/tools/todos.ts","../src/tools/wikis.ts","../src/tools/work-items.ts","../src/tools/discussions-unified.ts","../src/tools/notes-unified.ts","../src/tools/git.ts","../src/client/git.ts","../src/tools/audit.ts","../src/tools/award-emoji.ts","../src/tools/orbit.ts","../src/tools/index.ts","../src/v2/plugin.ts","../src/v2/tool-adapter.ts","../src/index.ts"],"sourcesContent":["import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const mergeRequestTools = {\n gitlab_get_merge_request: tool({\n description: `Get details of a specific merge request by project and MR IID.\nReturns: title, description, state, author, assignees, reviewers, labels, diff stats, and discussion notes.`,\n args: {\n project_id: z\n .string()\n .describe('The project ID or URL-encoded path (e.g., \"gitlab-org/gitlab\" or \"123\")'),\n mr_iid: z.number().describe('The internal ID of the merge request within the project'),\n include_changes: z\n .boolean()\n .optional()\n .describe('Whether to include the list of changed files (default: false)'),\n },\n execute: async (\n args: { project_id: string; mr_iid: number; include_changes?: boolean },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const mr = await client.getMergeRequest(args.project_id, args.mr_iid, args.include_changes);\n return JSON.stringify(mr, null, 2);\n },\n }),\n\n gitlab_list_merge_requests: tool({\n description: `List merge requests for a project or search globally.\nCan filter by state (opened, closed, merged, all), scope (assigned_to_me, created_by_me), and labels.\n\nIMPORTANT: Response includes pagination info. If nextPage exists, there are more results.\nAlways paginate until you get an empty response or no nextPage to ensure you have all data.`,\n args: {\n project_id: z\n .string()\n .optional()\n .describe('The project ID or path. If not provided, searches globally.'),\n state: z\n .enum(['opened', 'closed', 'merged', 'all'])\n .optional()\n .describe('Filter by MR state (default: opened)'),\n scope: z\n .enum(['assigned_to_me', 'created_by_me', 'all'])\n .optional()\n .describe('Filter by scope'),\n search: z.string().optional().describe('Search MRs by title or description'),\n labels: z.string().optional().describe('Comma-separated list of labels to filter by'),\n limit: z.number().optional().describe('Maximum number of results per page (default: 20)'),\n page: z.number().optional().describe('Page number for pagination (default: 1)'),\n },\n execute: async (\n args: {\n project_id?: string;\n state?: 'opened' | 'closed' | 'merged' | 'all';\n scope?: 'assigned_to_me' | 'created_by_me' | 'all';\n search?: string;\n labels?: string;\n limit?: number;\n page?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const result = await client.listMergeRequests({\n projectId: args.project_id,\n state: args.state,\n scope: args.scope,\n search: args.search,\n labels: args.labels,\n limit: args.limit,\n page: args.page,\n });\n return JSON.stringify(result, null, 2);\n },\n }),\n\n gitlab_get_mr_changes: tool({\n description: `Get the file changes (diff) for a merge request.\nReturns the list of files changed with their diffs.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n },\n execute: async (args: { project_id: string; mr_iid: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const changes = await client.getMrChanges(args.project_id, args.mr_iid);\n return JSON.stringify(changes, null, 2);\n },\n }),\n\n gitlab_create_merge_request: tool({\n description: `Create a new merge request.\nReturns the created merge request with all details.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n source_branch: z.string().describe('The source branch name'),\n target_branch: z.string().describe('The target branch name'),\n title: z.string().describe('The title of the merge request'),\n description: z\n .string()\n .optional()\n .describe('The description of the merge request (supports Markdown)'),\n assignee_ids: z.array(z.number()).optional().describe('Array of user IDs to assign'),\n reviewer_ids: z.array(z.number()).optional().describe('Array of user IDs to review'),\n labels: z.string().optional().describe('Comma-separated list of labels'),\n milestone_id: z.number().optional().describe('The ID of a milestone'),\n remove_source_branch: z\n .boolean()\n .optional()\n .describe('Remove source branch after merge (default: false)'),\n squash: z.boolean().optional().describe('Squash commits on merge (default: false)'),\n allow_collaboration: z\n .boolean()\n .optional()\n .describe('Allow commits from members who can merge to the target branch'),\n target_project_id: z\n .number()\n .optional()\n .describe(\n 'The ID of the target project for cross-project (fork to upstream) merge requests. Defaults to the source project when omitted.'\n ),\n },\n execute: async (\n args: {\n project_id: string;\n source_branch: string;\n target_branch: string;\n title: string;\n description?: string;\n assignee_ids?: number[];\n reviewer_ids?: number[];\n labels?: string;\n milestone_id?: number;\n remove_source_branch?: boolean;\n squash?: boolean;\n allow_collaboration?: boolean;\n target_project_id?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const mr = await client.createMergeRequest(args.project_id, {\n source_branch: args.source_branch,\n target_branch: args.target_branch,\n title: args.title,\n description: args.description,\n assignee_ids: args.assignee_ids,\n reviewer_ids: args.reviewer_ids,\n labels: args.labels,\n milestone_id: args.milestone_id,\n remove_source_branch: args.remove_source_branch,\n squash: args.squash,\n allow_collaboration: args.allow_collaboration,\n target_project_id: args.target_project_id,\n });\n return JSON.stringify(mr, null, 2);\n },\n }),\n\n gitlab_update_merge_request: tool({\n description: `Update an existing merge request.\nCan update title, description, state, assignees, reviewers, labels, and more.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n title: z.string().optional().describe('The new title'),\n description: z.string().optional().describe('The new description (supports Markdown)'),\n state_event: z\n .enum(['close', 'reopen'])\n .optional()\n .describe('Change the state (close or reopen)'),\n assignee_ids: z.array(z.number()).optional().describe('Array of user IDs to assign'),\n reviewer_ids: z.array(z.number()).optional().describe('Array of user IDs to review'),\n labels: z.string().optional().describe('Comma-separated list of labels'),\n milestone_id: z.number().optional().describe('The ID of a milestone'),\n remove_source_branch: z.boolean().optional().describe('Remove source branch after merge'),\n squash: z.boolean().optional().describe('Squash commits on merge'),\n target_branch: z.string().optional().describe('The target branch name'),\n },\n execute: async (\n args: {\n project_id: string;\n mr_iid: number;\n title?: string;\n description?: string;\n state_event?: 'close' | 'reopen';\n assignee_ids?: number[];\n reviewer_ids?: number[];\n labels?: string;\n milestone_id?: number;\n remove_source_branch?: boolean;\n squash?: boolean;\n target_branch?: string;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const mr = await client.updateMergeRequest(args.project_id, args.mr_iid, {\n title: args.title,\n description: args.description,\n state_event: args.state_event,\n assignee_ids: args.assignee_ids,\n reviewer_ids: args.reviewer_ids,\n labels: args.labels,\n milestone_id: args.milestone_id,\n remove_source_branch: args.remove_source_branch,\n squash: args.squash,\n target_branch: args.target_branch,\n });\n return JSON.stringify(mr, null, 2);\n },\n }),\n\n gitlab_get_mr_details: tool({\n description: `Get additional details for a merge request.\n\nDetail types:\n- commits: List all commits in the MR\n- pipelines: List all pipelines that ran for the MR\n\nExamples:\n- Get commits: detail_type=\"commits\", project_id=\"group/project\", mr_iid=123\n- Get pipelines: detail_type=\"pipelines\", project_id=\"group/project\", mr_iid=123`,\n args: {\n detail_type: z.enum(['commits', 'pipelines']).describe('Type of details to fetch'),\n project_id: z.string().describe('The project ID or URL-encoded path'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n },\n execute: async (\n args: { detail_type: 'commits' | 'pipelines'; project_id: string; mr_iid: number },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n\n switch (args.detail_type) {\n case 'commits': {\n const commits = await client.getMrCommits(args.project_id, args.mr_iid);\n return JSON.stringify(commits, null, 2);\n }\n case 'pipelines': {\n const pipelines = await client.getMrPipelines(args.project_id, args.mr_iid);\n return JSON.stringify(pipelines, null, 2);\n }\n }\n },\n }),\n\n gitlab_list_merge_request_diffs: tool({\n description: `List merge request diffs with pagination support.\nReturns the list of file diffs for a merge request, with support for pagination to handle large changesets.\nThis is useful when you need to process diffs in chunks or when the MR has many changed files.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n page: z.number().optional().describe('Page number for pagination (default: 1)'),\n per_page: z.number().optional().describe('Number of diffs per page (default: 20, max: 100)'),\n },\n execute: async (\n args: { project_id: string; mr_iid: number; page?: number; per_page?: number },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const diffs = await client.listMergeRequestDiffs(args.project_id, args.mr_iid, {\n page: args.page,\n per_page: args.per_page,\n });\n return JSON.stringify(diffs, null, 2);\n },\n }),\n\n gitlab_add_mr_reviewer: tool({\n description: `Add a reviewer to a merge request without affecting existing reviewers.\nThis is safer than gitlab_update_merge_request when you only want to add a single reviewer,\nas it preserves all existing reviewers.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n reviewer_id: z.number().describe('The user ID of the reviewer to add'),\n },\n execute: async (\n args: { project_id: string; mr_iid: number; reviewer_id: number },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const mr = await client.addReviewer(args.project_id, args.mr_iid, args.reviewer_id);\n return JSON.stringify(mr, null, 2);\n },\n }),\n\n gitlab_remove_mr_reviewer: tool({\n description: `Remove a reviewer from a merge request without affecting other reviewers.\nThis is safer than gitlab_update_merge_request when you only want to remove a single reviewer,\nas it preserves all other reviewers.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n reviewer_id: z.number().describe('The user ID of the reviewer to remove'),\n },\n execute: async (\n args: { project_id: string; mr_iid: number; reviewer_id: number },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const mr = await client.removeReviewer(args.project_id, args.mr_iid, args.reviewer_id);\n return JSON.stringify(mr, null, 2);\n },\n }),\n\n gitlab_set_mr_auto_merge: tool({\n description: `Enable auto-merge (MWPS - Merge When Pipeline Succeeds) on a merge request.\nUses the GitLab GraphQL API mergeRequestAccept mutation with a merge strategy.\nThe MR will be automatically merged when all required conditions are met.\nRequires the MR to be approved and have a passing pipeline (depending on project settings).\nNote: You must provide the current HEAD SHA of the MR to prevent race conditions.`,\n args: {\n project_id: z.string().describe('The project ID or path (e.g., \"gitlab-org/gitlab\")'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n sha: z\n .string()\n .describe(\n 'The HEAD SHA of the merge request. Get this from the MR details (diff_refs.head_sha or sha field).'\n ),\n strategy: z\n .enum(['MERGE_WHEN_CHECKS_PASS', 'ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS'])\n .optional()\n .describe(\n 'MERGE_WHEN_CHECKS_PASS (default) waits for all checks. ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS adds to merge train.'\n ),\n },\n execute: async (\n args: {\n project_id: string;\n mr_iid: number;\n sha: string;\n strategy?: 'MERGE_WHEN_CHECKS_PASS' | 'ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS';\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const result = await client.setAutoMerge(\n args.project_id,\n args.mr_iid,\n args.sha,\n args.strategy || 'MERGE_WHEN_CHECKS_PASS'\n );\n return JSON.stringify(result, null, 2);\n },\n }),\n\n gitlab_smart_merge_mr: tool({\n description: `Smart merge: merges immediately if checks pass, otherwise enables auto-merge (MWPS).\nThis tool automatically determines the best merge action based on MR state:\n- If MR is mergeable (pipeline passed, approved): merges immediately\n- If pipeline is running or awaiting approval: enables auto-merge\n- Returns detailed context about what happened and why\n\nProvides actionable feedback on failures including MR state, pipeline status, and remediation hints.\nNote: You must provide the current HEAD SHA of the MR to prevent race conditions.`,\n args: {\n project_id: z.string().describe('The project ID or path (e.g., \"gitlab-org/gitlab\")'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n sha: z\n .string()\n .describe(\n 'The HEAD SHA of the merge request. Get this from the MR details (diff_refs.head_sha or sha field).'\n ),\n strategy: z\n .enum(['MERGE_WHEN_CHECKS_PASS', 'ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS'])\n .optional()\n .describe(\n '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.'\n ),\n },\n execute: async (\n args: {\n project_id: string;\n mr_iid: number;\n sha: string;\n strategy?: 'MERGE_WHEN_CHECKS_PASS' | 'ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS';\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const result = await client.smartMerge(args.project_id, args.mr_iid, args.sha, args.strategy);\n return JSON.stringify(result, null, 2);\n },\n }),\n\n gitlab_merge_mr: tool({\n description: `Merge a merge request immediately.\nUse this when you know the MR is ready to merge (pipeline passed, approved, no conflicts).\nFor automatic handling based on MR state, use gitlab_smart_merge_mr instead.\n\nWARNING: If sha is omitted, the merge may succeed against a newer commit than what was reviewed/approved.\nAlways provide sha when you want to ensure you're merging the exact code that was reviewed.`,\n args: {\n project_id: z.string().describe('The project ID or path (e.g., \"gitlab-org/gitlab\")'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n sha: z\n .string()\n .optional()\n .describe(\n 'HEAD SHA to verify before merging. Recommended to prevent merging unreviewed code if new commits were pushed.'\n ),\n squash: z\n .boolean()\n .optional()\n .describe('Whether to squash commits (uses project default if not specified)'),\n should_remove_source_branch: z\n .boolean()\n .optional()\n .describe('Whether to delete source branch after merge'),\n },\n execute: async (\n args: {\n project_id: string;\n mr_iid: number;\n sha?: string;\n squash?: boolean;\n should_remove_source_branch?: boolean;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const result = await client.mergeMergeRequest(args.project_id, args.mr_iid, {\n sha: args.sha,\n squash: args.squash,\n shouldRemoveSourceBranch: args.should_remove_source_branch,\n });\n return JSON.stringify(result, null, 2);\n },\n }),\n\n gitlab_override_requested_changes: tool({\n description: `Bypass (or re-enable) a \"requested changes\" merge block on a merge request.\n\nWhen a reviewer formally requests changes, the merge check \"Change requests must be approved by the requesting user\" blocks the merge (detailed_merge_status: requested_changes). This tool sets the persistent override_requested_changes flag, which is exactly what the \"Bypass\" button in the MR widget does: it downgrades that check from a blocking failure to a non-blocking warning so the MR can be merged.\n\nUse this when the requesting reviewer is unavailable (e.g. on PTO) and their concerns have been addressed. The acting user must have permission to merge to the target branch, otherwise GitLab silently ignores the flag.\n\nNote: this is NOT the same as clearing your own requested-changes review. It overrides another user's request. Set override=false to restore the block.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n override: z\n .boolean()\n .optional()\n .describe('true (default) to bypass requested changes, false to restore the block'),\n },\n execute: async (\n args: { project_id: string; mr_iid: number; override?: boolean },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const result = await client.overrideRequestedChanges(\n args.project_id,\n args.mr_iid,\n args.override ?? true\n );\n return JSON.stringify(result, null, 2);\n },\n }),\n\n gitlab_approve_merge_request: tool({\n description: `Approve a merge request.\nAdds the current user's approval to the merge request.\nRequires at least Developer role on the project.\nReturns the updated approval state including approved_by list.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n sha: z\n .string()\n .optional()\n .describe(\n 'The HEAD SHA of the MR. If provided, the approval will only succeed if this matches the current HEAD, preventing approval of outdated code.'\n ),\n },\n execute: async (\n args: { project_id: string; mr_iid: number; sha?: string },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const result = await client.approveMergeRequest(args.project_id, args.mr_iid, args.sha);\n return JSON.stringify(result, null, 2);\n },\n }),\n\n gitlab_unapprove_merge_request: tool({\n description: `Unapprove (revoke approval from) a merge request.\nRemoves the current user's approval from the merge request.\nOnly the user who approved can unapprove; you cannot remove others' approvals.\nReturns the updated approval state.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n mr_iid: z.number().describe('The internal ID of the merge request'),\n },\n execute: async (args: { project_id: string; mr_iid: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const result = await client.unapproveMergeRequest(args.project_id, args.mr_iid);\n return JSON.stringify(result, null, 2);\n },\n }),\n};\n","import fs from 'fs';\nimport path from 'path';\nimport os from 'os';\nimport { GitLabApiClient } from './client/index.js';\n\n/**\n * Read GitLab token from OpenCode auth.json storage\n */\nfunction readTokenFromAuthStorage(): string | undefined {\n try {\n const authPath = path.join(os.homedir(), '.local', 'share', 'opencode', 'auth.json');\n\n if (!fs.existsSync(authPath)) {\n return undefined;\n }\n\n const authData = JSON.parse(fs.readFileSync(authPath, 'utf-8'));\n const gitlabAuth = authData?.gitlab;\n\n if (!gitlabAuth) {\n return undefined;\n }\n\n // Handle OAuth token structure (type: \"oauth\", access: \"token\")\n if (gitlabAuth.type === 'oauth' && gitlabAuth.access) {\n return gitlabAuth.access;\n }\n\n // Handle API token structure (type: \"api\", key: \"token\")\n if (gitlabAuth.type === 'api' && gitlabAuth.key) {\n return gitlabAuth.key;\n }\n\n // Fallback to direct token field\n return gitlabAuth.token || undefined;\n } catch (error) {\n // Silently fail if we can't read the auth file\n return undefined;\n }\n}\n\n/**\n * Get GitLab API client from environment or auth storage\n */\nexport function getGitLabClient(): GitLabApiClient {\n // First try GITLAB_TOKEN environment variable\n let token = process.env['GITLAB_TOKEN'];\n\n // If not found, try reading from OpenCode auth storage\n if (!token) {\n token = readTokenFromAuthStorage();\n }\n\n if (!token) {\n throw new Error(\n 'GitLab API token not found. Set GITLAB_TOKEN environment variable or configure it in OpenCode auth storage (~/.local/share/opencode/auth.json).'\n );\n }\n\n const instanceUrl = process.env['GITLAB_INSTANCE_URL'] || 'https://gitlab.com';\n return new GitLabApiClient(instanceUrl, token);\n}\n","/**\n * Pagination info from GitLab API response headers\n */\nexport interface PaginationInfo {\n total?: number;\n totalPages?: number;\n page?: number;\n perPage?: number;\n nextPage?: number;\n prevPage?: number;\n}\n\n/**\n * Response with pagination info for list endpoints\n */\nexport interface PaginatedResponse<T> {\n data: T;\n pagination: PaginationInfo;\n}\n\n/**\n * Base GitLab API client with common HTTP methods\n */\nexport class GitLabApiClient {\n protected instanceUrl: string;\n protected token: string;\n\n constructor(instanceUrl: string, token: string) {\n this.instanceUrl = instanceUrl.replace(/\\/$/, ''); // Remove trailing slash\n this.token = token;\n }\n\n protected get headers(): Record<string, string> {\n return {\n Authorization: `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n };\n }\n\n protected encodeProjectId(projectId: string): string {\n // If it contains a slash, URL-encode the entire path\n if (projectId.includes('/')) {\n return encodeURIComponent(projectId);\n }\n return projectId;\n }\n\n /**\n * Core HTTP request used by all REST helpers.\n *\n * Returns the raw `Response` after validating the status code so callers can\n * inspect headers (e.g. for pagination) before parsing the body.\n */\n protected async rawFetch(method: string, path: string, body?: unknown): Promise<Response> {\n const url = `${this.instanceUrl}/api/v4${path}`;\n\n const response = await fetch(url, {\n method,\n headers: this.headers,\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`GitLab API error ${response.status}: ${errorText}`);\n }\n\n return response;\n }\n\n async fetch<T>(method: string, path: string, body?: unknown): Promise<T> {\n const response = await this.rawFetch(method, path, body);\n\n // Handle empty responses\n const text = await response.text();\n if (!text) {\n return {} as T;\n }\n\n return JSON.parse(text) as T;\n }\n\n /**\n * Parse a numeric pagination header, guarding against empty strings.\n *\n * GitLab returns `\"\"` (rather than omitting the header) for `X-Next-Page` and\n * `X-Prev-Page` when there is no next/prev page, and bare `parseInt` without\n * a radix on an empty string yields `NaN`. Treat empty/missing as `undefined`.\n */\n private parsePaginationHeader(response: Response, name: string): number | undefined {\n const raw = response.headers.get(name);\n if (raw == null || raw === '') return undefined;\n const value = parseInt(raw, 10);\n return Number.isNaN(value) ? undefined : value;\n }\n\n /**\n * Pagination info extracted from GitLab API response headers\n */\n protected extractPaginationInfo(response: Response): PaginationInfo {\n return {\n total: this.parsePaginationHeader(response, 'X-Total'),\n totalPages: this.parsePaginationHeader(response, 'X-Total-Pages'),\n page: this.parsePaginationHeader(response, 'X-Page'),\n perPage: this.parsePaginationHeader(response, 'X-Per-Page'),\n nextPage: this.parsePaginationHeader(response, 'X-Next-Page'),\n prevPage: this.parsePaginationHeader(response, 'X-Prev-Page'),\n };\n }\n\n /**\n * Fetch with pagination info from response headers.\n * Use this for list endpoints where knowing if more data exists is important.\n */\n protected async fetchWithPagination<T>(\n method: string,\n path: string,\n body?: unknown\n ): Promise<PaginatedResponse<T>> {\n const response = await this.rawFetch(method, path, body);\n\n const text = await response.text();\n const data = text ? (JSON.parse(text) as T) : ([] as unknown as T);\n const pagination = this.extractPaginationInfo(response);\n\n return { data, pagination };\n }\n\n async fetchText(method: string, path: string): Promise<string> {\n const url = `${this.instanceUrl}/api/v4${path}`;\n\n const response = await fetch(url, {\n method,\n headers: this.headers,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`GitLab API error ${response.status}: ${errorText}`);\n }\n\n return response.text();\n }\n\n /**\n * Execute a GraphQL query or mutation\n * @template T - The expected type of the data field in the GraphQL response\n * @param query - The GraphQL query or mutation string\n * @param variables - Optional variables for the query\n * @returns The data from the GraphQL response\n */\n async fetchGraphQL<T>(query: string, variables?: Record<string, unknown>): Promise<T> {\n const url = `${this.instanceUrl}/api/graphql`;\n\n const response = await fetch(url, {\n method: 'POST',\n headers: this.headers,\n body: JSON.stringify({ query, variables }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`GitLab GraphQL error ${response.status}: ${errorText}`);\n }\n\n const result = await response.json();\n\n // Check for GraphQL errors\n if (result.errors && result.errors.length > 0) {\n const errorMessages = result.errors.map((e: { message: string }) => e.message).join(', ');\n throw new Error(`GraphQL errors: ${errorMessages}`);\n }\n\n return result.data as T;\n }\n}\n","export interface ConnectionPaginationOptions {\n first?: number;\n after?: string;\n last?: number;\n before?: string;\n}\n\nconst DEFAULT_PAGE_SIZE = 20;\nconst MAX_PAGE_SIZE = 100;\n\nfunction normalizePageSize(value: number | undefined): number | undefined {\n if (value === undefined || value === 0) return undefined;\n if (!Number.isFinite(value)) return DEFAULT_PAGE_SIZE;\n return Math.min(Math.max(Math.floor(value), 1), MAX_PAGE_SIZE);\n}\n\nexport function buildConnectionVariables(\n options?: ConnectionPaginationOptions\n): Record<string, unknown> {\n const variables: Record<string, unknown> = {};\n const first = normalizePageSize(options?.first);\n const last = normalizePageSize(options?.last);\n\n if (first !== undefined && last !== undefined) {\n throw new Error(\"Pagination accepts either 'first' or 'last', not both\");\n }\n if (options?.after && last !== undefined) {\n throw new Error(\"Pagination cursor 'after' cannot be combined with 'last'\");\n }\n if (options?.before && first !== undefined) {\n throw new Error(\"Pagination cursor 'before' cannot be combined with 'first'\");\n }\n\n if (first !== undefined) {\n variables.first = first;\n } else if (last !== undefined) {\n variables.last = last;\n } else if (options?.before) {\n variables.last = DEFAULT_PAGE_SIZE;\n } else {\n variables.first = DEFAULT_PAGE_SIZE;\n }\n\n if (options?.after) variables.after = options.after;\n if (options?.before) variables.before = options.before;\n\n return variables;\n}\n","/**\n * Shared types for GraphQL notes pagination\n */\n\nimport {\n buildConnectionVariables,\n type ConnectionPaginationOptions,\n} from './connection-pagination.js';\n\nexport interface NotesPageInfo {\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n startCursor: string | null;\n endCursor: string | null;\n}\n\nexport interface NoteAuthor {\n id: string;\n username: string;\n name: string;\n avatarUrl: string | null;\n}\n\nexport interface NoteNode {\n id: string;\n body: string;\n bodyHtml: string | null;\n createdAt: string;\n updatedAt: string;\n system: boolean;\n internal: boolean;\n resolvable: boolean;\n resolved: boolean;\n resolvedAt: string | null;\n author: NoteAuthor | null;\n url: string | null;\n}\n\nexport interface NotesConnection {\n nodes: NoteNode[];\n pageInfo: NotesPageInfo;\n count?: number;\n}\n\nexport interface NotesResult {\n notes: NotesConnection;\n pageInfo: NotesPageInfo;\n totalCount?: number;\n}\n\nexport interface NotesPaginationOptions extends ConnectionPaginationOptions {}\n\nexport function buildPaginationVariables(\n options?: NotesPaginationOptions\n): Record<string, unknown> {\n return buildConnectionVariables(options);\n}\n\nexport const NOTES_FRAGMENT = `\n fragment NoteFields on Note {\n id\n body\n bodyHtml\n createdAt\n updatedAt\n system\n internal\n resolvable\n resolved\n resolvedAt\n url\n author {\n id\n username\n name\n avatarUrl\n }\n }\n`;\n\nexport const NOTES_CONNECTION_FRAGMENT = `\n fragment NotesConnectionFields on NoteConnection {\n count\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n nodes {\n ...NoteFields\n }\n }\n`;\n","/**\n * Shared types for GraphQL discussions pagination\n */\n\nimport {\n buildConnectionVariables,\n type ConnectionPaginationOptions,\n} from './connection-pagination.js';\n\nexport interface DiscussionsPageInfo {\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n startCursor: string | null;\n endCursor: string | null;\n}\n\nexport interface DiscussionNoteAuthor {\n id: string;\n username: string;\n name: string;\n avatarUrl: string | null;\n}\n\nexport interface DiscussionNote {\n id: string;\n body: string;\n bodyHtml: string | null;\n createdAt: string;\n updatedAt: string;\n system: boolean;\n resolvable: boolean;\n resolved: boolean;\n resolvedAt: string | null;\n author: DiscussionNoteAuthor | null;\n url: string | null;\n}\n\nexport interface DiscussionNode {\n id: string;\n replyId: string;\n createdAt: string;\n resolved: boolean;\n resolvable: boolean;\n resolvedAt: string | null;\n resolvedBy: DiscussionNoteAuthor | null;\n notes: {\n nodes: DiscussionNote[];\n };\n}\n\nexport interface DiscussionsConnection {\n nodes: DiscussionNode[];\n pageInfo: DiscussionsPageInfo;\n}\n\nexport interface DiscussionsResult {\n discussions: DiscussionsConnection;\n}\n\nexport interface DiscussionsPaginationOptions extends ConnectionPaginationOptions {}\n\nexport function buildDiscussionsPaginationVariables(\n options?: DiscussionsPaginationOptions\n): Record<string, unknown> {\n return buildConnectionVariables(options);\n}\n\nexport const DISCUSSION_NOTE_FRAGMENT = `\n fragment DiscussionNoteFields on Note {\n id\n body\n bodyHtml\n createdAt\n updatedAt\n system\n resolvable\n resolved\n resolvedAt\n url\n author {\n id\n username\n name\n avatarUrl\n }\n }\n`;\n\nexport const DISCUSSION_FRAGMENT = `\n fragment DiscussionFields on Discussion {\n id\n replyId\n createdAt\n resolved\n resolvable\n resolvedAt\n resolvedBy {\n id\n username\n name\n avatarUrl\n }\n notes {\n nodes {\n ...DiscussionNoteFields\n }\n }\n }\n`;\n\nexport const DISCUSSIONS_CONNECTION_FRAGMENT = `\n fragment DiscussionsConnectionFields on DiscussionConnection {\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n nodes {\n ...DiscussionFields\n }\n }\n`;\n","import { GitLabApiClient, PaginatedResponse } from './base.js';\nimport {\n NotesResult,\n NotesConnection,\n NotesPaginationOptions,\n NOTES_FRAGMENT,\n NOTES_CONNECTION_FRAGMENT,\n buildPaginationVariables,\n} from './notes-types.js';\nimport {\n DiscussionsResult,\n DiscussionsConnection,\n DiscussionsPaginationOptions,\n DISCUSSION_NOTE_FRAGMENT,\n DISCUSSION_FRAGMENT,\n DISCUSSIONS_CONNECTION_FRAGMENT,\n buildDiscussionsPaginationVariables,\n} from './discussions-types.js';\n\nconst LIST_MR_NOTES_QUERY = `\n ${NOTES_FRAGMENT}\n ${NOTES_CONNECTION_FRAGMENT}\n query listMrNotes(\n $projectPath: ID!\n $mrIid: String!\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n project(fullPath: $projectPath) {\n mergeRequest(iid: $mrIid) {\n notes(\n first: $first\n after: $after\n last: $last\n before: $before\n ) {\n ...NotesConnectionFields\n }\n }\n }\n }\n`;\n\nconst LIST_MR_DISCUSSIONS_QUERY = `\n ${DISCUSSION_NOTE_FRAGMENT}\n ${DISCUSSION_FRAGMENT}\n ${DISCUSSIONS_CONNECTION_FRAGMENT}\n query listMrDiscussions(\n $projectPath: ID!\n $mrIid: String!\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n project(fullPath: $projectPath) {\n mergeRequest(iid: $mrIid) {\n discussions(\n first: $first\n after: $after\n last: $last\n before: $before\n ) {\n ...DiscussionsConnectionFields\n }\n }\n }\n }\n`;\n\nconst SET_AUTO_MERGE_MUTATION = `\n mutation setAutoMerge(\n $projectPath: ID!\n $iid: String!\n $sha: String!\n $strategy: MergeStrategyEnum\n ) {\n mergeRequestAccept(\n input: {\n projectPath: $projectPath\n iid: $iid\n sha: $sha\n strategy: $strategy\n }\n ) {\n mergeRequest {\n id\n iid\n title\n autoMergeEnabled\n autoMergeStrategy\n }\n errors\n }\n }\n`;\n\nconst OVERRIDE_REQUESTED_CHANGES_MUTATION = `\n mutation overrideRequestedChanges(\n $projectPath: ID!\n $iid: String!\n $override: Boolean\n ) {\n mergeRequestUpdate(\n input: {\n projectPath: $projectPath\n iid: $iid\n overrideRequestedChanges: $override\n }\n ) {\n mergeRequest {\n id\n iid\n title\n detailedMergeStatus\n }\n errors\n }\n }\n`;\n\nconst RESOLVE_DISCUSSION_MUTATION = `\n mutation resolveDiscussion($discussionId: DiscussionID!, $resolve: Boolean!) {\n discussionToggleResolve(input: { id: $discussionId, resolve: $resolve }) {\n discussion {\n id\n resolved\n resolvedAt\n resolvedBy {\n id\n username\n name\n }\n }\n errors\n }\n }\n`;\n\n/**\n * GitLab API client for Merge Request operations\n */\nexport class MergeRequestsClient extends GitLabApiClient {\n async getMergeRequest(projectId: string, mrIid: number, includeChanges?: boolean) {\n const encodedProject = this.encodeProjectId(projectId);\n let path = `/projects/${encodedProject}/merge_requests/${mrIid}`;\n if (includeChanges) {\n path += '?include_diverged_commits_count=true';\n }\n return this.fetch<Record<string, unknown>>('GET', path);\n }\n\n async listMergeRequests(options: {\n projectId?: string;\n state?: string;\n scope?: string;\n search?: string;\n labels?: string;\n limit?: number;\n page?: number;\n }): Promise<PaginatedResponse<Record<string, unknown>[]>> {\n const params = new URLSearchParams();\n params.set('per_page', String(options.limit || 20));\n if (options.page) params.set('page', String(options.page));\n\n if (options.state) params.set('state', options.state);\n if (options.scope) params.set('scope', options.scope);\n if (options.search) params.set('search', options.search);\n if (options.labels) params.set('labels', options.labels);\n\n let path: string;\n if (options.projectId) {\n const encodedProject = this.encodeProjectId(options.projectId);\n path = `/projects/${encodedProject}/merge_requests?${params}`;\n } else {\n path = `/merge_requests?${params}`;\n }\n\n return this.fetchWithPagination<Record<string, unknown>[]>('GET', path);\n }\n\n async getMrChanges(projectId: string, mrIid: number) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/merge_requests/${mrIid}/changes`\n );\n }\n\n /**\n * List notes on a merge request using GraphQL API with pagination support\n */\n async listMrNotes(\n projectId: string,\n mrIid: number,\n options?: NotesPaginationOptions\n ): Promise<NotesResult> {\n const variables: Record<string, unknown> = {\n projectPath: projectId,\n mrIid: String(mrIid),\n ...buildPaginationVariables(options),\n };\n\n const result = await this.fetchGraphQL<{\n project: {\n mergeRequest: {\n notes: NotesConnection;\n };\n };\n }>(LIST_MR_NOTES_QUERY, variables);\n\n const notes = result.project?.mergeRequest?.notes;\n if (!notes) {\n throw new Error('Merge request not found or access denied');\n }\n\n return {\n notes,\n pageInfo: notes.pageInfo,\n totalCount: notes.count,\n };\n }\n\n /**\n * List discussions on a merge request using GraphQL API with pagination support\n */\n async listMrDiscussions(\n projectId: string,\n mrIid: number,\n options?: DiscussionsPaginationOptions\n ): Promise<DiscussionsResult> {\n const variables: Record<string, unknown> = {\n projectPath: projectId,\n mrIid: String(mrIid),\n ...buildDiscussionsPaginationVariables(options),\n };\n\n const result = await this.fetchGraphQL<{\n project: {\n mergeRequest: {\n discussions: DiscussionsConnection;\n };\n };\n }>(LIST_MR_DISCUSSIONS_QUERY, variables);\n\n const discussions = result.project?.mergeRequest?.discussions;\n if (!discussions) {\n throw new Error('Merge request not found or access denied');\n }\n\n return { discussions };\n }\n\n async getMrDiscussion(projectId: string, mrIid: number, discussionId: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/merge_requests/${mrIid}/discussions/${discussionId}`\n );\n }\n\n async resolveMrDiscussion(projectId: string, mrIid: number, discussionId: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/projects/${encodedProject}/merge_requests/${mrIid}/discussions/${discussionId}`,\n { resolved: true }\n );\n }\n\n async unresolveMrDiscussion(projectId: string, mrIid: number, discussionId: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/projects/${encodedProject}/merge_requests/${mrIid}/discussions/${discussionId}`,\n { resolved: false }\n );\n }\n\n /**\n * Resolve or unresolve a discussion using GraphQL API.\n * This works for all discussions including outdated ones (resolved: null)\n * which the REST API cannot handle.\n *\n * @param discussionId - The discussion ID (can be short ID or full gid://gitlab/Discussion/ID format)\n * @param resolve - Whether to resolve (true) or unresolve (false) the discussion\n */\n async toggleDiscussionResolved(discussionId: string, resolve: boolean) {\n const gid = discussionId.startsWith('gid://')\n ? discussionId\n : `gid://gitlab/Discussion/${discussionId}`;\n\n const result = await this.fetchGraphQL<{\n discussionToggleResolve: {\n discussion: {\n id: string;\n resolved: boolean;\n resolvedAt: string | null;\n resolvedBy: {\n id: string;\n username: string;\n name: string;\n } | null;\n } | null;\n errors: string[];\n };\n }>(RESOLVE_DISCUSSION_MUTATION, {\n discussionId: gid,\n resolve,\n });\n\n if (result.discussionToggleResolve.errors.length > 0) {\n throw new Error(\n `Failed to ${resolve ? 'resolve' : 'unresolve'} discussion: ${result.discussionToggleResolve.errors.join(', ')}`\n );\n }\n\n if (!result.discussionToggleResolve.discussion) {\n throw new Error(\n `Failed to ${resolve ? 'resolve' : 'unresolve'} discussion: No discussion returned`\n );\n }\n\n return result.discussionToggleResolve.discussion;\n }\n\n async createMrDiscussion(\n projectId: string,\n mrIid: number,\n body: string,\n position?: {\n base_sha: string;\n start_sha: string;\n head_sha: string;\n position_type: 'text' | 'image';\n new_path?: string;\n old_path?: string;\n new_line?: number;\n old_line?: number;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const requestBody: Record<string, unknown> = { body };\n if (position) {\n requestBody.position = position;\n }\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/merge_requests/${mrIid}/discussions`,\n requestBody\n );\n }\n\n async createMrNote(projectId: string, mrIid: number, body: string, discussionId?: string) {\n const encodedProject = this.encodeProjectId(projectId);\n if (discussionId) {\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/merge_requests/${mrIid}/discussions/${discussionId}/notes`,\n { body }\n );\n }\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/merge_requests/${mrIid}/notes`,\n { body }\n );\n }\n\n async updateMrNote(projectId: string, mrIid: number, noteId: number, body: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/projects/${encodedProject}/merge_requests/${mrIid}/notes/${noteId}`,\n { body }\n );\n }\n\n async createMergeRequest(\n projectId: string,\n options: {\n source_branch: string;\n target_branch: string;\n title: string;\n description?: string;\n assignee_ids?: number[];\n reviewer_ids?: number[];\n labels?: string;\n milestone_id?: number;\n remove_source_branch?: boolean;\n squash?: boolean;\n allow_collaboration?: boolean;\n target_project_id?: number;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/merge_requests`,\n options\n );\n }\n\n async updateMergeRequest(\n projectId: string,\n mrIid: number,\n options: {\n title?: string;\n description?: string;\n state_event?: string;\n assignee_ids?: number[];\n reviewer_ids?: number[];\n labels?: string;\n milestone_id?: number;\n remove_source_branch?: boolean;\n squash?: boolean;\n target_branch?: string;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/projects/${encodedProject}/merge_requests/${mrIid}`,\n options\n );\n }\n\n async getMrCommits(projectId: string, mrIid: number) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/merge_requests/${mrIid}/commits`\n );\n }\n\n async getMrPipelines(projectId: string, mrIid: number) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/merge_requests/${mrIid}/pipelines`\n );\n }\n\n /**\n * Add a reviewer to a merge request without affecting existing reviewers\n */\n async addReviewer(projectId: string, mrIid: number, reviewerId: number) {\n const mr = await this.getMergeRequest(projectId, mrIid);\n const currentReviewers = (mr.reviewers as Array<{ id: number }>) || [];\n const currentReviewerIds = currentReviewers.map((r) => r.id);\n\n if (currentReviewerIds.includes(reviewerId)) {\n return mr;\n }\n\n const newReviewerIds = [...currentReviewerIds, reviewerId];\n return this.updateMergeRequest(projectId, mrIid, { reviewer_ids: newReviewerIds });\n }\n\n /**\n * Remove a reviewer from a merge request without affecting other reviewers\n */\n async removeReviewer(projectId: string, mrIid: number, reviewerId: number) {\n const mr = await this.getMergeRequest(projectId, mrIid);\n const currentReviewers = (mr.reviewers as Array<{ id: number }>) || [];\n const currentReviewerIds = currentReviewers.map((r) => r.id);\n\n if (!currentReviewerIds.includes(reviewerId)) {\n return mr;\n }\n\n const newReviewerIds = currentReviewerIds.filter((id) => id !== reviewerId);\n return this.updateMergeRequest(projectId, mrIid, { reviewer_ids: newReviewerIds });\n }\n\n async listMergeRequestDiffs(\n projectId: string,\n mrIid: number,\n options: {\n page?: number;\n per_page?: number;\n } = {}\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const params = new URLSearchParams();\n\n if (options.page) params.append('page', options.page.toString());\n if (options.per_page) params.append('per_page', options.per_page.toString());\n\n const query = params.toString();\n const path = `/projects/${encodedProject}/merge_requests/${mrIid}/diffs${query ? `?${query}` : ''}`;\n\n return this.fetch<Record<string, unknown>[]>('GET', path);\n }\n\n /**\n * Set auto-merge (MWPS) on a merge request using GraphQL API\n * Uses the mergeRequestAccept mutation with a merge strategy\n */\n async setAutoMerge(\n projectId: string,\n mrIid: number,\n sha: string,\n strategy:\n | 'MERGE_WHEN_CHECKS_PASS'\n | 'ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS' = 'MERGE_WHEN_CHECKS_PASS',\n retries = 3\n ) {\n // GitLab rejects the mergeRequestAccept mutation while a merge request's\n // mergeability is still being (re)computed, returning a transient error\n // such as \"mergeability is being checked\" or \"cannot be merged\". This is\n // not a real failure: the check settles within a second or two. Retry a\n // few times with backoff on those transient errors before giving up.\n let lastError: Error | null = null;\n for (let attempt = 0; attempt <= retries; attempt++) {\n const result = await this.fetchGraphQL<{\n mergeRequestAccept: {\n mergeRequest: {\n id: string;\n iid: string;\n title: string;\n autoMergeEnabled: boolean;\n autoMergeStrategy: string;\n } | null;\n errors: string[];\n };\n }>(SET_AUTO_MERGE_MUTATION, {\n projectPath: projectId,\n iid: String(mrIid),\n sha: sha,\n strategy: strategy,\n });\n\n if (result.mergeRequestAccept.errors.length > 0) {\n const message = result.mergeRequestAccept.errors.join(', ');\n lastError = new Error(`Failed to set auto-merge: ${message}`);\n if (attempt < retries && MergeRequestsClient.isTransientMergeError(message)) {\n await MergeRequestsClient.delay(750 * (attempt + 1));\n continue;\n }\n throw lastError;\n }\n\n if (!result.mergeRequestAccept.mergeRequest) {\n lastError = new Error('Failed to set auto-merge: No merge request returned');\n if (attempt < retries) {\n await MergeRequestsClient.delay(750 * (attempt + 1));\n continue;\n }\n throw lastError;\n }\n\n return result.mergeRequestAccept.mergeRequest;\n }\n\n // Unreachable in practice (the loop either returns or throws), but keeps\n // the type checker happy and surfaces the last transient error if it ever\n // falls through.\n throw lastError ?? new Error('Failed to set auto-merge: exhausted retries');\n }\n\n /**\n * True for GitLab merge errors that are transient because mergeability is\n * still being (re)computed. Such errors clear on their own within a second\n * or two, so callers should retry rather than treat them as real failures.\n */\n private static isTransientMergeError(message: string): boolean {\n const m = message.toLowerCase();\n return (\n m.includes('being checked') ||\n m.includes('being recomputed') ||\n m.includes('cannot be merged') ||\n m.includes('not mergeable') ||\n m.includes('merge failed') ||\n m.includes('try again')\n );\n }\n\n /** Small awaitable delay helper (ms). */\n private static delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n\n /**\n * Override (or clear an override of) requested changes on a merge request.\n *\n * When a reviewer formally requests changes, the \"Change requests must be\n * approved by the requesting user\" merge check blocks the merge. Setting the\n * persistent `override_requested_changes` flag downgrades that check from a\n * blocking failure to a non-blocking warning, which is what the \"Bypass\"\n * button in the merge request widget does. This is distinct from\n * `mergeRequestDestroyRequestedChanges`, which only clears the calling user's\n * own requested-changes review.\n *\n * Requires permission to merge to the target branch (otherwise GitLab\n * silently ignores the flag).\n *\n * @param projectId Project ID or URL-encoded path\n * @param mrIid Internal ID of the merge request\n * @param override true to bypass requested changes, false to re-enable the block\n * @returns The updated merge request (id, iid, title, detailedMergeStatus)\n */\n async overrideRequestedChanges(projectId: string, mrIid: number, override: boolean = true) {\n const result = await this.fetchGraphQL<{\n mergeRequestUpdate: {\n mergeRequest: {\n id: string;\n iid: string;\n title: string;\n detailedMergeStatus: string;\n } | null;\n errors: string[];\n };\n }>(OVERRIDE_REQUESTED_CHANGES_MUTATION, {\n projectPath: projectId,\n iid: String(mrIid),\n override,\n });\n\n if (result.mergeRequestUpdate.errors.length > 0) {\n throw new Error(\n `Failed to override requested changes: ${result.mergeRequestUpdate.errors.join(', ')}`\n );\n }\n\n if (!result.mergeRequestUpdate.mergeRequest) {\n throw new Error('Failed to override requested changes: No merge request returned');\n }\n\n return result.mergeRequestUpdate.mergeRequest;\n }\n\n /**\n * Approve a merge request\n * Requires at least Developer role on the project\n */\n async approveMergeRequest(projectId: string, mrIid: number, sha?: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/merge_requests/${mrIid}/approve`,\n sha ? { sha } : undefined\n );\n }\n\n /**\n * Unapprove (revoke approval from) a merge request\n * Only removes the current user's approval\n */\n async unapproveMergeRequest(projectId: string, mrIid: number) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/merge_requests/${mrIid}/unapprove`\n );\n }\n\n /**\n * Merge a merge request immediately\n * Requires the MR to be in a mergeable state (approved, pipeline passed, no conflicts)\n */\n async mergeMergeRequest(\n projectId: string,\n mrIid: number,\n options?: {\n sha?: string;\n squash?: boolean;\n shouldRemoveSourceBranch?: boolean;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const body: Record<string, unknown> = {};\n if (options?.sha) body.sha = options.sha;\n if (options?.squash !== undefined) body.squash = options.squash;\n if (options?.shouldRemoveSourceBranch !== undefined) {\n body.should_remove_source_branch = options.shouldRemoveSourceBranch;\n }\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/projects/${encodedProject}/merge_requests/${mrIid}/merge`,\n Object.keys(body).length > 0 ? body : undefined\n );\n }\n\n /**\n * Resolve the auto-merge strategy for a project.\n *\n * When the caller does not specify a strategy, projects with merge trains\n * enabled require ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS; otherwise\n * MERGE_WHEN_CHECKS_PASS is correct. Using the wrong one causes auto-merge to\n * fail with an opaque \"The merge failed\" error. Falls back to\n * MERGE_WHEN_CHECKS_PASS if the project setting cannot be read.\n *\n * Returns both the chosen strategy and how it was arrived at, so the caller\n * can thread a breadcrumb into its result. A bare fallback would collapse a\n * 401, a network timeout, and a genuine 404 all into a silent MWPS default,\n * reintroducing the opaque \"The merge failed\" this behaviour exists to\n * eliminate; `detection` makes that observable without changing the fallback.\n */\n private async resolveAutoMergeStrategy(projectId: string): Promise<{\n strategy: 'MERGE_WHEN_CHECKS_PASS' | 'ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS';\n detection: 'merge_trains_enabled' | 'merge_trains_disabled' | 'defaulted_after_error';\n reason?: string;\n }> {\n try {\n const encodedProject = this.encodeProjectId(projectId);\n const project = await this.fetch<{ merge_trains_enabled?: boolean }>(\n 'GET',\n `/projects/${encodedProject}`\n );\n return project.merge_trains_enabled\n ? {\n strategy: 'ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS',\n detection: 'merge_trains_enabled',\n }\n : { strategy: 'MERGE_WHEN_CHECKS_PASS', detection: 'merge_trains_disabled' };\n } catch (error) {\n return {\n strategy: 'MERGE_WHEN_CHECKS_PASS',\n detection: 'defaulted_after_error',\n reason: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n /**\n * Smart merge: merge immediately if checks pass, otherwise set auto-merge\n * Returns detailed context about what happened.\n *\n * If `strategy` is omitted, it is auto-detected from the project's merge\n * train settings (merge-train projects need ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS).\n */\n async smartMerge(\n projectId: string,\n mrIid: number,\n sha: string,\n strategy?: 'MERGE_WHEN_CHECKS_PASS' | 'ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS'\n ): Promise<{\n action: 'merged' | 'auto_merge_enabled' | 'failed';\n message: string;\n mergeRequest?: Record<string, unknown>;\n context?: {\n state: string;\n detailedMergeStatus: string;\n pipelineStatus: string | null;\n hasConflicts: boolean;\n hasAnyApproval: boolean;\n strategyDetection?: string;\n };\n }> {\n type SmartMergeMr = {\n state: string;\n detailed_merge_status: string;\n has_conflicts: boolean;\n sha: string;\n head_pipeline?: { status: string };\n approved_by?: unknown[];\n };\n\n let mr = (await this.getMergeRequest(projectId, mrIid)) as SmartMergeMr;\n\n // GitLab reports detailed_merge_status = 'checking' while it (re)computes\n // mergeability, which happens right after a push or when the MR is first\n // opened. Firing the auto-merge mutation during this window fails\n // transiently even though the MR is fine. Wait for the status to settle\n // into a terminal value before deciding how to merge, so we route to a\n // direct merge / auto-merge / clear failure based on the REAL state.\n if (mr.detailed_merge_status === 'checking') {\n for (let attempt = 0; attempt < 5 && mr.detailed_merge_status === 'checking'; attempt++) {\n await MergeRequestsClient.delay(1000 * (attempt + 1));\n mr = (await this.getMergeRequest(projectId, mrIid)) as SmartMergeMr;\n }\n }\n\n const context: {\n state: string;\n detailedMergeStatus: string;\n pipelineStatus: string | null;\n hasConflicts: boolean;\n hasAnyApproval: boolean;\n strategyDetection?: string;\n } = {\n state: mr.state,\n detailedMergeStatus: mr.detailed_merge_status,\n pipelineStatus: mr.head_pipeline?.status || null,\n hasConflicts: mr.has_conflicts,\n hasAnyApproval: (mr.approved_by?.length || 0) > 0,\n };\n\n if (mr.state !== 'opened') {\n return {\n action: 'failed',\n message: `MR is not open (state: ${mr.state})`,\n context,\n };\n }\n\n if (mr.has_conflicts) {\n return {\n action: 'failed',\n message: 'MR has merge conflicts that must be resolved',\n context,\n };\n }\n\n if (mr.detailed_merge_status === 'mergeable') {\n try {\n const result = await this.mergeMergeRequest(projectId, mrIid, { sha: mr.sha });\n return {\n action: 'merged',\n message: 'MR merged successfully',\n mergeRequest: result,\n context,\n };\n } catch (error) {\n return {\n action: 'failed',\n message: `Direct merge failed: ${error instanceof Error ? error.message : String(error)}`,\n context,\n };\n }\n }\n\n // 'checking' is intentionally NOT here: it is resolved to a terminal\n // status above before we get this far. Auto-merge is only appropriate when\n // the merge is genuinely pending (pipeline running or approval outstanding).\n const autoMergeStatuses = ['ci_still_running', 'not_approved'];\n if (autoMergeStatuses.includes(mr.detailed_merge_status)) {\n let resolvedStrategy: 'MERGE_WHEN_CHECKS_PASS' | 'ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS';\n if (strategy) {\n resolvedStrategy = strategy;\n context.strategyDetection = `explicit: ${strategy}`;\n } else {\n const detected = await this.resolveAutoMergeStrategy(projectId);\n resolvedStrategy = detected.strategy;\n context.strategyDetection =\n detected.detection === 'defaulted_after_error'\n ? `failed, defaulted to MERGE_WHEN_CHECKS_PASS${detected.reason ? ` (${detected.reason})` : ''}`\n : `auto-detected (${detected.detection}): ${detected.strategy}`;\n }\n try {\n const result = await this.setAutoMerge(projectId, mrIid, sha, resolvedStrategy);\n const autoMergeMessages: Record<string, string> = {\n ci_still_running: 'pipeline passes',\n not_approved: 'approved',\n };\n return {\n action: 'auto_merge_enabled',\n message: `Auto-merge enabled (${resolvedStrategy}). MR will merge when ${autoMergeMessages[mr.detailed_merge_status]}.`,\n mergeRequest: result as unknown as Record<string, unknown>,\n context,\n };\n } catch (error) {\n return {\n action: 'failed',\n message: `Failed to enable auto-merge: ${error instanceof Error ? error.message : String(error)}. MR status: ${mr.detailed_merge_status}, pipeline: ${mr.head_pipeline?.status || 'none'}`,\n context,\n };\n }\n }\n\n const statusHints: Record<string, string> = {\n discussions_not_resolved: 'Resolve all open discussion threads before merging.',\n draft_status: 'MR is in draft. Mark as ready before merging.',\n need_rebase: 'Source branch needs to be rebased onto the target branch.',\n requested_changes: 'A reviewer requested changes that must be addressed.',\n policies_denied: 'Merge is blocked by a security/compliance policy.',\n external_status_checks: 'External status checks must pass before merging.',\n jira_association_missing: 'MR must be linked to a Jira issue.',\n conflict: 'MR has merge conflicts that must be resolved.',\n };\n\n return {\n action: 'failed',\n message: statusHints[mr.detailed_merge_status] ?? `Cannot merge: ${mr.detailed_merge_status}`,\n context,\n };\n }\n}\n","import { GitLabApiClient, PaginatedResponse } from './base.js';\nimport {\n NotesResult,\n NotesConnection,\n NotesPaginationOptions,\n NOTES_FRAGMENT,\n NOTES_CONNECTION_FRAGMENT,\n buildPaginationVariables,\n} from './notes-types.js';\nimport {\n DiscussionsResult,\n DiscussionsConnection,\n DiscussionsPaginationOptions,\n DISCUSSION_NOTE_FRAGMENT,\n DISCUSSION_FRAGMENT,\n DISCUSSIONS_CONNECTION_FRAGMENT,\n buildDiscussionsPaginationVariables,\n} from './discussions-types.js';\n\nconst LIST_ISSUE_NOTES_QUERY = `\n ${NOTES_FRAGMENT}\n ${NOTES_CONNECTION_FRAGMENT}\n query listIssueNotes(\n $projectPath: ID!\n $issueIid: String!\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n project(fullPath: $projectPath) {\n issue(iid: $issueIid) {\n notes(\n first: $first\n after: $after\n last: $last\n before: $before\n ) {\n ...NotesConnectionFields\n }\n }\n }\n }\n`;\n\nconst LIST_ISSUE_DISCUSSIONS_QUERY = `\n ${DISCUSSION_NOTE_FRAGMENT}\n ${DISCUSSION_FRAGMENT}\n ${DISCUSSIONS_CONNECTION_FRAGMENT}\n query listIssueDiscussions(\n $projectPath: ID!\n $issueIid: String!\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n project(fullPath: $projectPath) {\n issue(iid: $issueIid) {\n discussions(\n first: $first\n after: $after\n last: $last\n before: $before\n ) {\n ...DiscussionsConnectionFields\n }\n }\n }\n }\n`;\n\n/**\n * GitLab API client for Issue operations\n */\nexport class IssuesClient extends GitLabApiClient {\n async createIssue(\n projectId: string,\n title: string,\n options?: {\n description?: string;\n assignee_ids?: number[];\n milestone_id?: number;\n labels?: string;\n due_date?: string;\n confidential?: boolean;\n weight?: number;\n epic_id?: number;\n issue_type?: string;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const body: Record<string, unknown> = {\n title,\n ...Object.fromEntries(\n Object.entries(options || {}).filter(([_, value]) => value !== undefined)\n ),\n };\n\n return this.fetch<Record<string, unknown>>('POST', `/projects/${encodedProject}/issues`, body);\n }\n\n async getIssue(projectId: string, issueIid: number) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/issues/${issueIid}`\n );\n }\n\n async listIssues(options: {\n projectId?: string;\n state?: string;\n scope?: string;\n search?: string;\n labels?: string;\n milestone?: string;\n limit?: number;\n page?: number;\n }): Promise<PaginatedResponse<Record<string, unknown>[]>> {\n const params = new URLSearchParams();\n params.set('per_page', String(options.limit || 20));\n if (options.page) params.set('page', String(options.page));\n\n if (options.state) params.set('state', options.state);\n if (options.scope) params.set('scope', options.scope);\n if (options.search) params.set('search', options.search);\n if (options.labels) params.set('labels', options.labels);\n if (options.milestone) params.set('milestone', options.milestone);\n\n let path: string;\n if (options.projectId) {\n const encodedProject = this.encodeProjectId(options.projectId);\n path = `/projects/${encodedProject}/issues?${params}`;\n } else {\n path = `/issues?${params}`;\n }\n\n return this.fetchWithPagination<Record<string, unknown>[]>('GET', path);\n }\n\n /**\n * List notes on an issue using GraphQL API with pagination support\n */\n async listIssueNotes(\n projectId: string,\n issueIid: number,\n options?: NotesPaginationOptions\n ): Promise<NotesResult> {\n const variables: Record<string, unknown> = {\n projectPath: projectId,\n issueIid: String(issueIid),\n ...buildPaginationVariables(options),\n };\n\n const result = await this.fetchGraphQL<{\n project: {\n issue: {\n notes: NotesConnection;\n };\n };\n }>(LIST_ISSUE_NOTES_QUERY, variables);\n\n const notes = result.project?.issue?.notes;\n if (!notes) {\n throw new Error('Issue not found or access denied');\n }\n\n return {\n notes,\n pageInfo: notes.pageInfo,\n totalCount: notes.count,\n };\n }\n\n /**\n * List discussions on an issue using GraphQL API with pagination support\n */\n async listIssueDiscussions(\n projectId: string,\n issueIid: number,\n options?: DiscussionsPaginationOptions\n ): Promise<DiscussionsResult> {\n const variables: Record<string, unknown> = {\n projectPath: projectId,\n issueIid: String(issueIid),\n ...buildDiscussionsPaginationVariables(options),\n };\n\n const result = await this.fetchGraphQL<{\n project: {\n issue: {\n discussions: DiscussionsConnection;\n };\n };\n }>(LIST_ISSUE_DISCUSSIONS_QUERY, variables);\n\n const discussions = result.project?.issue?.discussions;\n if (!discussions) {\n throw new Error('Issue not found or access denied');\n }\n\n return { discussions };\n }\n\n async getIssueDiscussion(projectId: string, issueIid: number, discussionId: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/issues/${issueIid}/discussions/${discussionId}`\n );\n }\n\n async createIssueNote(projectId: string, issueIid: number, body: string, discussionId?: string) {\n const encodedProject = this.encodeProjectId(projectId);\n if (discussionId) {\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/issues/${issueIid}/discussions/${discussionId}/notes`,\n { body }\n );\n }\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/issues/${issueIid}/notes`,\n { body }\n );\n }\n\n async resolveIssueDiscussion(projectId: string, issueIid: number, discussionId: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/projects/${encodedProject}/issues/${issueIid}/discussions/${discussionId}`,\n { resolved: true }\n );\n }\n\n async unresolveIssueDiscussion(projectId: string, issueIid: number, discussionId: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/projects/${encodedProject}/issues/${issueIid}/discussions/${discussionId}`,\n { resolved: false }\n );\n }\n\n async getIssueNote(projectId: string, issueIid: number, noteId: number) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/issues/${issueIid}/notes/${noteId}`\n );\n }\n\n async updateIssueNote(projectId: string, issueIid: number, noteId: number, body: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/projects/${encodedProject}/issues/${issueIid}/notes/${noteId}`,\n { body }\n );\n }\n}\n","import { GitLabApiClient } from './base.js';\n\nfunction toGid(type: string, id: string | number): string {\n return `gid://gitlab/${type}/${id}`;\n}\n\nconst WORK_ITEM_WIDGETS_FRAGMENT = `\n widgets {\n type\n ... on WorkItemWidgetAssignees {\n assignees {\n nodes {\n id\n username\n name\n }\n }\n }\n ... on WorkItemWidgetLabels {\n labels {\n nodes {\n id\n title\n color\n }\n }\n }\n }\n`;\n\nconst WORK_ITEM_FIELDS = `\n id\n iid\n title\n description\n state\n createdAt\n updatedAt\n confidential\n workItemType {\n id\n name\n }\n author {\n id\n username\n name\n }\n webUrl\n ${WORK_ITEM_WIDGETS_FRAGMENT}\n`;\n\nconst GET_WORK_ITEM_QUERY = `\n query getWorkItem($fullPath: ID!, $iid: String!) {\n workspace: project(fullPath: $fullPath) {\n workItems(iid: $iid, first: 1) {\n nodes {\n ${WORK_ITEM_FIELDS}\n }\n }\n }\n }\n`;\n\nconst LIST_WORK_ITEMS_QUERY = `\n query listWorkItems(\n $fullPath: ID!\n $state: WorkItemState\n $search: String\n $types: [WorkItemTypeEnum!]\n $labelNames: [String!]\n $first: Int\n ) {\n workspace: project(fullPath: $fullPath) {\n workItems(\n state: $state\n search: $search\n types: $types\n labelName: $labelNames\n first: $first\n ) {\n nodes {\n ${WORK_ITEM_FIELDS}\n }\n }\n }\n }\n`;\n\nconst LIST_GROUP_WORK_ITEMS_QUERY = `\n query listGroupWorkItems(\n $fullPath: ID!\n $state: WorkItemState\n $search: String\n $types: [WorkItemTypeEnum!]\n $labelNames: [String!]\n $first: Int\n ) {\n workspace: group(fullPath: $fullPath) {\n workItems(\n state: $state\n search: $search\n types: $types\n labelName: $labelNames\n first: $first\n ) {\n nodes {\n ${WORK_ITEM_FIELDS}\n }\n }\n }\n }\n`;\n\nconst GET_WORK_ITEM_NOTES_QUERY = `\n query getWorkItemNotes($fullPath: ID!, $iid: String!) {\n workspace: project(fullPath: $fullPath) {\n workItems(iid: $iid, first: 1) {\n nodes {\n id\n iid\n widgets {\n type\n ... on WorkItemWidgetNotes {\n discussions {\n nodes {\n id\n notes {\n nodes {\n id\n body\n createdAt\n updatedAt\n author {\n id\n username\n name\n }\n system\n resolvable\n resolved\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n`;\n\n// The widget inputs (labelsWidget, assigneesWidget) declare their id lists as\n// non-null (`[LabelID!]!` / `[UserID!]!`) on the create path. Threading a\n// nullable variable into them fails GraphQL variable-usage validation before\n// any value is bound. To stay compatible, the whole input object is built in\n// the client (see createWorkItem/updateWorkItem) and passed as a single\n// `$input` variable, omitting any widget the caller did not provide.\nconst CREATE_WORK_ITEM_MUTATION = `\n mutation createWorkItem($input: WorkItemCreateInput!) {\n workItemCreate(input: $input) {\n workItem {\n ${WORK_ITEM_FIELDS}\n }\n errors\n }\n }\n`;\n\nconst UPDATE_WORK_ITEM_MUTATION = `\n mutation updateWorkItem($input: WorkItemUpdateInput!) {\n workItemUpdate(input: $input) {\n workItem {\n ${WORK_ITEM_FIELDS}\n }\n errors\n }\n }\n`;\n\nconst CREATE_NOTE_MUTATION = `\n mutation createWorkItemNote($noteableId: NoteableID!, $body: String!) {\n createNote(input: { noteableId: $noteableId, body: $body }) {\n note {\n id\n body\n createdAt\n author {\n id\n username\n name\n }\n }\n errors\n }\n }\n`;\n\n// workItemUpdate and createNote mutations require the global GID (WorkItemID! / NoteableID!),\n// not the iid. This query resolves the iid to the GID before the mutation.\nconst GET_WORK_ITEM_GID_QUERY = `\n query getWorkItemGid($fullPath: ID!, $iid: String!) {\n workspace: project(fullPath: $fullPath) {\n workItems(iid: $iid, first: 1) {\n nodes {\n id\n }\n }\n }\n }\n`;\n\ntype WorkItemWidget = { type: string } & Record<string, unknown>;\n\nfunction flattenWidgets(raw: Record<string, unknown>): Record<string, unknown> {\n const widgets = raw.widgets as WorkItemWidget[] | undefined;\n if (!widgets) return raw;\n\n const assigneesWidget = widgets.find((w) => w.type === 'ASSIGNEES') as\n | { assignees?: { nodes: unknown[] } }\n | undefined;\n const labelsWidget = widgets.find((w) => w.type === 'LABELS') as\n | { labels?: { nodes: unknown[] } }\n | undefined;\n\n const { widgets: _w, ...rest } = raw;\n return {\n ...rest,\n assignees: assigneesWidget?.assignees?.nodes ?? [],\n labels: labelsWidget?.labels?.nodes ?? [],\n };\n}\n\nexport class WorkItemsClient extends GitLabApiClient {\n async getWorkItem(projectId: string, workItemIid: number) {\n const result = await this.fetchGraphQL<{\n workspace: {\n workItems: { nodes: Record<string, unknown>[] };\n };\n }>(GET_WORK_ITEM_QUERY, {\n fullPath: projectId,\n iid: String(workItemIid),\n });\n\n const workItem = result.workspace?.workItems?.nodes?.[0];\n if (!workItem) {\n throw new Error(`Work item with iid ${workItemIid} not found in project ${projectId}`);\n }\n return flattenWidgets(workItem);\n }\n\n async listWorkItems(options: {\n projectId?: string;\n groupId?: string;\n state?: string;\n search?: string;\n labels?: string;\n work_item_type?: string;\n limit?: number;\n }) {\n const variables: Record<string, unknown> = {\n state: options.state ? options.state.toUpperCase() : undefined,\n search: options.search,\n types: options.work_item_type ? [options.work_item_type.toUpperCase()] : undefined,\n labelNames: options.labels ? options.labels.split(',').map((l) => l.trim()) : undefined,\n first: options.limit || 20,\n };\n\n if (options.projectId) {\n const result = await this.fetchGraphQL<{\n workspace: {\n workItems: { nodes: Record<string, unknown>[] };\n };\n }>(LIST_WORK_ITEMS_QUERY, { fullPath: options.projectId, ...variables });\n\n return (result.workspace?.workItems?.nodes ?? []).map(flattenWidgets);\n } else if (options.groupId) {\n const result = await this.fetchGraphQL<{\n workspace: {\n workItems: { nodes: Record<string, unknown>[] };\n };\n }>(LIST_GROUP_WORK_ITEMS_QUERY, { fullPath: options.groupId, ...variables });\n\n return (result.workspace?.workItems?.nodes ?? []).map(flattenWidgets);\n } else {\n throw new Error('Either projectId or groupId must be provided');\n }\n }\n\n async getWorkItemNotes(projectId: string, workItemIid: number) {\n const result = await this.fetchGraphQL<{\n workspace: {\n workItems: {\n nodes: {\n id: string;\n iid: string;\n widgets: (WorkItemWidget & {\n discussions?: {\n nodes: { id: string; notes: { nodes: Record<string, unknown>[] } }[];\n };\n })[];\n }[];\n };\n };\n }>(GET_WORK_ITEM_NOTES_QUERY, {\n fullPath: projectId,\n iid: String(workItemIid),\n });\n\n const workItem = result.workspace?.workItems?.nodes?.[0];\n if (!workItem) {\n throw new Error(`Work item with iid ${workItemIid} not found in project ${projectId}`);\n }\n\n const notesWidget = workItem.widgets?.find((w) => w.type === 'NOTES');\n const discussions = notesWidget?.discussions?.nodes ?? [];\n return discussions.flatMap((d) => d.notes?.nodes ?? []);\n }\n\n async createWorkItem(\n projectId: string,\n options: {\n title: string;\n work_item_type_id: number;\n description?: string;\n labels?: string[];\n assignee_ids?: number[];\n }\n ) {\n const labelIds = options.labels?.map((l) => toGid('Label', l));\n const assigneeIds = options.assignee_ids?.map((id) => toGid('User', id));\n\n const input: Record<string, unknown> = {\n projectPath: projectId,\n title: options.title,\n workItemTypeId: toGid('WorkItems::Type', options.work_item_type_id),\n };\n\n if (options.description !== undefined) {\n input.descriptionWidget = { description: options.description };\n }\n if (labelIds?.length) {\n input.labelsWidget = { labelIds };\n }\n if (assigneeIds?.length) {\n input.assigneesWidget = { assigneeIds };\n }\n\n const result = await this.fetchGraphQL<{\n workItemCreate: {\n workItem: Record<string, unknown>;\n errors: string[];\n };\n }>(CREATE_WORK_ITEM_MUTATION, { input });\n\n if (result.workItemCreate.errors.length > 0) {\n throw new Error(`Failed to create work item: ${result.workItemCreate.errors.join(', ')}`);\n }\n\n return flattenWidgets(result.workItemCreate.workItem);\n }\n\n async updateWorkItem(\n projectId: string,\n workItemIid: number,\n options: {\n title?: string;\n description?: string;\n state_event?: string;\n labels?: string[];\n assignee_ids?: number[];\n }\n ) {\n const gidResult = await this.fetchGraphQL<{\n workspace: { workItems: { nodes: { id: string }[] } };\n }>(GET_WORK_ITEM_GID_QUERY, {\n fullPath: projectId,\n iid: String(workItemIid),\n });\n\n const gid = gidResult.workspace?.workItems?.nodes?.[0]?.id;\n if (!gid) {\n throw new Error(`Work item with iid ${workItemIid} not found in project ${projectId}`);\n }\n\n const stateEvent = options.state_event\n ? options.state_event === 'close'\n ? 'CLOSE'\n : 'REOPEN'\n : undefined;\n\n const labelIds = options.labels?.map((l) => toGid('Label', l));\n const assigneeIds = options.assignee_ids?.map((id) => toGid('User', id));\n\n const input: Record<string, unknown> = { id: gid };\n\n if (options.title !== undefined) {\n input.title = options.title;\n }\n if (options.description !== undefined) {\n input.descriptionWidget = { description: options.description };\n }\n if (stateEvent !== undefined) {\n input.stateEvent = stateEvent;\n }\n if (labelIds?.length) {\n // The update labels widget (WorkItemWidgetLabelsUpdateInput) exposes\n // addLabelIds/removeLabelIds rather than the create widget's labelIds.\n input.labelsWidget = { addLabelIds: labelIds };\n }\n if (assigneeIds?.length) {\n input.assigneesWidget = { assigneeIds };\n }\n\n const result = await this.fetchGraphQL<{\n workItemUpdate: {\n workItem: Record<string, unknown>;\n errors: string[];\n };\n }>(UPDATE_WORK_ITEM_MUTATION, { input });\n\n if (result.workItemUpdate.errors.length > 0) {\n throw new Error(`Failed to update work item: ${result.workItemUpdate.errors.join(', ')}`);\n }\n\n return flattenWidgets(result.workItemUpdate.workItem);\n }\n\n async createWorkItemNote(projectId: string, workItemIid: number, body: string) {\n const gidResult = await this.fetchGraphQL<{\n workspace: { workItems: { nodes: { id: string }[] } };\n }>(GET_WORK_ITEM_GID_QUERY, {\n fullPath: projectId,\n iid: String(workItemIid),\n });\n\n const gid = gidResult.workspace?.workItems?.nodes?.[0]?.id;\n if (!gid) {\n throw new Error(`Work item with iid ${workItemIid} not found in project ${projectId}`);\n }\n\n const result = await this.fetchGraphQL<{\n createNote: {\n note: Record<string, unknown>;\n errors: string[];\n };\n }>(CREATE_NOTE_MUTATION, {\n noteableId: gid,\n body,\n });\n\n if (result.createNote.errors.length > 0) {\n throw new Error(`Failed to create note: ${result.createNote.errors.join(', ')}`);\n }\n\n return result.createNote.note;\n }\n}\n","import { GitLabApiClient } from './base.js';\n\nexport class PipelinesClient extends GitLabApiClient {\n async listPipelines(\n projectId: string,\n options?: { status?: string; ref?: string; limit?: number }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const params = new URLSearchParams();\n params.set('per_page', String(options?.limit || 20));\n\n if (options?.status) params.set('status', options.status);\n if (options?.ref) params.set('ref', options.ref);\n\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/pipelines?${params}`\n );\n }\n\n async getPipeline(projectId: string, pipelineId: number) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/pipelines/${pipelineId}`\n );\n }\n\n async listPipelineJobs(projectId: string, pipelineId: number, scope?: string) {\n const encodedProject = this.encodeProjectId(projectId);\n const params = new URLSearchParams();\n if (scope) params.set('scope[]', scope);\n\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/pipelines/${pipelineId}/jobs?${params}`\n );\n }\n\n async getJobLog(projectId: string, jobId: number) {\n const encodedProject = this.encodeProjectId(projectId);\n const log = await this.fetchText('GET', `/projects/${encodedProject}/jobs/${jobId}/trace`);\n // Truncate very long logs\n const maxLength = 50000;\n if (log.length > maxLength) {\n return `[Log truncated, showing last ${maxLength} characters]\\n\\n${log.slice(-maxLength)}`;\n }\n return log;\n }\n\n async retryJob(projectId: string, jobId: number) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/jobs/${jobId}/retry`\n );\n }\n\n async getPipelineFailingJobs(projectId: string, pipelineId: number) {\n const encodedProject = this.encodeProjectId(projectId);\n const jobs = await this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/pipelines/${pipelineId}/jobs?scope[]=failed`\n );\n return jobs;\n }\n\n /**\n * Validate a CI/CD configuration\n * @param projectId - The project ID or URL-encoded path\n * @param content - The CI/CD configuration content (YAML as string)\n * @param options - Optional parameters\n * @param options.dry_run - Run pipeline creation simulation (default: false)\n * @param options.include_jobs - Include list of jobs in response (default: false)\n * @param options.ref - Branch or tag context for validation (defaults to project's default branch)\n * @returns Validation result with errors, warnings, and optionally merged YAML and jobs\n */\n async lintCiConfig(\n projectId: string,\n content: string,\n options?: {\n dry_run?: boolean;\n include_jobs?: boolean;\n ref?: string;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const body: Record<string, unknown> = {\n content,\n };\n\n if (options?.dry_run !== undefined) body.dry_run = options.dry_run;\n if (options?.include_jobs !== undefined) body.include_jobs = options.include_jobs;\n if (options?.ref) body.ref = options.ref;\n\n return this.fetch<{\n valid: boolean;\n errors: string[];\n warnings: string[];\n merged_yaml?: string;\n includes?: Array<{\n type: string;\n location: string;\n blob?: string;\n raw?: string;\n extra?: Record<string, unknown>;\n context_project?: string;\n context_sha?: string;\n }>;\n jobs?: Array<{\n name: string;\n stage: string;\n before_script: string[];\n script: string[];\n after_script: string[];\n tag_list: string[];\n only: Record<string, unknown> | null;\n except: Record<string, unknown> | null;\n environment: string | null;\n when: string;\n allow_failure: boolean;\n needs: unknown;\n }>;\n }>('POST', `/projects/${encodedProject}/ci/lint`, body);\n }\n\n /**\n * Validate an existing CI/CD configuration from the repository\n * @param projectId - The project ID or URL-encoded path\n * @param options - Optional parameters\n * @param options.content_ref - Commit SHA, branch or tag to get CI config from (defaults to default branch)\n * @param options.dry_run - Run pipeline creation simulation (default: false)\n * @param options.dry_run_ref - Branch or tag context for validation (defaults to project's default branch)\n * @param options.include_jobs - Include list of jobs in response (default: false)\n * @returns Validation result with errors, warnings, and optionally merged YAML and jobs\n */\n async lintExistingCiConfig(\n projectId: string,\n options?: {\n content_ref?: string;\n dry_run?: boolean;\n dry_run_ref?: string;\n include_jobs?: boolean;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const params = new URLSearchParams();\n\n if (options?.content_ref) params.set('content_ref', options.content_ref);\n if (options?.dry_run !== undefined) params.set('dry_run', String(options.dry_run));\n if (options?.dry_run_ref) params.set('dry_run_ref', options.dry_run_ref);\n if (options?.include_jobs !== undefined)\n params.set('include_jobs', String(options.include_jobs));\n\n const queryString = params.toString();\n const path = queryString\n ? `/projects/${encodedProject}/ci/lint?${queryString}`\n : `/projects/${encodedProject}/ci/lint`;\n\n return this.fetch<{\n valid: boolean;\n errors: string[];\n warnings: string[];\n merged_yaml?: string;\n includes?: Array<{\n type: string;\n location: string;\n blob?: string;\n raw?: string;\n extra?: Record<string, unknown>;\n context_project?: string;\n context_sha?: string;\n }>;\n jobs?: Array<{\n name: string;\n stage: string;\n before_script: string[];\n script: string[];\n after_script: string[];\n tag_list: string[];\n only: Record<string, unknown> | null;\n except: Record<string, unknown> | null;\n environment: string | null;\n when: string;\n allow_failure: boolean;\n needs: unknown;\n }>;\n }>('GET', path);\n }\n}\n","import { GitLabApiClient } from './base.js';\n\nexport class RepositoryClient extends GitLabApiClient {\n async getFile(projectId: string, filePath: string, ref: string) {\n const encodedProject = this.encodeProjectId(projectId);\n const encodedPath = encodeURIComponent(filePath);\n const url = `/projects/${encodedProject}/repository/files/${encodedPath}?ref=${encodeURIComponent(ref)}`;\n\n const file = await this.fetch<{ content: string; encoding: string }>('GET', url);\n\n // Decode base64 content\n if (file.encoding === 'base64') {\n return Buffer.from(file.content, 'base64').toString('utf-8');\n }\n return file.content;\n }\n\n async listCommits(\n projectId: string,\n options?: { ref?: string; path?: string; since?: string; until?: string; limit?: number }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const params = new URLSearchParams();\n params.set('per_page', String(options?.limit || 20));\n\n if (options?.ref) params.set('ref_name', options.ref);\n if (options?.path) params.set('path', options.path);\n if (options?.since) params.set('since', options.since);\n if (options?.until) params.set('until', options.until);\n\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/repository/commits?${params}`\n );\n }\n\n async getCommit(projectId: string, sha: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/repository/commits/${sha}`\n );\n }\n\n async getCommitDiff(projectId: string, sha: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/repository/commits/${sha}/diff`\n );\n }\n\n async createCommit(\n projectId: string,\n options: {\n branch: string;\n commit_message: string;\n actions: Array<{\n action: 'create' | 'delete' | 'move' | 'update' | 'chmod';\n file_path: string;\n content?: string;\n encoding?: 'text' | 'base64';\n previous_path?: string;\n execute_filemode?: boolean;\n }>;\n author_email?: string;\n author_name?: string;\n start_branch?: string;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/repository/commits`,\n options\n );\n }\n\n async listRepositoryTree(\n projectId: string,\n options?: {\n path?: string;\n ref?: string;\n recursive?: boolean;\n per_page?: number;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const params = new URLSearchParams();\n\n if (options?.path) params.set('path', options.path);\n if (options?.ref) params.set('ref', options.ref);\n if (options?.recursive) params.set('recursive', 'true');\n if (options?.per_page) params.set('per_page', String(options.per_page));\n\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/repository/tree?${params}`\n );\n }\n\n async listBranches(projectId: string, search?: string) {\n const encodedProject = this.encodeProjectId(projectId);\n const params = new URLSearchParams();\n if (search) params.set('search', search);\n\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/repository/branches?${params}`\n );\n }\n\n // ========== Commit Discussion Methods ==========\n\n async listCommitDiscussions(projectId: string, sha: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/repository/commits/${sha}/discussions`\n );\n }\n\n async getCommitDiscussion(projectId: string, sha: string, discussionId: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/repository/commits/${sha}/discussions/${discussionId}`\n );\n }\n\n async createCommitNote(\n projectId: string,\n sha: string,\n body: string,\n options?: {\n discussion_id?: string;\n path?: string;\n line?: number;\n line_type?: 'new' | 'old';\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n // If discussion_id is provided, add note to existing discussion thread\n if (options?.discussion_id) {\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/repository/commits/${sha}/discussions/${options.discussion_id}/notes`,\n { body }\n );\n }\n // Otherwise create a new note (optionally positioned on a specific line)\n const requestBody: Record<string, unknown> = { body };\n if (options?.path) requestBody.path = options.path;\n if (options?.line) requestBody.line = options.line;\n if (options?.line_type) requestBody.line_type = options.line_type;\n\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/repository/commits/${sha}/comments`,\n requestBody\n );\n }\n\n async createCommitDiscussion(\n projectId: string,\n sha: string,\n body: string,\n position?: {\n base_sha: string;\n start_sha: string;\n head_sha: string;\n position_type: 'text' | 'image';\n new_path?: string;\n old_path?: string;\n new_line?: number;\n old_line?: number;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const requestBody: Record<string, unknown> = { body };\n if (position) {\n requestBody.position = position;\n }\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/repository/commits/${sha}/discussions`,\n requestBody\n );\n }\n\n /**\n * Get comments on a specific commit\n * API: GET /projects/:id/repository/commits/:sha/comments\n */\n async getCommitComments(projectId: string, sha: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/repository/commits/${sha}/comments`\n );\n }\n}\n","import { GitLabApiClient } from './base.js';\n\ninterface SearchOptions {\n state?: string;\n order_by?: string;\n sort?: string;\n ref?: string;\n limit?: number;\n}\n\nexport class SearchClient extends GitLabApiClient {\n async search(scope: string, searchQuery: string, projectId?: string, limit?: number) {\n const params = new URLSearchParams();\n params.set('scope', scope);\n params.set('search', searchQuery);\n params.set('per_page', String(limit || 20));\n\n let path: string;\n if (projectId) {\n const encodedProject = this.encodeProjectId(projectId);\n path = `/projects/${encodedProject}/search?${params}`;\n } else {\n path = `/search?${params}`;\n }\n\n return this.fetch<Record<string, unknown>[]>('GET', path);\n }\n\n /**\n * Search for commits in a project or globally\n * @param searchQuery - The search term\n * @param projectId - Optional project ID to limit search\n * @param options - Optional search parameters\n */\n async searchCommits(searchQuery: string, projectId?: string, options?: SearchOptions) {\n const params = new URLSearchParams();\n params.set('scope', 'commits');\n params.set('search', searchQuery);\n params.set('per_page', String(options?.limit || 20));\n\n if (options?.ref) params.set('ref', options.ref);\n if (options?.order_by) params.set('order_by', options.order_by);\n if (options?.sort) params.set('sort', options.sort);\n\n let path: string;\n if (projectId) {\n const encodedProject = this.encodeProjectId(projectId);\n path = `/projects/${encodedProject}/search?${params}`;\n } else {\n path = `/search?${params}`;\n }\n\n return this.fetch<Record<string, unknown>[]>('GET', path);\n }\n\n /**\n * Search for projects within a specific group\n * @param groupId - The group ID or URL-encoded path\n * @param searchQuery - The search term\n * @param options - Optional search parameters\n */\n async searchGroupProjects(groupId: string, searchQuery: string, options?: SearchOptions) {\n const encodedGroup = this.encodeProjectId(groupId);\n const params = new URLSearchParams();\n params.set('scope', 'projects');\n params.set('search', searchQuery);\n params.set('per_page', String(options?.limit || 20));\n\n if (options?.order_by) params.set('order_by', options.order_by);\n if (options?.sort) params.set('sort', options.sort);\n\n return this.fetch<Record<string, unknown>[]>('GET', `/groups/${encodedGroup}/search?${params}`);\n }\n\n /**\n * Search for milestones in a project or globally\n * @param searchQuery - The search term\n * @param projectId - Optional project ID to limit search\n * @param options - Optional search parameters\n */\n async searchMilestones(searchQuery: string, projectId?: string, options?: SearchOptions) {\n const params = new URLSearchParams();\n params.set('scope', 'milestones');\n params.set('search', searchQuery);\n params.set('per_page', String(options?.limit || 20));\n\n if (options?.state) params.set('state', options.state);\n if (options?.order_by) params.set('order_by', options.order_by);\n if (options?.sort) params.set('sort', options.sort);\n\n let path: string;\n if (projectId) {\n const encodedProject = this.encodeProjectId(projectId);\n path = `/projects/${encodedProject}/search?${params}`;\n } else {\n path = `/search?${params}`;\n }\n\n return this.fetch<Record<string, unknown>[]>('GET', path);\n }\n\n /**\n * Search for notes/comments in a project\n * @param searchQuery - The search term\n * @param projectId - The project ID to search in\n * @param options - Optional search parameters\n */\n async searchNotes(searchQuery: string, projectId: string, options?: SearchOptions) {\n const encodedProject = this.encodeProjectId(projectId);\n const params = new URLSearchParams();\n params.set('scope', 'notes');\n params.set('search', searchQuery);\n params.set('per_page', String(options?.limit || 20));\n\n if (options?.order_by) params.set('order_by', options.order_by);\n if (options?.sort) params.set('sort', options.sort);\n\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/search?${params}`\n );\n }\n\n /**\n * Search for users by name or email\n * @param searchQuery - The search term (name or email)\n * @param projectId - Optional project ID to limit search\n * @param options - Optional search parameters\n */\n async searchUsers(searchQuery: string, projectId?: string, options?: SearchOptions) {\n const params = new URLSearchParams();\n params.set('scope', 'users');\n params.set('search', searchQuery);\n params.set('per_page', String(options?.limit || 20));\n\n if (options?.order_by) params.set('order_by', options.order_by);\n if (options?.sort) params.set('sort', options.sort);\n\n let path: string;\n if (projectId) {\n const encodedProject = this.encodeProjectId(projectId);\n path = `/projects/${encodedProject}/search?${params}`;\n } else {\n path = `/search?${params}`;\n }\n\n return this.fetch<Record<string, unknown>[]>('GET', path);\n }\n\n /**\n * Search for wiki blobs (wiki content)\n * @param searchQuery - The search term (supports filters like filename:, path:, extension:)\n * @param projectId - Optional project ID to limit search\n * @param options - Optional search parameters\n */\n async searchWikiBlobs(searchQuery: string, projectId?: string, options?: SearchOptions) {\n const params = new URLSearchParams();\n params.set('scope', 'wiki_blobs');\n params.set('search', searchQuery);\n params.set('per_page', String(options?.limit || 20));\n\n if (options?.ref) params.set('ref', options.ref);\n if (options?.order_by) params.set('order_by', options.order_by);\n if (options?.sort) params.set('sort', options.sort);\n\n let path: string;\n if (projectId) {\n const encodedProject = this.encodeProjectId(projectId);\n path = `/projects/${encodedProject}/search?${params}`;\n } else {\n path = `/search?${params}`;\n }\n\n return this.fetch<Record<string, unknown>[]>('GET', path);\n }\n\n /**\n * Search GitLab documentation\n * Note: This uses the public GitLab docs search API\n * @param searchQuery - The search term\n * @param limit - Maximum number of results (default: 10)\n */\n async searchDocumentation(searchQuery: string, limit?: number) {\n // GitLab documentation search uses the public docs site\n // We'll use the Algolia search API that powers docs.gitlab.com\n const url = `https://docs.gitlab.com/search.json?q=${encodeURIComponent(searchQuery)}&limit=${limit || 10}`;\n\n const response = await fetch(url);\n\n if (!response.ok) {\n throw new Error(`Documentation search error ${response.status}: ${await response.text()}`);\n }\n\n return response.json();\n }\n}\n","import { GitLabApiClient } from './base.js';\n\nexport class ProjectsClient extends GitLabApiClient {\n async getProject(projectId: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>('GET', `/projects/${encodedProject}`);\n }\n\n async listProjectMembers(projectId: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>[]>('GET', `/projects/${encodedProject}/members`);\n }\n}\n","import { GitLabApiClient } from './base.js';\n\nexport interface UserStatus {\n emoji?: string;\n message?: string;\n availability?: 'not_set' | 'busy';\n clear_status_at?: string;\n}\n\nexport interface User {\n id: number;\n username: string;\n name: string;\n state: string;\n locked: boolean;\n avatar_url: string;\n web_url: string;\n created_at?: string;\n bio?: string;\n location?: string;\n public_email?: string;\n job_title?: string;\n pronouns?: string;\n organization?: string;\n bot?: boolean;\n work_information?: string;\n}\n\nexport class UsersClient extends GitLabApiClient {\n async getCurrentUser() {\n return this.fetch<User>('GET', '/user');\n }\n\n /**\n * Get a user by ID\n * @param userId - The user ID\n */\n async getUser(userId: number): Promise<User> {\n return this.fetch<User>('GET', `/users/${userId}`);\n }\n\n /**\n * Find users by username\n * @param username - The username to search for (exact match)\n */\n async getUserByUsername(username: string): Promise<User[]> {\n const params = new URLSearchParams();\n params.set('username', username);\n return this.fetch<User[]>('GET', `/users?${params}`);\n }\n\n /**\n * Get a user's status\n * @param userId - The user ID\n */\n async getUserStatus(userId: number): Promise<UserStatus> {\n return this.fetch<UserStatus>('GET', `/users/${userId}/status`);\n }\n}\n","import { GitLabApiClient } from './base.js';\n\nexport class WikisClient extends GitLabApiClient {\n async getWikiPage(projectId: string, slug: string) {\n const encodedProject = this.encodeProjectId(projectId);\n const encodedSlug = encodeURIComponent(slug);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/wikis/${encodedSlug}`\n );\n }\n}\n","/**\n * Validate GitLab Global ID (GID) format\n * @param gid - The GID to validate\n * @param expectedType - Expected resource type (e.g., 'Vulnerability', 'Issue')\n * @returns true if valid, false otherwise\n */\nexport function isValidGid(gid: string, expectedType?: string): boolean {\n // GID format: gid://gitlab/{ResourceType}/{id}\n const gidPattern = /^gid:\\/\\/gitlab\\/([A-Za-z]+)\\/(\\d+)$/;\n const match = gid.match(gidPattern);\n\n if (!match) {\n return false;\n }\n\n // If expectedType is provided, validate it matches\n if (expectedType && match[1] !== expectedType) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Validate and throw error if GID format is invalid\n * @param gid - The GID to validate\n * @param expectedType - Expected resource type (e.g., 'Vulnerability', 'Issue')\n * @throws Error if GID format is invalid\n */\nexport function validateGid(gid: string, expectedType?: string): void {\n if (!isValidGid(gid, expectedType)) {\n const typeMsg = expectedType ? ` of type '${expectedType}'` : '';\n throw new Error(\n `Invalid GitLab Global ID${typeMsg}: '${gid}'. Expected format: gid://gitlab/${expectedType || 'ResourceType'}/{id}`\n );\n }\n}\n","import { GitLabApiClient } from './base.js';\nimport { validateGid } from '../validation.js';\n\nexport type DismissalReason =\n | 'ACCEPTABLE_RISK'\n | 'FALSE_POSITIVE'\n | 'MITIGATING_CONTROL'\n | 'USED_IN_TESTS'\n | 'NOT_APPLICABLE';\n\nexport type VulnerabilitySeverity = 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW' | 'INFO' | 'UNKNOWN';\n\n// GraphQL mutation constants\nconst CREATE_VULNERABILITY_ISSUE_MUTATION = `\n mutation($projectPath: ID!, $vulnerabilityIds: [VulnerabilityID!]!) {\n createVulnerabilityIssueLink(input: {\n projectPath: $projectPath\n vulnerabilityIds: $vulnerabilityIds\n }) {\n issue {\n id\n iid\n title\n webUrl\n }\n errors\n }\n }\n`;\n\nconst DISMISS_VULNERABILITY_MUTATION = `\n mutation($id: VulnerabilityID!, $reason: VulnerabilityDismissalReason!, $comment: String) {\n vulnerabilityDismiss(input: {\n id: $id\n dismissalReason: $reason\n comment: $comment\n }) {\n vulnerability {\n id\n state\n dismissalReason\n }\n errors\n }\n }\n`;\n\nconst CONFIRM_VULNERABILITY_MUTATION = `\n mutation($id: VulnerabilityID!, $comment: String) {\n vulnerabilityConfirm(input: {\n id: $id\n comment: $comment\n }) {\n vulnerability {\n id\n state\n }\n errors\n }\n }\n`;\n\nconst REVERT_VULNERABILITY_MUTATION = `\n mutation($id: VulnerabilityID!, $comment: String) {\n vulnerabilityRevertToDetected(input: {\n id: $id\n comment: $comment\n }) {\n vulnerability {\n id\n state\n }\n errors\n }\n }\n`;\n\nconst UPDATE_VULNERABILITY_SEVERITY_MUTATION = `\n mutation($ids: [VulnerabilityID!]!, $severity: VulnerabilitySeverity!, $comment: String!) {\n vulnerabilitiesUpdateSeverity(input: {\n ids: $ids\n severity: $severity\n comment: $comment\n }) {\n vulnerabilities {\n id\n severity\n }\n errors\n }\n }\n`;\n\nconst LINK_VULNERABILITY_TO_ISSUE_MUTATION = `\n mutation($issueId: IssueID!, $vulnerabilityIds: [VulnerabilityID!]!) {\n vulnerabilityIssueLinksCreate(input: {\n issueId: $issueId\n vulnerabilityIds: $vulnerabilityIds\n }) {\n issue {\n id\n iid\n title\n webUrl\n }\n errors\n }\n }\n`;\n\nexport class SecurityClient extends GitLabApiClient {\n async listVulnerabilities(\n projectId: string,\n options?: {\n state?: string;\n severity?: string;\n report_type?: string;\n limit?: number;\n }\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n const params = new URLSearchParams();\n params.set('per_page', String(options?.limit || 20));\n\n if (options?.state) params.set('state', options.state);\n if (options?.severity) params.set('severity', options.severity);\n if (options?.report_type) params.set('report_type', options.report_type);\n\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/projects/${encodedProject}/vulnerabilities?${params}`\n );\n }\n\n async getVulnerabilityDetails(projectId: string, vulnerabilityId: number) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/vulnerabilities/${vulnerabilityId}`\n );\n }\n\n /**\n * Create an issue linked to one or more vulnerabilities\n * @param projectPath - Full path of the project (e.g., 'group/project')\n * @param vulnerabilityIds - Array of vulnerability IDs in format 'gid://gitlab/Vulnerability/{id}'\n * @returns The created issue\n */\n async createVulnerabilityIssue(projectPath: string, vulnerabilityIds: string[]) {\n // Validate all vulnerability IDs\n vulnerabilityIds.forEach((id) => validateGid(id, 'Vulnerability'));\n\n const result = await this.fetchGraphQL<{\n createVulnerabilityIssueLink: {\n issue: Record<string, unknown>;\n errors: string[];\n };\n }>(CREATE_VULNERABILITY_ISSUE_MUTATION, { projectPath, vulnerabilityIds });\n\n if (result.createVulnerabilityIssueLink.errors.length > 0) {\n throw new Error(\n `Failed to create vulnerability issue: ${result.createVulnerabilityIssueLink.errors.join(', ')}`\n );\n }\n\n return result.createVulnerabilityIssueLink.issue;\n }\n\n /**\n * Dismiss a vulnerability with a reason\n * @param vulnerabilityId - Vulnerability ID in format 'gid://gitlab/Vulnerability/{id}'\n * @param reason - Dismissal reason\n * @param comment - Optional comment explaining the dismissal\n * @returns The updated vulnerability\n */\n async dismissVulnerability(vulnerabilityId: string, reason: DismissalReason, comment?: string) {\n validateGid(vulnerabilityId, 'Vulnerability');\n\n const result = await this.fetchGraphQL<{\n vulnerabilityDismiss: {\n vulnerability: Record<string, unknown>;\n errors: string[];\n };\n }>(DISMISS_VULNERABILITY_MUTATION, { id: vulnerabilityId, reason, comment });\n\n if (result.vulnerabilityDismiss.errors.length > 0) {\n throw new Error(\n `Failed to dismiss vulnerability: ${result.vulnerabilityDismiss.errors.join(', ')}`\n );\n }\n\n return result.vulnerabilityDismiss.vulnerability;\n }\n\n /**\n * Confirm a vulnerability\n * @param vulnerabilityId - Vulnerability ID in format 'gid://gitlab/Vulnerability/{id}'\n * @param comment - Optional comment\n * @returns The updated vulnerability\n */\n async confirmVulnerability(vulnerabilityId: string, comment?: string) {\n validateGid(vulnerabilityId, 'Vulnerability');\n\n const result = await this.fetchGraphQL<{\n vulnerabilityConfirm: {\n vulnerability: Record<string, unknown>;\n errors: string[];\n };\n }>(CONFIRM_VULNERABILITY_MUTATION, { id: vulnerabilityId, comment });\n\n if (result.vulnerabilityConfirm.errors.length > 0) {\n throw new Error(\n `Failed to confirm vulnerability: ${result.vulnerabilityConfirm.errors.join(', ')}`\n );\n }\n\n return result.vulnerabilityConfirm.vulnerability;\n }\n\n /**\n * Revert a vulnerability back to detected state\n * @param vulnerabilityId - Vulnerability ID in format 'gid://gitlab/Vulnerability/{id}'\n * @param comment - Optional comment\n * @returns The updated vulnerability\n */\n async revertVulnerability(vulnerabilityId: string, comment?: string) {\n validateGid(vulnerabilityId, 'Vulnerability');\n\n const result = await this.fetchGraphQL<{\n vulnerabilityRevertToDetected: {\n vulnerability: Record<string, unknown>;\n errors: string[];\n };\n }>(REVERT_VULNERABILITY_MUTATION, { id: vulnerabilityId, comment });\n\n if (result.vulnerabilityRevertToDetected.errors.length > 0) {\n throw new Error(\n `Failed to revert vulnerability: ${result.vulnerabilityRevertToDetected.errors.join(', ')}`\n );\n }\n\n return result.vulnerabilityRevertToDetected.vulnerability;\n }\n\n /**\n * Update the severity of one or more vulnerabilities\n * @param vulnerabilityIds - Array of vulnerability IDs in format 'gid://gitlab/Vulnerability/{id}'\n * @param severity - New severity level\n * @param comment - Comment explaining the severity change\n * @returns Array of updated vulnerabilities\n */\n async updateVulnerabilitySeverity(\n vulnerabilityIds: string[],\n severity: VulnerabilitySeverity,\n comment: string\n ) {\n // Validate all vulnerability IDs\n vulnerabilityIds.forEach((id) => validateGid(id, 'Vulnerability'));\n\n const result = await this.fetchGraphQL<{\n vulnerabilitiesUpdateSeverity: {\n vulnerabilities: Record<string, unknown>[];\n errors: string[];\n };\n }>(UPDATE_VULNERABILITY_SEVERITY_MUTATION, { ids: vulnerabilityIds, severity, comment });\n\n if (result.vulnerabilitiesUpdateSeverity.errors.length > 0) {\n throw new Error(\n `Failed to update vulnerability severity: ${result.vulnerabilitiesUpdateSeverity.errors.join(', ')}`\n );\n }\n\n return result.vulnerabilitiesUpdateSeverity.vulnerabilities;\n }\n\n /**\n * Link an existing issue to one or more vulnerabilities\n * @param issueId - Issue ID in format 'gid://gitlab/Issue/{id}'\n * @param vulnerabilityIds - Array of vulnerability IDs in format 'gid://gitlab/Vulnerability/{id}'\n * @returns The linked issue\n */\n async linkVulnerabilityToIssue(issueId: string, vulnerabilityIds: string[]) {\n validateGid(issueId, 'Issue');\n vulnerabilityIds.forEach((id) => validateGid(id, 'Vulnerability'));\n\n const result = await this.fetchGraphQL<{\n vulnerabilityIssueLinksCreate: {\n issue: Record<string, unknown>;\n errors: string[];\n };\n }>(LINK_VULNERABILITY_TO_ISSUE_MUTATION, { issueId, vulnerabilityIds });\n\n if (result.vulnerabilityIssueLinksCreate.errors.length > 0) {\n throw new Error(\n `Failed to link vulnerability to issue: ${result.vulnerabilityIssueLinksCreate.errors.join(', ')}`\n );\n }\n\n return result.vulnerabilityIssueLinksCreate.issue;\n }\n}\n","import { GitLabApiClient } from './base.js';\n\nexport interface TodosPageInfo {\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n startCursor: string | null;\n endCursor: string | null;\n}\n\nexport interface TodoNode {\n id: string;\n body: string;\n state: string;\n action: string;\n createdAt: string;\n targetType: string;\n targetUrl: string | null;\n snoozedUntil: string | null;\n project: {\n id: string;\n name: string;\n fullPath: string;\n } | null;\n group: {\n id: string;\n name: string;\n fullPath: string;\n } | null;\n author: {\n id: string;\n username: string;\n name: string;\n avatarUrl: string | null;\n };\n}\n\nexport interface TodosConnection {\n nodes: TodoNode[];\n pageInfo: TodosPageInfo;\n count: number;\n}\n\nexport interface TodosResult {\n todos: TodosConnection;\n}\n\nconst LIST_TODOS_QUERY = `\n query listTodos(\n $state: [TodoStateEnum!]\n $action: [TodoActionEnum!]\n $type: [TodoTargetEnum!]\n $projectId: [ID!]\n $groupId: [ID!]\n $authorId: [ID!]\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n currentUser {\n todos(\n state: $state\n action: $action\n type: $type\n projectId: $projectId\n groupId: $groupId\n authorId: $authorId\n first: $first\n after: $after\n last: $last\n before: $before\n ) {\n count\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n nodes {\n id\n body\n state\n action\n createdAt\n targetType\n targetUrl\n snoozedUntil\n project {\n id\n name\n fullPath\n }\n group {\n id\n name\n fullPath\n }\n author {\n id\n username\n name\n avatarUrl\n }\n }\n }\n }\n }\n`;\n\nexport class TodosClient extends GitLabApiClient {\n async listTodos(options?: {\n action?: string;\n author_id?: number;\n project_id?: string;\n group_id?: string;\n state?: string;\n type?: string;\n first?: number;\n after?: string;\n last?: number;\n before?: string;\n }): Promise<TodosResult> {\n if (options?.first !== undefined && options?.last !== undefined) {\n throw new Error(\n 'Cannot specify both \"first\" and \"last\" pagination parameters. Use \"first\"/\"after\" for forward pagination or \"last\"/\"before\" for backward pagination.'\n );\n }\n\n const variables: Record<string, unknown> = {};\n\n if (options?.first !== undefined) {\n variables.first = options.first;\n } else if (options?.last === undefined) {\n variables.first = 20;\n }\n\n if (options?.after) variables.after = options.after;\n if (options?.last !== undefined) variables.last = options.last;\n if (options?.before) variables.before = options.before;\n\n if (options?.action) {\n variables.action = [this.mapTodoAction(options.action)];\n }\n if (options?.author_id) {\n variables.authorId = [`gid://gitlab/User/${options.author_id}`];\n }\n if (options?.project_id) {\n variables.projectId = [options.project_id];\n }\n if (options?.group_id) {\n variables.groupId = [options.group_id];\n }\n if (options?.state) {\n variables.state = [options.state.toLowerCase()];\n }\n if (options?.type) {\n variables.type = [this.mapTodoTargetType(options.type)];\n }\n\n const result = await this.fetchGraphQL<{\n currentUser: {\n todos: TodosConnection;\n };\n }>(LIST_TODOS_QUERY, variables);\n\n const todos = result.currentUser.todos;\n\n return {\n todos,\n };\n }\n\n private mapTodoAction(action: string): string {\n const actionMap: Record<string, string> = {\n assigned: 'ASSIGNED',\n mentioned: 'MENTIONED',\n build_failed: 'BUILD_FAILED',\n marked: 'MARKED',\n approval_required: 'APPROVAL_REQUIRED',\n unmergeable: 'UNMERGEABLE',\n directly_addressed: 'DIRECTLY_ADDRESSED',\n merge_train_removed: 'MERGE_TRAIN_REMOVED',\n review_requested: 'REVIEW_REQUESTED',\n };\n return actionMap[action] || action.toUpperCase();\n }\n\n private mapTodoTargetType(type: string): string {\n const typeMap: Record<string, string> = {\n Issue: 'ISSUE',\n MergeRequest: 'MERGEREQUEST',\n 'DesignManagement::Design': 'DESIGN',\n Alert: 'ALERT',\n Commit: 'COMMIT',\n Epic: 'EPIC',\n };\n return typeMap[type] || type;\n }\n\n async markTodoAsDone(\n todoId: number\n ): Promise<{ success: boolean; todo?: Record<string, unknown>; message?: string }> {\n try {\n const result = await this.fetch<Record<string, unknown>>(\n 'POST',\n `/todos/${todoId}/mark_as_done`\n );\n return { success: true, todo: result };\n } catch (error) {\n if (error instanceof Error && error.message.includes('404')) {\n return {\n success: false,\n message: `Todo ${todoId} not found. It may have already been marked as done or does not exist.`,\n };\n }\n throw error;\n }\n }\n\n async markAllTodosAsDone() {\n return this.fetch<Record<string, unknown>>('POST', '/todos/mark_as_done');\n }\n\n async getTodoCount() {\n const result = await this.fetchGraphQL<{\n currentUser: {\n todos: {\n count: number;\n };\n };\n }>(`query { currentUser { todos(state: [pending]) { count } } }`);\n\n return { count: result.currentUser.todos.count };\n }\n}\n","import { GitLabApiClient } from './base.js';\nimport {\n NotesResult,\n NotesConnection,\n NotesPaginationOptions,\n NOTES_FRAGMENT,\n NOTES_CONNECTION_FRAGMENT,\n buildPaginationVariables,\n} from './notes-types.js';\nimport {\n DiscussionsResult,\n DiscussionsConnection,\n DiscussionsPaginationOptions,\n DISCUSSION_NOTE_FRAGMENT,\n DISCUSSION_FRAGMENT,\n DISCUSSIONS_CONNECTION_FRAGMENT,\n buildDiscussionsPaginationVariables,\n} from './discussions-types.js';\n\nconst LIST_EPIC_NOTES_QUERY = `\n ${NOTES_FRAGMENT}\n ${NOTES_CONNECTION_FRAGMENT}\n query listEpicNotes(\n $groupPath: ID!\n $epicIid: String!\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n group(fullPath: $groupPath) {\n epic(iid: $epicIid) {\n notes(\n first: $first\n after: $after\n last: $last\n before: $before\n ) {\n ...NotesConnectionFields\n }\n }\n }\n }\n`;\n\nconst LIST_EPIC_DISCUSSIONS_QUERY = `\n ${DISCUSSION_NOTE_FRAGMENT}\n ${DISCUSSION_FRAGMENT}\n ${DISCUSSIONS_CONNECTION_FRAGMENT}\n query listEpicDiscussions(\n $groupPath: ID!\n $epicIid: String!\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n group(fullPath: $groupPath) {\n epic(iid: $epicIid) {\n discussions(\n first: $first\n after: $after\n last: $last\n before: $before\n ) {\n ...DiscussionsConnectionFields\n }\n }\n }\n }\n`;\n\nexport class EpicsClient extends GitLabApiClient {\n async getEpic(groupId: string, epicIid: number) {\n const encodedGroup = encodeURIComponent(groupId);\n return this.fetch<Record<string, unknown>>('GET', `/groups/${encodedGroup}/epics/${epicIid}`);\n }\n\n async listEpics(options: {\n groupId: string;\n state?: string;\n author_id?: number;\n labels?: string;\n search?: string;\n limit?: number;\n }) {\n const encodedGroup = encodeURIComponent(options.groupId);\n const params = new URLSearchParams();\n params.set('per_page', String(options.limit || 20));\n\n if (options.state) params.set('state', options.state);\n if (options.author_id) params.set('author_id', String(options.author_id));\n if (options.labels) params.set('labels', options.labels);\n if (options.search) params.set('search', options.search);\n\n return this.fetch<Record<string, unknown>[]>('GET', `/groups/${encodedGroup}/epics?${params}`);\n }\n\n async createEpic(\n groupId: string,\n options: {\n title: string;\n description?: string;\n labels?: string;\n start_date?: string;\n end_date?: string;\n confidential?: boolean;\n }\n ) {\n const encodedGroup = encodeURIComponent(groupId);\n return this.fetch<Record<string, unknown>>('POST', `/groups/${encodedGroup}/epics`, options);\n }\n\n async updateEpic(\n groupId: string,\n epicIid: number,\n options: {\n title?: string;\n description?: string;\n labels?: string;\n start_date?: string;\n end_date?: string;\n state_event?: string;\n confidential?: boolean;\n }\n ) {\n const encodedGroup = encodeURIComponent(groupId);\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/groups/${encodedGroup}/epics/${epicIid}`,\n options\n );\n }\n\n async listEpicIssues(groupId: string, epicIid: number) {\n const encodedGroup = encodeURIComponent(groupId);\n return this.fetch<Record<string, unknown>[]>(\n 'GET',\n `/groups/${encodedGroup}/epics/${epicIid}/issues`\n );\n }\n\n async addIssueToEpic(groupId: string, epicIid: number, issueId: number) {\n const encodedGroup = encodeURIComponent(groupId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/groups/${encodedGroup}/epics/${epicIid}/issues/${issueId}`\n );\n }\n\n async removeIssueFromEpic(groupId: string, epicIid: number, epicIssueId: number) {\n const encodedGroup = encodeURIComponent(groupId);\n return this.fetch<Record<string, unknown>>(\n 'DELETE',\n `/groups/${encodedGroup}/epics/${epicIid}/issues/${epicIssueId}`\n );\n }\n\n /**\n * List notes on an epic using GraphQL API with pagination support\n */\n async listEpicNotes(\n groupId: string,\n epicIid: number,\n options?: NotesPaginationOptions\n ): Promise<NotesResult> {\n const variables: Record<string, unknown> = {\n groupPath: groupId,\n epicIid: String(epicIid),\n ...buildPaginationVariables(options),\n };\n\n const result = await this.fetchGraphQL<{\n group: {\n epic: {\n notes: NotesConnection;\n };\n };\n }>(LIST_EPIC_NOTES_QUERY, variables);\n\n const notes = result.group?.epic?.notes;\n if (!notes) {\n throw new Error('Epic not found or access denied');\n }\n\n return {\n notes,\n pageInfo: notes.pageInfo,\n totalCount: notes.count,\n };\n }\n\n /**\n * List discussions on an epic using GraphQL API with pagination support\n */\n async listEpicDiscussions(\n groupId: string,\n epicIid: number,\n options?: DiscussionsPaginationOptions\n ): Promise<DiscussionsResult> {\n const variables: Record<string, unknown> = {\n groupPath: groupId,\n epicIid: String(epicIid),\n ...buildDiscussionsPaginationVariables(options),\n };\n\n const result = await this.fetchGraphQL<{\n group: {\n epic: {\n discussions: DiscussionsConnection;\n };\n };\n }>(LIST_EPIC_DISCUSSIONS_QUERY, variables);\n\n const discussions = result.group?.epic?.discussions;\n if (!discussions) {\n throw new Error('Epic not found or access denied');\n }\n\n return { discussions };\n }\n\n async getEpicDiscussion(groupId: string, epicIid: number, discussionId: string) {\n const encodedGroup = encodeURIComponent(groupId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/groups/${encodedGroup}/epics/${epicIid}/discussions/${discussionId}`\n );\n }\n\n async createEpicNote(groupId: string, epicIid: number, body: string, discussionId?: string) {\n const encodedGroup = encodeURIComponent(groupId);\n if (discussionId) {\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/groups/${encodedGroup}/epics/${epicIid}/discussions/${discussionId}/notes`,\n { body }\n );\n }\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/groups/${encodedGroup}/epics/${epicIid}/notes`,\n { body }\n );\n }\n\n async getEpicNote(groupId: string, epicIid: number, noteId: number) {\n const encodedGroup = encodeURIComponent(groupId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/groups/${encodedGroup}/epics/${epicIid}/notes/${noteId}`\n );\n }\n\n async updateEpicNote(groupId: string, epicIid: number, noteId: number, body: string) {\n const encodedGroup = encodeURIComponent(groupId);\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/groups/${encodedGroup}/epics/${epicIid}/notes/${noteId}`,\n { body }\n );\n }\n}\n","import { GitLabApiClient } from './base.js';\nimport {\n NotesResult,\n NotesConnection,\n NotesPaginationOptions,\n NOTES_FRAGMENT,\n NOTES_CONNECTION_FRAGMENT,\n buildPaginationVariables,\n} from './notes-types.js';\nimport {\n DiscussionsResult,\n DiscussionsConnection,\n DiscussionsPaginationOptions,\n DISCUSSION_NOTE_FRAGMENT,\n DISCUSSION_FRAGMENT,\n DISCUSSIONS_CONNECTION_FRAGMENT,\n buildDiscussionsPaginationVariables,\n} from './discussions-types.js';\n\nconst LIST_SNIPPET_NOTES_QUERY = `\n ${NOTES_FRAGMENT}\n ${NOTES_CONNECTION_FRAGMENT}\n query listSnippetNotes(\n $snippetGid: SnippetID!\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n snippets(ids: [$snippetGid]) {\n nodes {\n notes(\n first: $first\n after: $after\n last: $last\n before: $before\n ) {\n ...NotesConnectionFields\n }\n }\n }\n }\n`;\n\nconst LIST_SNIPPET_DISCUSSIONS_QUERY = `\n ${DISCUSSION_NOTE_FRAGMENT}\n ${DISCUSSION_FRAGMENT}\n ${DISCUSSIONS_CONNECTION_FRAGMENT}\n query listSnippetDiscussions(\n $snippetGid: SnippetID!\n $first: Int\n $after: String\n $last: Int\n $before: String\n ) {\n snippets(ids: [$snippetGid]) {\n nodes {\n discussions(\n first: $first\n after: $after\n last: $last\n before: $before\n ) {\n ...DiscussionsConnectionFields\n }\n }\n }\n }\n`;\n\n/**\n * GitLab API client for Snippet operations\n */\nexport class SnippetsClient extends GitLabApiClient {\n /**\n * List notes on a snippet using GraphQL API with pagination support\n */\n async listSnippetNotes(\n projectId: string,\n snippetId: number,\n options?: NotesPaginationOptions\n ): Promise<NotesResult> {\n const variables: Record<string, unknown> = {\n snippetGid: `gid://gitlab/ProjectSnippet/${snippetId}`,\n ...buildPaginationVariables(options),\n };\n\n const result = await this.fetchGraphQL<{\n snippets: {\n nodes: Array<{\n notes: NotesConnection;\n }>;\n };\n }>(LIST_SNIPPET_NOTES_QUERY, variables);\n\n const notes = result.snippets.nodes[0]?.notes || {\n nodes: [],\n pageInfo: {\n hasNextPage: false,\n hasPreviousPage: false,\n startCursor: null,\n endCursor: null,\n },\n count: 0,\n };\n\n return {\n notes,\n pageInfo: notes.pageInfo,\n totalCount: notes.count,\n };\n }\n\n /**\n * List discussions on a snippet using GraphQL API with pagination support\n */\n async listSnippetDiscussions(\n projectId: string,\n snippetId: number,\n options?: DiscussionsPaginationOptions\n ): Promise<DiscussionsResult> {\n const variables: Record<string, unknown> = {\n snippetGid: `gid://gitlab/ProjectSnippet/${snippetId}`,\n ...buildDiscussionsPaginationVariables(options),\n };\n\n const result = await this.fetchGraphQL<{\n snippets: {\n nodes: Array<{\n discussions: DiscussionsConnection;\n }>;\n };\n }>(LIST_SNIPPET_DISCUSSIONS_QUERY, variables);\n\n const discussions = result.snippets.nodes[0]?.discussions || {\n nodes: [],\n pageInfo: {\n hasNextPage: false,\n hasPreviousPage: false,\n startCursor: null,\n endCursor: null,\n },\n };\n\n return { discussions };\n }\n\n async getSnippetDiscussion(projectId: string, snippetId: number, discussionId: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/snippets/${snippetId}/discussions/${discussionId}`\n );\n }\n\n async createSnippetNote(\n projectId: string,\n snippetId: number,\n body: string,\n discussionId?: string\n ) {\n const encodedProject = this.encodeProjectId(projectId);\n if (discussionId) {\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/snippets/${snippetId}/discussions/${discussionId}/notes`,\n { body }\n );\n }\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/snippets/${snippetId}/notes`,\n { body }\n );\n }\n\n async createSnippetDiscussion(projectId: string, snippetId: number, body: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/snippets/${snippetId}/discussions`,\n { body }\n );\n }\n\n async updateSnippetNote(projectId: string, snippetId: number, noteId: number, body: string) {\n const encodedProject = this.encodeProjectId(projectId);\n return this.fetch<Record<string, unknown>>(\n 'PUT',\n `/projects/${encodedProject}/snippets/${snippetId}/notes/${noteId}`,\n { body }\n );\n }\n}\n","import { GitLabApiClient } from './base.js';\n\n/**\n * Resource identifier for discussion operations\n */\nexport interface DiscussionResourceId {\n projectId?: string;\n groupId?: string;\n iid?: number;\n sha?: string;\n snippetId?: number;\n}\n\n/**\n * GitLab API client for universal Discussion operations\n * Provides a consistent interface for discussions across all resource types\n */\nexport class DiscussionsClient extends GitLabApiClient {\n /**\n * Universal method to reply to any discussion thread\n * Supports: merge requests, issues, epics, commits, snippets\n */\n async replyToDiscussion(\n resourceType: 'merge_request' | 'issue' | 'epic' | 'commit' | 'snippet',\n resourceId: DiscussionResourceId,\n discussionId: string,\n body: string\n ): Promise<Record<string, unknown>> {\n switch (resourceType) {\n case 'merge_request': {\n if (!resourceId.projectId || !resourceId.iid) {\n throw new Error('projectId and iid are required for merge_request discussions');\n }\n const encodedProject = this.encodeProjectId(resourceId.projectId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/merge_requests/${resourceId.iid}/discussions/${discussionId}/notes`,\n { body }\n );\n }\n case 'issue': {\n if (!resourceId.projectId || !resourceId.iid) {\n throw new Error('projectId and iid are required for issue discussions');\n }\n const encodedProject = this.encodeProjectId(resourceId.projectId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/issues/${resourceId.iid}/discussions/${discussionId}/notes`,\n { body }\n );\n }\n case 'epic': {\n if (!resourceId.groupId || !resourceId.iid) {\n throw new Error('groupId and iid are required for epic discussions');\n }\n const encodedGroup = encodeURIComponent(resourceId.groupId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/groups/${encodedGroup}/epics/${resourceId.iid}/discussions/${discussionId}/notes`,\n { body }\n );\n }\n case 'commit': {\n if (!resourceId.projectId || !resourceId.sha) {\n throw new Error('projectId and sha are required for commit discussions');\n }\n const encodedProject = this.encodeProjectId(resourceId.projectId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/repository/commits/${resourceId.sha}/discussions/${discussionId}/notes`,\n { body }\n );\n }\n case 'snippet': {\n if (!resourceId.projectId || !resourceId.snippetId) {\n throw new Error('projectId and snippetId are required for snippet discussions');\n }\n const encodedProject = this.encodeProjectId(resourceId.projectId);\n return this.fetch<Record<string, unknown>>(\n 'POST',\n `/projects/${encodedProject}/snippets/${resourceId.snippetId}/discussions/${discussionId}/notes`,\n { body }\n );\n }\n default:\n throw new Error(`Unsupported resource type: ${resourceType}`);\n }\n }\n\n /**\n * Universal method to get a specific discussion from any resource type\n * Supports: merge requests, issues, epics, commits, snippets\n */\n async getDiscussion(\n resourceType: 'merge_request' | 'issue' | 'epic' | 'commit' | 'snippet',\n resourceId: DiscussionResourceId,\n discussionId: string\n ): Promise<Record<string, unknown>> {\n switch (resourceType) {\n case 'merge_request': {\n if (!resourceId.projectId || !resourceId.iid) {\n throw new Error('projectId and iid are required for merge_request discussions');\n }\n const encodedProject = this.encodeProjectId(resourceId.projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/merge_requests/${resourceId.iid}/discussions/${discussionId}`\n );\n }\n case 'issue': {\n if (!resourceId.projectId || !resourceId.iid) {\n throw new Error('projectId and iid are required for issue discussions');\n }\n const encodedProject = this.encodeProjectId(resourceId.projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/issues/${resourceId.iid}/discussions/${discussionId}`\n );\n }\n case 'epic': {\n if (!resourceId.groupId || !resourceId.iid) {\n throw new Error('groupId and iid are required for epic discussions');\n }\n const encodedGroup = encodeURIComponent(resourceId.groupId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/groups/${encodedGroup}/epics/${resourceId.iid}/discussions/${discussionId}`\n );\n }\n case 'commit': {\n if (!resourceId.projectId || !resourceId.sha) {\n throw new Error('projectId and sha are required for commit discussions');\n }\n const encodedProject = this.encodeProjectId(resourceId.projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/repository/commits/${resourceId.sha}/discussions/${discussionId}`\n );\n }\n case 'snippet': {\n if (!resourceId.projectId || !resourceId.snippetId) {\n throw new Error('projectId and snippetId are required for snippet discussions');\n }\n const encodedProject = this.encodeProjectId(resourceId.projectId);\n return this.fetch<Record<string, unknown>>(\n 'GET',\n `/projects/${encodedProject}/snippets/${resourceId.snippetId}/discussions/${discussionId}`\n );\n }\n default:\n throw new Error(`Unsupported resource type: ${resourceType}`);\n }\n }\n}\n","import { GitLabApiClient } from './base.js';\n\nexport interface AuditEvent {\n id: number;\n author_id: number;\n entity_id: number;\n entity_type: string;\n details: Record<string, unknown>;\n created_at: string;\n author_name?: string;\n ip_address?: string;\n target_details?: string;\n target_type?: string;\n target_id?: number;\n}\n\nexport interface AuditEventOptions {\n created_after?: string; // ISO 8601 format\n created_before?: string; // ISO 8601 format\n entity_type?: string;\n entity_id?: number;\n author_id?: number;\n per_page?: number;\n page?: number;\n}\n\n/**\n * Client for GitLab Audit Events API\n * Note: Requires appropriate permissions (project/group owner or instance admin)\n */\nexport class AuditClient extends GitLabApiClient {\n /**\n * List audit events for a project\n * Requires: Project owner role\n * API: GET /projects/:id/audit_events\n */\n async listProjectAuditEvents(\n projectId: string,\n options: AuditEventOptions = {}\n ): Promise<AuditEvent[]> {\n const encodedId = this.encodeProjectId(projectId);\n const params = new URLSearchParams();\n\n if (options.created_after) params.append('created_after', options.created_after);\n if (options.created_before) params.append('created_before', options.created_before);\n if (options.entity_type) params.append('entity_type', options.entity_type);\n if (options.entity_id) params.append('entity_id', options.entity_id.toString());\n if (options.author_id) params.append('author_id', options.author_id.toString());\n if (options.per_page) params.append('per_page', options.per_page.toString());\n if (options.page) params.append('page', options.page.toString());\n\n const query = params.toString();\n const path = `/projects/${encodedId}/audit_events${query ? `?${query}` : ''}`;\n\n return this.fetch<AuditEvent[]>('GET', path);\n }\n\n /**\n * List audit events for a group\n * Requires: Group owner role\n * API: GET /groups/:id/audit_events\n */\n async listGroupAuditEvents(\n groupId: string,\n options: AuditEventOptions = {}\n ): Promise<AuditEvent[]> {\n const encodedId = encodeURIComponent(groupId);\n const params = new URLSearchParams();\n\n if (options.created_after) params.append('created_after', options.created_after);\n if (options.created_before) params.append('created_before', options.created_before);\n if (options.entity_type) params.append('entity_type', options.entity_type);\n if (options.entity_id) params.append('entity_id', options.entity_id.toString());\n if (options.author_id) params.append('author_id', options.author_id.toString());\n if (options.per_page) params.append('per_page', options.per_page.toString());\n if (options.page) params.append('page', options.page.toString());\n\n const query = params.toString();\n const path = `/groups/${encodedId}/audit_events${query ? `?${query}` : ''}`;\n\n return this.fetch<AuditEvent[]>('GET', path);\n }\n\n /**\n * List instance-level audit events\n * Requires: Administrator access\n * API: GET /audit_events\n */\n async listInstanceAuditEvents(options: AuditEventOptions = {}): Promise<AuditEvent[]> {\n const params = new URLSearchParams();\n\n if (options.created_after) params.append('created_after', options.created_after);\n if (options.created_before) params.append('created_before', options.created_before);\n if (options.entity_type) params.append('entity_type', options.entity_type);\n if (options.entity_id) params.append('entity_id', options.entity_id.toString());\n if (options.author_id) params.append('author_id', options.author_id.toString());\n if (options.per_page) params.append('per_page', options.per_page.toString());\n if (options.page) params.append('page', options.page.toString());\n\n const query = params.toString();\n const path = `/audit_events${query ? `?${query}` : ''}`;\n\n return this.fetch<AuditEvent[]>('GET', path);\n }\n}\n","import { GitLabApiClient } from './base.js';\n\n/**\n * Award emoji response from GitLab API\n */\nexport interface AwardEmoji {\n id: number;\n name: string;\n user: {\n id: number;\n username: string;\n name: string;\n state: string;\n avatar_url: string;\n web_url: string;\n };\n created_at: string;\n updated_at: string;\n awardable_id: number;\n awardable_type: string;\n}\n\n/**\n * Supported resource types for award emoji\n */\nexport type AwardableResourceType = 'merge_request' | 'issue' | 'snippet';\n\n/**\n * Resource identifier for award emoji operations\n */\nexport interface AwardEmojiResourceId {\n projectId: string;\n resourceType: AwardableResourceType;\n resourceIid: number;\n noteId?: number;\n}\n\n/**\n * GitLab API client for Award Emoji (reactions) operations\n * Supports adding/removing emoji reactions on MRs, issues, snippets and their notes\n *\n * API docs: https://docs.gitlab.com/ee/api/award_emoji.html\n */\nexport class AwardEmojiClient extends GitLabApiClient {\n /**\n * Build the base path for award emoji operations\n */\n private buildAwardEmojiPath(resource: AwardEmojiResourceId): string {\n const encodedProject = this.encodeProjectId(resource.projectId);\n\n let basePath: string;\n switch (resource.resourceType) {\n case 'merge_request':\n basePath = `/projects/${encodedProject}/merge_requests/${resource.resourceIid}`;\n break;\n case 'issue':\n basePath = `/projects/${encodedProject}/issues/${resource.resourceIid}`;\n break;\n case 'snippet':\n basePath = `/projects/${encodedProject}/snippets/${resource.resourceIid}`;\n break;\n }\n\n if (resource.noteId) {\n return `${basePath}/notes/${resource.noteId}/award_emoji`;\n }\n return `${basePath}/award_emoji`;\n }\n\n /**\n * List all award emoji on a resource or note\n */\n async listAwardEmoji(resource: AwardEmojiResourceId): Promise<AwardEmoji[]> {\n const path = this.buildAwardEmojiPath(resource);\n return this.fetch<AwardEmoji[]>('GET', path);\n }\n\n /**\n * Get a single award emoji by ID\n */\n async getAwardEmoji(resource: AwardEmojiResourceId, awardId: number): Promise<AwardEmoji> {\n const path = `${this.buildAwardEmojiPath(resource)}/${awardId}`;\n return this.fetch<AwardEmoji>('GET', path);\n }\n\n /**\n * Add an award emoji (reaction) to a resource or note\n *\n * @param resource - The resource to add the emoji to\n * @param name - The emoji name without colons (e.g., 'thumbsup', 'rocket', 'eyes')\n */\n async createAwardEmoji(resource: AwardEmojiResourceId, name: string): Promise<AwardEmoji> {\n const path = this.buildAwardEmojiPath(resource);\n return this.fetch<AwardEmoji>('POST', path, { name });\n }\n\n /**\n * Remove an award emoji from a resource or note\n */\n async deleteAwardEmoji(resource: AwardEmojiResourceId, awardId: number): Promise<void> {\n const path = `${this.buildAwardEmojiPath(resource)}/${awardId}`;\n await this.fetch<void>('DELETE', path);\n }\n}\n","import { GitLabApiClient as BaseClient } from './base.js';\nimport { MergeRequestsClient } from './merge-requests.js';\nimport { IssuesClient } from './issues.js';\nimport { WorkItemsClient } from './work-items.js';\nimport { PipelinesClient } from './pipelines.js';\nimport { RepositoryClient } from './repository.js';\nimport { SearchClient } from './search.js';\nimport { ProjectsClient } from './projects.js';\nimport { UsersClient } from './users.js';\nimport { WikisClient } from './wikis.js';\nimport { SecurityClient } from './security.js';\nimport { TodosClient } from './todos.js';\nimport { EpicsClient } from './epics.js';\nimport { SnippetsClient } from './snippets.js';\nimport { DiscussionsClient } from './discussions.js';\nimport { AuditClient } from './audit.js';\nimport { AwardEmojiClient } from './award-emoji.js';\n\n// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging\nclass UnifiedGitLabClient extends BaseClient {}\n// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging\ninterface UnifiedGitLabClient\n extends\n MergeRequestsClient,\n IssuesClient,\n WorkItemsClient,\n PipelinesClient,\n RepositoryClient,\n SearchClient,\n ProjectsClient,\n UsersClient,\n WikisClient,\n SecurityClient,\n TodosClient,\n EpicsClient,\n SnippetsClient,\n DiscussionsClient,\n AuditClient,\n AwardEmojiClient {}\n\ntype Constructor = new (...args: never[]) => object;\n\nfunction applyMixins(derivedCtor: Constructor, constructors: Constructor[]) {\n constructors.forEach((baseCtor) => {\n Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => {\n Object.defineProperty(\n derivedCtor.prototype,\n name,\n Object.getOwnPropertyDescriptor(baseCtor.prototype, name) || Object.create(null)\n );\n });\n });\n}\n\napplyMixins(UnifiedGitLabClient, [\n MergeRequestsClient,\n IssuesClient,\n WorkItemsClient,\n PipelinesClient,\n RepositoryClient,\n SearchClient,\n ProjectsClient,\n UsersClient,\n WikisClient,\n SecurityClient,\n TodosClient,\n EpicsClient,\n SnippetsClient,\n DiscussionsClient,\n AuditClient,\n AwardEmojiClient,\n]);\n\nexport { UnifiedGitLabClient as GitLabApiClient };\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const issueTools = {\n gitlab_create_issue: tool({\n description: `Create a new issue in a GitLab project.\nReturns the created issue with all details including IID, web URL, and metadata.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n title: z.string().describe('The title of the issue'),\n description: z\n .string()\n .optional()\n .describe('The description of the issue (supports Markdown)'),\n assignee_ids: z\n .array(z.number())\n .optional()\n .describe('Array of user IDs to assign the issue to'),\n milestone_id: z\n .number()\n .optional()\n .describe('The ID of the milestone to assign the issue to'),\n labels: z\n .string()\n .optional()\n .describe('Comma-separated list of label names (e.g., \"bug,critical\")'),\n due_date: z\n .string()\n .optional()\n .describe('Due date for the issue in YYYY-MM-DD format (e.g., \"2025-12-31\")'),\n confidential: z.boolean().optional().describe('Whether the issue should be confidential'),\n weight: z.number().optional().describe('The weight of the issue (for issue boards)'),\n epic_id: z\n .number()\n .optional()\n .describe('The ID of the epic to add the issue to (Premium/Ultimate)'),\n issue_type: z\n .enum(['issue', 'incident', 'test_case', 'task'])\n .optional()\n .describe('The type of issue (default: issue)'),\n },\n execute: async (\n args: {\n project_id: string;\n title: string;\n description?: string;\n assignee_ids?: number[];\n milestone_id?: number;\n labels?: string;\n due_date?: string;\n confidential?: boolean;\n weight?: number;\n epic_id?: number;\n issue_type?: 'issue' | 'incident' | 'test_case' | 'task';\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const issue = await client.createIssue(args.project_id, args.title, {\n description: args.description,\n assignee_ids: args.assignee_ids,\n milestone_id: args.milestone_id,\n labels: args.labels,\n due_date: args.due_date,\n confidential: args.confidential,\n weight: args.weight,\n epic_id: args.epic_id,\n issue_type: args.issue_type,\n });\n return JSON.stringify(issue, null, 2);\n },\n }),\n\n gitlab_get_issue: tool({\n description: `Get details of a specific issue by project and issue IID.\nReturns: title, description, state, author, assignees, labels, milestone, weight, and comments.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n issue_iid: z.number().describe('The internal ID of the issue within the project'),\n },\n execute: async (args: { project_id: string; issue_iid: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const issue = await client.getIssue(args.project_id, args.issue_iid);\n return JSON.stringify(issue, null, 2);\n },\n }),\n\n gitlab_list_issues: tool({\n description: `List issues for a project or search globally.\nCan filter by state, labels, assignee, milestone.\n\nIMPORTANT: Response includes pagination info. If nextPage exists, there are more results.\nAlways paginate until you get an empty response or no nextPage to ensure you have all data.`,\n args: {\n project_id: z\n .string()\n .optional()\n .describe('The project ID or path. If not provided, searches globally.'),\n state: z\n .enum(['opened', 'closed', 'all'])\n .optional()\n .describe('Filter by issue state (default: opened)'),\n scope: z\n .enum(['assigned_to_me', 'created_by_me', 'all'])\n .optional()\n .describe('Filter by scope'),\n search: z.string().optional().describe('Search issues by title or description'),\n labels: z.string().optional().describe('Comma-separated list of labels to filter by'),\n milestone: z.string().optional().describe('Filter by milestone title'),\n limit: z.number().optional().describe('Maximum number of results per page (default: 20)'),\n page: z.number().optional().describe('Page number for pagination (default: 1)'),\n },\n execute: async (\n args: {\n project_id?: string;\n state?: 'opened' | 'closed' | 'all';\n scope?: 'assigned_to_me' | 'created_by_me' | 'all';\n search?: string;\n labels?: string;\n milestone?: string;\n limit?: number;\n page?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const result = await client.listIssues({\n projectId: args.project_id,\n state: args.state,\n scope: args.scope,\n search: args.search,\n labels: args.labels,\n milestone: args.milestone,\n limit: args.limit,\n page: args.page,\n });\n return JSON.stringify(result, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\n/**\n * Helper to return validation errors in a consistent format.\n */\nfunction validationError(message: string): string {\n return JSON.stringify({ error: message }, null, 2);\n}\n\nexport const epicTools = {\n gitlab_get_epic: tool({\n description: `Get details of a specific epic by group and epic IID.\nReturns: title, description, state, author, start/end dates, labels, associated issues, and child epics.`,\n args: {\n group_id: z\n .string()\n .describe(\n 'The group ID or URL-encoded path (e.g., \"gitlab-org\" or \"my-group/my-subgroup\")'\n ),\n epic_iid: z.number().describe('The internal ID of the epic within the group'),\n },\n execute: async (args: { group_id: string; epic_iid: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const epic = await client.getEpic(args.group_id, args.epic_iid);\n return JSON.stringify(epic, null, 2);\n },\n }),\n\n gitlab_list_epics: tool({\n description: `List epics for a group with filtering capabilities.\nCan filter by state (opened, closed, all), author, labels, and search query.`,\n args: {\n group_id: z.string().describe('The group ID or URL-encoded path'),\n state: z\n .enum(['opened', 'closed', 'all'])\n .optional()\n .describe('Filter by epic state (default: opened)'),\n author_id: z.number().optional().describe('Filter by author user ID'),\n labels: z.string().optional().describe('Comma-separated list of labels to filter by'),\n search: z.string().optional().describe('Search epics by title or description'),\n limit: z.number().optional().describe('Maximum number of results (default: 20)'),\n },\n execute: async (\n args: {\n group_id: string;\n state?: 'opened' | 'closed' | 'all';\n author_id?: number;\n labels?: string;\n search?: string;\n limit?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const epics = await client.listEpics({\n groupId: args.group_id,\n state: args.state,\n author_id: args.author_id,\n labels: args.labels,\n search: args.search,\n limit: args.limit,\n });\n return JSON.stringify(epics, null, 2);\n },\n }),\n\n gitlab_create_epic: tool({\n description: `Create a new epic in a group.\nReturns the created epic with all details.`,\n args: {\n group_id: z.string().describe('The group ID or URL-encoded path'),\n title: z.string().describe('The title of the epic'),\n description: z\n .string()\n .optional()\n .describe('The description of the epic (supports Markdown)'),\n labels: z.string().optional().describe('Comma-separated list of labels'),\n start_date: z.string().optional().describe('Start date in YYYY-MM-DD format'),\n end_date: z.string().optional().describe('Due/end date in YYYY-MM-DD format'),\n confidential: z\n .boolean()\n .optional()\n .describe('Whether the epic is confidential (default: false)'),\n },\n execute: async (\n args: {\n group_id: string;\n title: string;\n description?: string;\n labels?: string;\n start_date?: string;\n end_date?: string;\n confidential?: boolean;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const epic = await client.createEpic(args.group_id, {\n title: args.title,\n description: args.description,\n labels: args.labels,\n start_date: args.start_date,\n end_date: args.end_date,\n confidential: args.confidential,\n });\n return JSON.stringify(epic, null, 2);\n },\n }),\n\n gitlab_update_epic: tool({\n description: `Update an existing epic.\nCan update title, description, labels, dates, state, and confidentiality.`,\n args: {\n group_id: z.string().describe('The group ID or URL-encoded path'),\n epic_iid: z.number().describe('The internal ID of the epic'),\n title: z.string().optional().describe('The new title'),\n description: z.string().optional().describe('The new description (supports Markdown)'),\n labels: z.string().optional().describe('Comma-separated list of labels'),\n start_date: z.string().optional().describe('Start date in YYYY-MM-DD format'),\n end_date: z.string().optional().describe('Due/end date in YYYY-MM-DD format'),\n state_event: z\n .enum(['close', 'reopen'])\n .optional()\n .describe('Change the state (close or reopen)'),\n confidential: z.boolean().optional().describe('Whether the epic is confidential'),\n },\n execute: async (\n args: {\n group_id: string;\n epic_iid: number;\n title?: string;\n description?: string;\n labels?: string;\n start_date?: string;\n end_date?: string;\n state_event?: 'close' | 'reopen';\n confidential?: boolean;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const epic = await client.updateEpic(args.group_id, args.epic_iid, {\n title: args.title,\n description: args.description,\n labels: args.labels,\n start_date: args.start_date,\n end_date: args.end_date,\n state_event: args.state_event,\n confidential: args.confidential,\n });\n return JSON.stringify(epic, null, 2);\n },\n }),\n\n gitlab_manage_epic_issues: tool({\n description: `Manage issues linked to a GitLab epic.\n\nActions:\n- list: Get all issues associated with the epic\n- add: Link an existing issue to the epic (issue can be from any project within the group hierarchy)\n- remove: Unlink an issue from the epic\n\nExamples:\n- List issues: action=\"list\", group_id=\"gitlab-org\", epic_iid=123\n- Add issue: action=\"add\", group_id=\"gitlab-org\", epic_iid=123, issue_id=456\n- Remove issue: action=\"remove\", group_id=\"gitlab-org\", epic_iid=123, epic_issue_id=789\n\nNote: The epic_issue_id (for remove) is the ID of the epic-issue association, which can be obtained from the list action response.`,\n args: {\n action: z.enum(['list', 'add', 'remove']).describe('The action to perform'),\n group_id: z.string().describe('The group ID or URL-encoded path'),\n epic_iid: z.number().describe('The internal ID of the epic within the group'),\n issue_id: z\n .number()\n .optional()\n .describe('The global ID of the issue to add (required for \"add\" action)'),\n epic_issue_id: z\n .number()\n .optional()\n .describe(\n 'The ID of the epic-issue association to remove (required for \"remove\" action, from list response)'\n ),\n },\n execute: async (\n args: {\n action: 'list' | 'add' | 'remove';\n group_id: string;\n epic_iid: number;\n issue_id?: number;\n epic_issue_id?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n\n switch (args.action) {\n case 'list': {\n const issues = await client.listEpicIssues(args.group_id, args.epic_iid);\n return JSON.stringify(issues, null, 2);\n }\n case 'add': {\n if (args.issue_id === undefined) {\n return validationError('issue_id is required for \"add\" action');\n }\n const result = await client.addIssueToEpic(args.group_id, args.epic_iid, args.issue_id);\n return JSON.stringify(result, null, 2);\n }\n case 'remove': {\n if (args.epic_issue_id === undefined) {\n return validationError('epic_issue_id is required for \"remove\" action');\n }\n const result = await client.removeIssueFromEpic(\n args.group_id,\n args.epic_iid,\n args.epic_issue_id\n );\n return JSON.stringify(result, null, 2);\n }\n }\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const pipelineTools = {\n gitlab_list_pipelines: tool({\n description: `List pipelines for a project.\nCan filter by status, ref (branch/tag), username.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n status: z\n .enum(['running', 'pending', 'success', 'failed', 'canceled', 'skipped', 'manual'])\n .optional()\n .describe('Filter by pipeline status'),\n ref: z.string().optional().describe('Filter by branch or tag name'),\n limit: z.number().optional().describe('Maximum number of results (default: 20)'),\n },\n execute: async (\n args: {\n project_id: string;\n status?: 'running' | 'pending' | 'success' | 'failed' | 'canceled' | 'skipped' | 'manual';\n ref?: string;\n limit?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const pipelines = await client.listPipelines(args.project_id, {\n status: args.status,\n ref: args.ref,\n limit: args.limit,\n });\n return JSON.stringify(pipelines, null, 2);\n },\n }),\n\n gitlab_get_pipeline: tool({\n description: `Get details of a specific pipeline including its jobs.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n pipeline_id: z.number().describe('The ID of the pipeline'),\n },\n execute: async (args: { project_id: string; pipeline_id: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const pipeline = await client.getPipeline(args.project_id, args.pipeline_id);\n return JSON.stringify(pipeline, null, 2);\n },\n }),\n\n gitlab_list_pipeline_jobs: tool({\n description: `List jobs for a pipeline, optionally filter by scope (failed, success, etc).`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n pipeline_id: z.number().describe('The ID of the pipeline'),\n scope: z\n .enum([\n 'created',\n 'pending',\n 'running',\n 'failed',\n 'success',\n 'canceled',\n 'skipped',\n 'manual',\n ])\n .optional()\n .describe('Filter jobs by scope/status'),\n },\n execute: async (\n args: {\n project_id: string;\n pipeline_id: number;\n scope?:\n | 'created'\n | 'pending'\n | 'running'\n | 'failed'\n | 'success'\n | 'canceled'\n | 'skipped'\n | 'manual';\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const jobs = await client.listPipelineJobs(args.project_id, args.pipeline_id, args.scope);\n return JSON.stringify(jobs, null, 2);\n },\n }),\n\n gitlab_get_job_log: tool({\n description: `Get the log/trace output of a specific CI job.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n job_id: z.number().describe('The ID of the job'),\n },\n execute: async (args: { project_id: string; job_id: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n return client.getJobLog(args.project_id, args.job_id);\n },\n }),\n\n gitlab_retry_job: tool({\n description: `Retry a failed or canceled CI job.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n job_id: z.number().describe('The ID of the job to retry'),\n },\n execute: async (args: { project_id: string; job_id: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const job = await client.retryJob(args.project_id, args.job_id);\n return JSON.stringify(job, null, 2);\n },\n }),\n\n gitlab_get_pipeline_failing_jobs: tool({\n description: `Get all failed jobs in a pipeline.\nReturns only the jobs that have failed, making it easier to debug pipeline failures.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n pipeline_id: z.number().describe('The ID of the pipeline'),\n },\n execute: async (args: { project_id: string; pipeline_id: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const jobs = await client.getPipelineFailingJobs(args.project_id, args.pipeline_id);\n return JSON.stringify(jobs, null, 2);\n },\n }),\n\n gitlab_lint_ci_config: tool({\n description: `Validate a CI/CD YAML configuration against GitLab CI syntax rules.\nThis validates the configuration in the context of the project, including:\n- Using the project's CI/CD variables\n- Searching the project's files for include:local entries\n- Optionally simulating pipeline creation (dry_run)\n- Optionally including the list of jobs that would be created\n\nModes:\n- content: Validate provided YAML content (requires 'content' parameter)\n- existing: Validate the existing .gitlab-ci.yml from the repository\n\nReturns validation result with:\n- valid: boolean indicating if configuration is valid\n- errors: array of error messages\n- warnings: array of warning messages\n- merged_yaml: the final merged YAML after processing includes (optional)\n- includes: list of included files (for existing mode)\n- jobs: list of jobs that would be created (optional, requires include_jobs=true)\n\nExamples:\n- Validate content: mode=\"content\", project_id=\"group/project\", content=\"stages: [build]...\"\n- Validate existing: mode=\"existing\", project_id=\"group/project\"`,\n args: {\n mode: z\n .enum(['content', 'existing'])\n .describe('Validation mode: \"content\" for provided YAML, \"existing\" for repo file'),\n project_id: z.string().describe('The project ID or URL-encoded path'),\n content: z\n .string()\n .optional()\n .describe('The CI/CD configuration content (YAML as string) - required for mode=\"content\"'),\n dry_run: z\n .boolean()\n .optional()\n .describe('Run pipeline creation simulation instead of just static check (default: false)'),\n include_jobs: z\n .boolean()\n .optional()\n .describe('Include list of jobs that would be created in the response (default: false)'),\n ref: z\n .string()\n .optional()\n .describe(\n 'Branch or tag context to use for validation (defaults to project default branch)'\n ),\n content_ref: z\n .string()\n .optional()\n .describe(\n 'For mode=\"existing\": Commit SHA, branch or tag to get CI config from (defaults to project default branch)'\n ),\n },\n execute: async (\n args: {\n mode: 'content' | 'existing';\n project_id: string;\n content?: string;\n dry_run?: boolean;\n include_jobs?: boolean;\n ref?: string;\n content_ref?: string;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n\n switch (args.mode) {\n case 'content': {\n if (!args.content) {\n return JSON.stringify({ error: 'content is required when mode is \"content\"' }, null, 2);\n }\n const result = await client.lintCiConfig(args.project_id, args.content, {\n dry_run: args.dry_run,\n include_jobs: args.include_jobs,\n ref: args.ref,\n });\n return JSON.stringify(result, null, 2);\n }\n case 'existing': {\n const result = await client.lintExistingCiConfig(args.project_id, {\n content_ref: args.content_ref,\n dry_run: args.dry_run,\n dry_run_ref: args.ref,\n include_jobs: args.include_jobs,\n });\n return JSON.stringify(result, null, 2);\n }\n }\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const repositoryTools = {\n gitlab_get_file: tool({\n description: `Get the contents of a file from a repository.\nSupports fetching files from any branch, tag, or commit SHA.\nAn explicit ref is required by the GitLab repository files API.\nNote: Invalid refs will result in a 404 error from the GitLab API.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n file_path: z.string().describe('Path to the file in the repository'),\n ref: z\n .string()\n .trim()\n .min(1)\n .describe(\n 'Branch name, tag, or commit SHA to fetch the file from. ' +\n 'Supports full or short commit SHAs.'\n ),\n },\n execute: async (\n args: { project_id: string; file_path: string; ref: string },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n return client.getFile(args.project_id, args.file_path, args.ref);\n },\n }),\n\n gitlab_get_commit: tool({\n description: `Get a single commit with full details.\nReturns commit metadata including author, message, stats, and parent commits.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n sha: z.string().describe('The commit SHA'),\n },\n execute: async (args: { project_id: string; sha: string }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const commit = await client.getCommit(args.project_id, args.sha);\n return JSON.stringify(commit, null, 2);\n },\n }),\n\n gitlab_list_commits: tool({\n description: `List commits in a repository. Can filter by branch/ref and path.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n ref: z.string().optional().describe('Branch or tag name'),\n path: z.string().optional().describe('File or directory path to filter commits'),\n since: z.string().optional().describe('Only commits after this date (ISO 8601 format)'),\n until: z.string().optional().describe('Only commits before this date (ISO 8601 format)'),\n limit: z.number().optional().describe('Maximum number of results (default: 20)'),\n },\n execute: async (\n args: {\n project_id: string;\n ref?: string;\n path?: string;\n since?: string;\n until?: string;\n limit?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const commits = await client.listCommits(args.project_id, {\n ref: args.ref,\n path: args.path,\n since: args.since,\n until: args.until,\n limit: args.limit,\n });\n return JSON.stringify(commits, null, 2);\n },\n }),\n\n gitlab_get_commit_diff: tool({\n description: `Get the diff for a specific commit.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n sha: z.string().describe('The commit SHA'),\n },\n execute: async (args: { project_id: string; sha: string }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const diff = await client.getCommitDiff(args.project_id, args.sha);\n return JSON.stringify(diff, null, 2);\n },\n }),\n\n gitlab_list_repository_tree: tool({\n description: `List files and directories in a repository.\nReturns the tree structure of the repository at a given path and ref.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n path: z.string().optional().describe('Path inside repository (default: root)'),\n ref: z.string().optional().describe('Branch, tag, or commit SHA (default: default branch)'),\n recursive: z.boolean().optional().describe('Get recursive tree (default: false)'),\n per_page: z.number().optional().describe('Number of results per page (default: 20)'),\n },\n execute: async (\n args: {\n project_id: string;\n path?: string;\n ref?: string;\n recursive?: boolean;\n per_page?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const tree = await client.listRepositoryTree(args.project_id, {\n path: args.path,\n ref: args.ref,\n recursive: args.recursive,\n per_page: args.per_page,\n });\n return JSON.stringify(tree, null, 2);\n },\n }),\n\n gitlab_list_branches: tool({\n description: `List branches in a repository.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n search: z.string().optional().describe('Search branches by name'),\n },\n execute: async (args: { project_id: string; search?: string }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const branches = await client.listBranches(args.project_id, args.search);\n return JSON.stringify(branches, null, 2);\n },\n }),\n\n gitlab_get_commit_comments: tool({\n description: `Get all comments on a specific commit.\nReturns all comments (notes) that have been added to a commit, including line-specific comments.\nThis is different from discussions - it returns individual comments in a flat structure.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n sha: z.string().describe('The commit SHA'),\n },\n execute: async (args: { project_id: string; sha: string }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const comments = await client.getCommitComments(args.project_id, args.sha);\n return JSON.stringify(comments, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\n/**\n * All supported search scopes\n */\ntype SearchScope =\n | 'projects'\n | 'issues'\n | 'merge_requests'\n | 'milestones'\n | 'users'\n | 'blobs'\n | 'commits'\n | 'notes'\n | 'wiki_blobs'\n | 'group_projects';\n\n/**\n * Scopes that use the generic search API\n */\nconst GENERIC_SEARCH_SCOPES = ['projects', 'issues', 'merge_requests', 'blobs'] as const;\n\n/**\n * Scopes that use specialized client methods\n */\nconst SPECIALIZED_SCOPES = [\n 'milestones',\n 'users',\n 'commits',\n 'notes',\n 'wiki_blobs',\n 'group_projects',\n] as const;\n\n/**\n * All valid search scopes\n */\nconst ALL_SCOPES = [...GENERIC_SEARCH_SCOPES, ...SPECIALIZED_SCOPES] as const;\n\n/**\n * Scopes that support the 'ref' parameter\n */\nconst REF_SUPPORTED_SCOPES = ['commits', 'wiki_blobs'] as const;\n\n/**\n * Scopes that support the 'state' parameter\n */\nconst STATE_SUPPORTED_SCOPES = ['milestones'] as const;\n\n/**\n * Create a standardized validation error message\n */\nfunction validationError(param: string, scope: string): Error {\n return new Error(`Missing required parameter: '${param}' is required for scope '${scope}'`);\n}\n\n/**\n * Create an error for invalid parameter usage\n */\nfunction invalidParamError(param: string, validScopes: readonly string[]): Error {\n return new Error(\n `Invalid parameter: '${param}' is only valid for scopes: ${validScopes.join(', ')}`\n );\n}\n\n/**\n * Validate scope-specific required parameters and parameter combinations\n *\n * @example\n * // Valid: notes scope with project_id\n * validateSearchParams('notes', { project_id: 'my/project' });\n *\n * @example\n * // Invalid: ref with issues scope\n * validateSearchParams('issues', { ref: 'main' }); // throws error\n */\nfunction validateSearchParams(\n scope: SearchScope,\n args: {\n project_id?: string;\n group_id?: string;\n ref?: string;\n state?: string;\n }\n): void {\n // Validate required parameters\n switch (scope) {\n case 'notes':\n if (!args.project_id) throw validationError('project_id', scope);\n break;\n case 'group_projects':\n if (!args.group_id) throw validationError('group_id', scope);\n break;\n }\n\n // Validate scope-specific parameter combinations\n if (args.ref && !REF_SUPPORTED_SCOPES.includes(scope as (typeof REF_SUPPORTED_SCOPES)[number])) {\n throw invalidParamError('ref', REF_SUPPORTED_SCOPES);\n }\n\n if (\n args.state &&\n !STATE_SUPPORTED_SCOPES.includes(scope as (typeof STATE_SUPPORTED_SCOPES)[number])\n ) {\n throw invalidParamError('state', STATE_SUPPORTED_SCOPES);\n }\n}\n\nexport const searchTools = {\n /**\n * Unified search across all GitLab resources\n *\n * @example\n * // Search for issues in a project\n * gitlab_search({ scope: \"issues\", search: \"bug\", project_id: \"my-group/project\" })\n *\n * @example\n * // Search commits on specific branch\n * gitlab_search({ scope: \"commits\", search: \"fix\", ref: \"main\" })\n *\n * @example\n * // Search for projects within a group\n * gitlab_search({ scope: \"group_projects\", group_id: \"gitlab-org\", search: \"runner\" })\n *\n * @example\n * // Search notes/comments in a project\n * gitlab_search({ scope: \"notes\", search: \"LGTM\", project_id: \"my-group/project\" })\n */\n gitlab_search: tool({\n description: `Search across GitLab for various resources with scope-specific options.\n\nScopes and their requirements:\n- projects: Search projects by name/description\n- issues: Search issues by title/description\n- merge_requests: Search MRs by title/description\n- milestones: Search milestones (supports state filter)\n- users: Search users by name/email\n- blobs: Search file content (code search)\n- commits: Search commits by message/author/SHA (supports ref filter)\n- notes: Search comments/notes (requires project_id)\n- wiki_blobs: Search wiki content (supports ref filter)\n- group_projects: Search projects within a group (requires group_id)\n\nFor scopes other than milestones, state=\"all\" is treated as omitted because it does not filter results.\n\nExamples:\n- Issues: scope=\"issues\", search=\"bug\", project_id=\"my-group/my-project\"\n- Code: scope=\"blobs\", search=\"function calculateTotal\"\n- Commits: scope=\"commits\", search=\"fix login\", ref=\"main\"\n- Group projects: scope=\"group_projects\", group_id=\"gitlab-org\", search=\"runner\"\n- Notes: scope=\"notes\", search=\"LGTM\", project_id=\"my-group/my-project\"`,\n args: {\n scope: z\n .enum([\n 'projects',\n 'issues',\n 'merge_requests',\n 'milestones',\n 'users',\n 'blobs',\n 'commits',\n 'notes',\n 'wiki_blobs',\n 'group_projects',\n ])\n .describe('The type of resource to search'),\n search: z.string().describe('The search query'),\n // Context parameters\n project_id: z\n .string()\n .optional()\n .describe('Limit search to a specific project. Required for notes scope'),\n group_id: z\n .string()\n .optional()\n .describe('Group ID or path. Required for group_projects scope'),\n // Common options\n limit: z.number().optional().describe('Maximum number of results (default: 20)'),\n order_by: z\n .enum(['created_at'])\n .optional()\n .describe(\n 'Order results by field (for milestones, users, commits, notes, wiki_blobs, group_projects)'\n ),\n sort: z\n .enum(['asc', 'desc'])\n .optional()\n .describe('Sort order (for milestones, users, commits, notes, wiki_blobs, group_projects)'),\n // Scope-specific options\n ref: z.string().optional().describe('Branch or tag name (for commits, wiki_blobs scopes)'),\n state: z\n .enum(['active', 'closed', 'all'])\n .optional()\n .describe('Filter by state (for milestones scope)'),\n },\n execute: async (\n args: {\n scope: SearchScope;\n search: string;\n project_id?: string;\n group_id?: string;\n limit?: number;\n order_by?: 'created_at';\n sort?: 'asc' | 'desc';\n ref?: string;\n state?: 'active' | 'closed' | 'all';\n },\n _ctx: ToolContext\n ) => {\n // Some tool adapters populate optional enum fields with their no-op value.\n if (args.scope !== 'milestones' && args.state === 'all') {\n args.state = undefined;\n }\n\n // Validate scope-specific requirements and parameter combinations\n validateSearchParams(args.scope, {\n project_id: args.project_id,\n group_id: args.group_id,\n ref: args.ref,\n state: args.state,\n });\n\n const client = getGitLabClient();\n const commonOptions = {\n order_by: args.order_by,\n sort: args.sort,\n limit: args.limit,\n };\n\n switch (args.scope) {\n // Generic search API scopes\n case 'projects':\n case 'issues':\n case 'merge_requests':\n case 'blobs':\n return JSON.stringify(\n await client.search(args.scope, args.search, args.project_id, args.limit),\n null,\n 2\n );\n\n // Specialized scopes with dedicated client methods\n case 'milestones':\n return JSON.stringify(\n await client.searchMilestones(args.search, args.project_id, {\n ...commonOptions,\n state: args.state,\n }),\n null,\n 2\n );\n\n case 'users':\n return JSON.stringify(\n await client.searchUsers(args.search, args.project_id, commonOptions),\n null,\n 2\n );\n\n case 'commits':\n return JSON.stringify(\n await client.searchCommits(args.search, args.project_id, {\n ...commonOptions,\n ref: args.ref,\n }),\n null,\n 2\n );\n\n case 'notes':\n return JSON.stringify(\n await client.searchNotes(args.search, args.project_id!, commonOptions),\n null,\n 2\n );\n\n case 'wiki_blobs':\n return JSON.stringify(\n await client.searchWikiBlobs(args.search, args.project_id, {\n ...commonOptions,\n ref: args.ref,\n }),\n null,\n 2\n );\n\n case 'group_projects':\n return JSON.stringify(\n await client.searchGroupProjects(args.group_id!, args.search, commonOptions),\n null,\n 2\n );\n\n default:\n throw new Error(\n `Invalid scope '${args.scope}'. Must be one of: ${ALL_SCOPES.join(', ')}`\n );\n }\n },\n }),\n\n /**\n * Search GitLab official documentation\n * Separate tool because it uses a completely different API (docs.gitlab.com)\n */\n gitlab_documentation_search: tool({\n description: `Search GitLab official documentation at docs.gitlab.com.\nReturns relevant documentation pages matching the search query.\n\nUseful for:\n- Finding GitLab feature documentation\n- Learning about GitLab APIs and integrations\n- Discovering best practices and guides\n- Troubleshooting GitLab issues\n\nNote: This searches the public GitLab documentation site, not your instance's documentation.`,\n args: {\n search: z.string().describe('The search query (documentation topic or keyword)'),\n limit: z.number().optional().describe('Maximum number of results (default: 10)'),\n },\n execute: async (args: { search: string; limit?: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const results = await client.searchDocumentation(args.search, args.limit);\n return JSON.stringify(results, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const projectTools = {\n gitlab_get_project: tool({\n description: `Get details of a specific project.`,\n args: {\n project_id: z\n .string()\n .describe('The project ID or URL-encoded path (e.g., \"gitlab-org/gitlab\")'),\n },\n execute: async (args: { project_id: string }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const project = await client.getProject(args.project_id);\n return JSON.stringify(project, null, 2);\n },\n }),\n\n gitlab_list_project_members: tool({\n description: `List members of a project.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n },\n execute: async (args: { project_id: string }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const members = await client.listProjectMembers(args.project_id);\n return JSON.stringify(members, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const userTools = {\n gitlab_get_current_user: tool({\n description: `Get current user information.\nReturns details about the authenticated user including username, email, and permissions.`,\n args: {},\n execute: async (_args: Record<string, never>, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const user = await client.getCurrentUser();\n return JSON.stringify(user, null, 2);\n },\n }),\n\n gitlab_get_user: tool({\n description: `Get a user by their ID.\nReturns user details including username, name, state, and profile information.`,\n args: {\n user_id: z.number().describe('The user ID'),\n },\n execute: async (args: { user_id: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const user = await client.getUser(args.user_id);\n return JSON.stringify(user, null, 2);\n },\n }),\n\n gitlab_get_user_by_username: tool({\n description: `Find a user by their username.\nReturns user details including ID, name, state, and profile information.\nUseful for looking up a user's ID when you only know their username.`,\n args: {\n username: z.string().describe('The username to look up (without @ prefix)'),\n },\n execute: async (args: { username: string }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const username = args.username.replace(/^@/, '');\n const users = await client.getUserByUsername(username);\n if (users.length === 0) {\n return JSON.stringify({ error: `No user found with username: ${username}` });\n }\n if (users.length > 1) {\n return JSON.stringify(\n {\n warning: `Multiple users found for username: ${username}`,\n users,\n },\n null,\n 2\n );\n }\n return JSON.stringify(users[0], null, 2);\n },\n }),\n\n gitlab_get_user_status: tool({\n description: `Get a user's status including availability.\nReturns the user's status emoji, message, and availability (e.g., \"busy\").\nUseful for checking if someone is available before requesting a review.`,\n args: {\n user_id: z.number().describe('The user ID'),\n },\n execute: async (args: { user_id: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const status = await client.getUserStatus(args.user_id);\n return JSON.stringify(status, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const securityTools = {\n gitlab_list_vulnerabilities: tool({\n description: `List persisted vulnerabilities for a project.\nReturns security vulnerabilities detected in the project.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n state: z\n .enum(['detected', 'confirmed', 'dismissed', 'resolved'])\n .optional()\n .describe('Filter by vulnerability state'),\n severity: z\n .enum(['undefined', 'info', 'unknown', 'low', 'medium', 'high', 'critical'])\n .optional()\n .describe('Filter by severity level'),\n report_type: z\n .enum([\n 'sast',\n 'dast',\n 'dependency_scanning',\n 'container_scanning',\n 'secret_detection',\n 'coverage_fuzzing',\n 'api_fuzzing',\n ])\n .optional()\n .describe('Filter by report type'),\n limit: z.number().optional().describe('Maximum number of results (default: 20)'),\n },\n execute: async (\n args: {\n project_id: string;\n state?: 'detected' | 'confirmed' | 'dismissed' | 'resolved';\n severity?: 'undefined' | 'info' | 'unknown' | 'low' | 'medium' | 'high' | 'critical';\n report_type?:\n | 'sast'\n | 'dast'\n | 'dependency_scanning'\n | 'container_scanning'\n | 'secret_detection'\n | 'coverage_fuzzing'\n | 'api_fuzzing';\n limit?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const vulnerabilities = await client.listVulnerabilities(args.project_id, {\n state: args.state,\n severity: args.severity,\n report_type: args.report_type,\n limit: args.limit,\n });\n return JSON.stringify(vulnerabilities, null, 2);\n },\n }),\n\n gitlab_get_vulnerability_details: tool({\n description: `Get details for a specific vulnerability.\nReturns full information about a security vulnerability including description, location, and remediation.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n vulnerability_id: z.number().describe('The ID of the vulnerability'),\n },\n execute: async (args: { project_id: string; vulnerability_id: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const vulnerability = await client.getVulnerabilityDetails(\n args.project_id,\n args.vulnerability_id\n );\n return JSON.stringify(vulnerability, null, 2);\n },\n }),\n\n gitlab_create_vulnerability_issue: tool({\n description: `Create a new issue linked to one or more security vulnerabilities.\nThis creates an issue in the project and automatically links it to the specified vulnerabilities.\nRequires Developer role or higher.`,\n args: {\n project_path: z\n .string()\n .describe('Full path of the project (e.g., \"group/project\" or \"group/subgroup/project\")'),\n vulnerability_ids: z\n .array(z.string())\n .describe(\n 'Array of vulnerability IDs in format \"gid://gitlab/Vulnerability/{id}\". Get these from gitlab_list_vulnerabilities.'\n ),\n },\n execute: async (\n args: { project_path: string; vulnerability_ids: string[] },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const issue = await client.createVulnerabilityIssue(\n args.project_path,\n args.vulnerability_ids\n );\n return JSON.stringify(issue, null, 2);\n },\n }),\n\n gitlab_dismiss_vulnerability: tool({\n description: `Dismiss a security vulnerability with a reason.\nUse this when a vulnerability is not applicable, is a false positive, or has been mitigated.\nRequires Developer role or higher.`,\n args: {\n vulnerability_id: z\n .string()\n .describe(\n 'Vulnerability ID in format \"gid://gitlab/Vulnerability/{id}\". Get this from gitlab_list_vulnerabilities.'\n ),\n reason: z\n .enum([\n 'ACCEPTABLE_RISK',\n 'FALSE_POSITIVE',\n 'MITIGATING_CONTROL',\n 'USED_IN_TESTS',\n 'NOT_APPLICABLE',\n ])\n .describe('Reason for dismissing the vulnerability'),\n comment: z.string().optional().describe('Optional comment explaining the dismissal'),\n },\n execute: async (\n args: {\n vulnerability_id: string;\n reason:\n | 'ACCEPTABLE_RISK'\n | 'FALSE_POSITIVE'\n | 'MITIGATING_CONTROL'\n | 'USED_IN_TESTS'\n | 'NOT_APPLICABLE';\n comment?: string;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const vulnerability = await client.dismissVulnerability(\n args.vulnerability_id,\n args.reason,\n args.comment\n );\n return JSON.stringify(vulnerability, null, 2);\n },\n }),\n\n gitlab_confirm_vulnerability: tool({\n description: `Confirm a security vulnerability.\nUse this to acknowledge that a vulnerability is valid and needs attention.\nRequires Developer role or higher.`,\n args: {\n vulnerability_id: z\n .string()\n .describe(\n 'Vulnerability ID in format \"gid://gitlab/Vulnerability/{id}\". Get this from gitlab_list_vulnerabilities.'\n ),\n comment: z.string().optional().describe('Optional comment about the confirmation'),\n },\n execute: async (args: { vulnerability_id: string; comment?: string }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const vulnerability = await client.confirmVulnerability(args.vulnerability_id, args.comment);\n return JSON.stringify(vulnerability, null, 2);\n },\n }),\n\n gitlab_revert_vulnerability_to_detected: tool({\n description: `Revert a vulnerability back to detected state.\nUse this to undo a previous confirmation or dismissal.\nRequires Developer role or higher.`,\n args: {\n vulnerability_id: z\n .string()\n .describe(\n 'Vulnerability ID in format \"gid://gitlab/Vulnerability/{id}\". Get this from gitlab_list_vulnerabilities.'\n ),\n comment: z.string().optional().describe('Optional comment about reverting the state'),\n },\n execute: async (args: { vulnerability_id: string; comment?: string }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const vulnerability = await client.revertVulnerability(args.vulnerability_id, args.comment);\n return JSON.stringify(vulnerability, null, 2);\n },\n }),\n\n gitlab_update_vulnerability_severity: tool({\n description: `Update the severity level of one or more vulnerabilities.\nUse this to adjust the severity rating based on your assessment.\nRequires Developer role or higher.`,\n args: {\n vulnerability_ids: z\n .array(z.string())\n .describe(\n 'Array of vulnerability IDs in format \"gid://gitlab/Vulnerability/{id}\". Get these from gitlab_list_vulnerabilities.'\n ),\n severity: z\n .enum(['CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'INFO', 'UNKNOWN'])\n .describe('New severity level for the vulnerabilities'),\n comment: z.string().describe('Comment explaining the severity change (required)'),\n },\n execute: async (\n args: {\n vulnerability_ids: string[];\n severity: 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW' | 'INFO' | 'UNKNOWN';\n comment: string;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const vulnerabilities = await client.updateVulnerabilitySeverity(\n args.vulnerability_ids,\n args.severity,\n args.comment\n );\n return JSON.stringify(vulnerabilities, null, 2);\n },\n }),\n\n gitlab_link_vulnerability_to_issue: tool({\n description: `Link an existing issue to one or more vulnerabilities.\nUse this to associate vulnerabilities with an existing issue for tracking.\nRequires Developer role or higher.`,\n args: {\n issue_id: z\n .string()\n .describe(\n 'Issue ID in format \"gid://gitlab/Issue/{id}\". You can construct this from the issue IID.'\n ),\n vulnerability_ids: z\n .array(z.string())\n .describe(\n 'Array of vulnerability IDs in format \"gid://gitlab/Vulnerability/{id}\". Get these from gitlab_list_vulnerabilities.'\n ),\n },\n execute: async (args: { issue_id: string; vulnerability_ids: string[] }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const issue = await client.linkVulnerabilityToIssue(args.issue_id, args.vulnerability_ids);\n return JSON.stringify(issue, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const todoTools = {\n gitlab_list_todos: tool({\n description: `List TODO items for the current user using GraphQL API with pagination support.\nReturns a list of pending or done TODO items assigned to the authenticated user.\nTODOs are created when you are assigned to an issue/MR, mentioned in a comment, or when someone requests your review.\n\nThe response includes pagination information (pageInfo) with cursors for fetching additional pages.\nUse 'after' with the 'endCursor' from pageInfo to get the next page.\nUse 'before' with the 'startCursor' from pageInfo to get the previous page.`,\n args: {\n action: z\n .enum([\n 'assigned',\n 'mentioned',\n 'build_failed',\n 'marked',\n 'approval_required',\n 'unmergeable',\n 'directly_addressed',\n 'merge_train_removed',\n 'review_requested',\n ])\n .optional()\n .describe('Filter by action type'),\n author_id: z.number().optional().describe('Filter by author ID'),\n project_id: z.string().optional().describe('Filter by project ID or path'),\n group_id: z.string().optional().describe('Filter by group ID'),\n state: z.enum(['pending', 'done']).optional().describe('Filter by state (default: pending)'),\n type: z\n .enum(['Issue', 'MergeRequest', 'DesignManagement::Design', 'Alert', 'Epic', 'Commit'])\n .optional()\n .describe('Filter by target type'),\n first: z\n .number()\n .optional()\n .describe('Number of items to return from the beginning (default: 20, max: 100)'),\n after: z\n .string()\n .optional()\n .describe('Cursor for forward pagination - use endCursor from previous response'),\n last: z\n .number()\n .optional()\n .describe('Number of items to return from the end (for backward pagination)'),\n before: z\n .string()\n .optional()\n .describe('Cursor for backward pagination - use startCursor from previous response'),\n },\n execute: async (\n args: {\n action?:\n | 'assigned'\n | 'mentioned'\n | 'build_failed'\n | 'marked'\n | 'approval_required'\n | 'unmergeable'\n | 'directly_addressed'\n | 'merge_train_removed'\n | 'review_requested';\n author_id?: number;\n project_id?: string;\n group_id?: string;\n state?: 'pending' | 'done';\n type?: 'Issue' | 'MergeRequest' | 'DesignManagement::Design' | 'Alert' | 'Epic' | 'Commit';\n first?: number;\n after?: string;\n last?: number;\n before?: string;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const result = await client.listTodos({\n action: args.action,\n author_id: args.author_id,\n project_id: args.project_id,\n group_id: args.group_id,\n state: args.state,\n type: args.type,\n first: args.first,\n after: args.after,\n last: args.last,\n before: args.before,\n });\n return JSON.stringify(result, null, 2);\n },\n }),\n\n gitlab_mark_todo_done: tool({\n description: `Mark TODO items as done.\n\nActions:\n- one: Mark a specific TODO item as done (requires todo_id)\n- all: Mark all pending TODO items as done\n\nExamples:\n- Mark one: action=\"one\", todo_id=123\n- Mark all: action=\"all\"`,\n args: {\n action: z\n .enum(['one', 'all'])\n .describe('Action to perform: \"one\" for single TODO, \"all\" for all TODOs'),\n todo_id: z\n .number()\n .optional()\n .describe('The ID of the TODO item (required for action=\"one\")'),\n },\n execute: async (args: { action: 'one' | 'all'; todo_id?: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n\n switch (args.action) {\n case 'one': {\n if (args.todo_id === undefined) {\n return JSON.stringify({ error: 'todo_id is required when action is \"one\"' }, null, 2);\n }\n const result = await client.markTodoAsDone(args.todo_id);\n if (!result.success) {\n return JSON.stringify(\n {\n success: false,\n message: result.message,\n },\n null,\n 2\n );\n }\n return JSON.stringify(\n {\n success: true,\n todo: result.todo,\n },\n null,\n 2\n );\n }\n case 'all': {\n const result = await client.markAllTodosAsDone();\n return JSON.stringify(result, null, 2);\n }\n }\n },\n }),\n\n gitlab_get_todo_count: tool({\n description: `Get the count of pending TODO items.\nReturns the total number of pending TODOs for the current user.`,\n args: {},\n execute: async (_args: Record<string, never>, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const count = await client.getTodoCount();\n return JSON.stringify(count, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const wikiTools = {\n gitlab_get_wiki_page: tool({\n description: `Get a wiki page with its content.\nReturns the wiki page content and metadata.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n slug: z.string().describe('The slug (URL-friendly name) of the wiki page'),\n },\n execute: async (args: { project_id: string; slug: string }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const page = await client.getWikiPage(args.project_id, args.slug);\n return JSON.stringify(page, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const workItemTools = {\n gitlab_get_work_item: tool({\n description: `Get a single work item (issue, epic, task, etc.).\nWork items are the new unified model for issues, epics, tasks, and other work tracking items in GitLab.`,\n args: {\n project_id: z.string().describe('The project ID or full path (e.g. \"gitlab-org/gitlab\")'),\n work_item_id: z\n .number()\n .describe(\n 'The IID of the work item — the number visible in the GitLab URL (e.g. for https://gitlab.com/group/project/-/work_items/52, use 52). This is NOT the global database ID.'\n ),\n },\n execute: async (args: { project_id: string; work_item_id: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const workItem = await client.getWorkItem(args.project_id, args.work_item_id);\n return JSON.stringify(workItem, null, 2);\n },\n }),\n\n gitlab_list_work_items: tool({\n description: `List work items in a project or group.\nWork items include issues, epics, tasks, and other work tracking items.`,\n args: {\n project_id: z.string().optional().describe('The project ID or URL-encoded path'),\n group_id: z.string().optional().describe('The group ID or URL-encoded path'),\n state: z\n .enum(['opened', 'closed', 'all'])\n .optional()\n .describe('Filter by state (default: opened)'),\n search: z.string().optional().describe('Search work items by title or description'),\n labels: z.string().optional().describe('Comma-separated list of labels to filter by'),\n work_item_type: z\n .string()\n .optional()\n .describe(\"Filter by work item type (e.g., 'Issue', 'Epic', 'Task')\"),\n limit: z.number().optional().describe('Maximum number of results (default: 20)'),\n },\n execute: async (\n args: {\n project_id?: string;\n group_id?: string;\n state?: 'opened' | 'closed' | 'all';\n search?: string;\n labels?: string;\n work_item_type?: string;\n limit?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const workItems = await client.listWorkItems({\n projectId: args.project_id,\n groupId: args.group_id,\n state: args.state,\n search: args.search,\n labels: args.labels,\n work_item_type: args.work_item_type,\n limit: args.limit,\n });\n return JSON.stringify(workItems, null, 2);\n },\n }),\n\n gitlab_get_work_item_notes: tool({\n description: `Get all comments for a work item.\nReturns all notes/comments on the work item in chronological order.`,\n args: {\n project_id: z.string().describe('The project ID or full path (e.g. \"gitlab-org/gitlab\")'),\n work_item_id: z\n .number()\n .describe(\n 'The IID of the work item — the number visible in the GitLab URL (e.g. for https://gitlab.com/group/project/-/work_items/52, use 52). This is NOT the global database ID.'\n ),\n },\n execute: async (args: { project_id: string; work_item_id: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n const notes = await client.getWorkItemNotes(args.project_id, args.work_item_id);\n return JSON.stringify(notes, null, 2);\n },\n }),\n\n gitlab_create_work_item: tool({\n description: `Create a new work item (issue, task, etc.).\nWork items are the new unified model for issues, epics, tasks, and other work tracking items.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n title: z.string().describe('The title of the work item'),\n work_item_type_id: z\n .number()\n .describe('The ID of the work item type (e.g., 1 for Issue, 2 for Task)'),\n description: z\n .string()\n .optional()\n .describe('The description of the work item (supports Markdown)'),\n labels: z.array(z.string()).optional().describe('Array of label names'),\n assignee_ids: z.array(z.number()).optional().describe('Array of user IDs to assign'),\n },\n execute: async (\n args: {\n project_id: string;\n title: string;\n work_item_type_id: number;\n description?: string;\n labels?: string[];\n assignee_ids?: number[];\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const workItem = await client.createWorkItem(args.project_id, {\n title: args.title,\n work_item_type_id: args.work_item_type_id,\n description: args.description,\n labels: args.labels,\n assignee_ids: args.assignee_ids,\n });\n return JSON.stringify(workItem, null, 2);\n },\n }),\n\n gitlab_update_work_item: tool({\n description: `Update an existing work item.\nCan update title, description, state, labels, and assignees.`,\n args: {\n project_id: z.string().describe('The project ID or full path (e.g. \"gitlab-org/gitlab\")'),\n work_item_id: z\n .number()\n .describe(\n 'The IID of the work item — the number visible in the GitLab URL (e.g. for https://gitlab.com/group/project/-/work_items/52, use 52). This is NOT the global database ID.'\n ),\n title: z.string().optional().describe('The new title'),\n description: z.string().optional().describe('The new description (supports Markdown)'),\n state_event: z\n .enum(['close', 'reopen'])\n .optional()\n .describe('Change the state (close or reopen)'),\n labels: z.array(z.string()).optional().describe('Array of label names'),\n assignee_ids: z.array(z.number()).optional().describe('Array of user IDs to assign'),\n },\n execute: async (\n args: {\n project_id: string;\n work_item_id: number;\n title?: string;\n description?: string;\n state_event?: 'close' | 'reopen';\n labels?: string[];\n assignee_ids?: number[];\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const workItem = await client.updateWorkItem(args.project_id, args.work_item_id, {\n title: args.title,\n description: args.description,\n state_event: args.state_event,\n labels: args.labels,\n assignee_ids: args.assignee_ids,\n });\n return JSON.stringify(workItem, null, 2);\n },\n }),\n\n gitlab_create_work_item_note: tool({\n description: `Create a comment on a work item.`,\n args: {\n project_id: z.string().describe('The project ID or full path (e.g. \"gitlab-org/gitlab\")'),\n work_item_id: z\n .number()\n .describe(\n 'The IID of the work item — the number visible in the GitLab URL (e.g. for https://gitlab.com/group/project/-/work_items/52, use 52). This is NOT the global database ID.'\n ),\n body: z.string().describe('The content of the note/comment (supports Markdown)'),\n },\n execute: async (\n args: { project_id: string; work_item_id: number; body: string },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const note = await client.createWorkItemNote(args.project_id, args.work_item_id, args.body);\n return JSON.stringify(note, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\nimport type { DiscussionsResult } from '../client/discussions-types.js';\n\nconst z = tool.schema;\n\n/**\n * Supported resource types for discussions\n */\ntype ResourceType = 'merge_request' | 'issue' | 'epic' | 'commit' | 'snippet';\n\n/**\n * Helper to normalize resolved parameter which might come as string from some frameworks\n */\nfunction normalizeBoolean(value: unknown): boolean | undefined {\n if (typeof value === 'boolean') return value;\n if (value === 'true') return true;\n if (value === 'false') return false;\n return undefined;\n}\n\n/**\n * Helper to apply client-side resolved filter to discussions\n * Note: GitLab API doesn't support server-side filtering by resolved status\n *\n * When filtering:\n * - resolved=true: Returns only resolved resolvable discussions\n * - resolved=false: Returns only unresolved resolvable discussions\n * - Only resolvable discussions are included (system notes with resolvable=false are excluded)\n */\nfunction filterDiscussionsByResolved(\n result: DiscussionsResult,\n resolved?: boolean | string\n): DiscussionsResult {\n const normalizedResolved = normalizeBoolean(resolved);\n if (normalizedResolved === undefined) {\n return result;\n }\n return {\n discussions: {\n ...result.discussions,\n nodes: result.discussions.nodes.filter(\n (d) => d.resolvable && d.resolved === normalizedResolved\n ),\n },\n };\n}\n\n/**\n * Supported resource types for resolve/unresolve operations\n */\ntype ResolvableResourceType = 'merge_request' | 'issue';\n\n/**\n * Position object for code-specific comments on MRs and commits\n */\nconst positionSchema = z.object({\n base_sha: z.string().describe('SHA of the base commit'),\n start_sha: z.string().describe('SHA of the start commit'),\n head_sha: z.string().describe('SHA of the head commit'),\n position_type: z.enum(['text', 'image']).describe('Type of position'),\n old_path: z.string().optional().describe('Path of the file before changes'),\n new_path: z.string().optional().describe('Path of the file after changes'),\n old_line: z.number().optional().describe('Line number in the old version'),\n new_line: z.number().optional().describe('Line number in the new version'),\n});\n\n/**\n * Helper to validate required parameters based on resource type\n */\nfunction validateResourceParams(\n resourceType: ResourceType,\n args: {\n project_id?: string;\n group_id?: string;\n iid?: number;\n sha?: string;\n snippet_id?: number;\n }\n): void {\n switch (resourceType) {\n case 'merge_request':\n case 'issue':\n if (!args.project_id) throw new Error(`project_id is required for ${resourceType}`);\n if (args.iid == null) throw new Error(`iid is required for ${resourceType}`);\n break;\n case 'epic':\n if (!args.group_id) throw new Error('group_id is required for epic');\n if (args.iid == null) throw new Error('iid is required for epic');\n break;\n case 'commit':\n if (!args.project_id) throw new Error('project_id is required for commit');\n if (!args.sha) throw new Error('sha is required for commit');\n break;\n case 'snippet':\n if (!args.project_id) throw new Error('project_id is required for snippet');\n if (args.snippet_id == null) throw new Error('snippet_id is required for snippet');\n break;\n }\n}\n\nexport const discussionsUnifiedTools = {\n /**\n * List discussions for any GitLab resource type\n */\n gitlab_list_discussions: tool({\n description: `List discussions (comment threads) on any GitLab resource.\nSupports: merge_requests, issues, epics, commits, snippets.\n\nReturns discussion threads with nested notes. Each discussion contains \na 'notes' array with individual comments.\n\nFor pagination, use 'after' with the 'endCursor' from pageInfo to get the next page.\n\nExamples:\n- MR: resource_type=\"merge_request\", project_id=\"group/project\", iid=123\n- Issue: resource_type=\"issue\", project_id=\"group/project\", iid=456 \n- Epic: resource_type=\"epic\", group_id=\"my-group\", iid=1\n- Commit: resource_type=\"commit\", project_id=\"group/project\", sha=\"abc123\"\n- Snippet: resource_type=\"snippet\", project_id=\"group/project\", snippet_id=789`,\n args: {\n resource_type: z\n .enum(['merge_request', 'issue', 'epic', 'commit', 'snippet'])\n .describe('Type of GitLab resource'),\n project_id: z\n .string()\n .optional()\n .describe('Project ID or path. Required for merge_request, issue, commit, snippet'),\n group_id: z.string().optional().describe('Group ID or path. Required for epic'),\n iid: z\n .number()\n .optional()\n .describe('Internal ID of the resource (for merge_request, issue, epic)'),\n sha: z.string().optional().describe('Commit SHA (required for commit)'),\n snippet_id: z.number().optional().describe('Snippet ID (required for snippet)'),\n // Filtering\n resolved: z\n .boolean()\n .optional()\n .describe(\n 'Filter by resolved status: true for resolved, false for unresolved. Only returns resolvable discussions (excludes system notes). Client-side filtering.'\n ),\n // Pagination\n first: z\n .number()\n .int()\n .min(0)\n .max(100)\n .optional()\n .describe('Number of items to return (default: 20, max: 100; 0 uses the default)'),\n after: z\n .string()\n .optional()\n .describe('Cursor for pagination - use endCursor from previous response'),\n before: z.string().optional().describe('Cursor for backward pagination'),\n last: z\n .number()\n .int()\n .min(0)\n .max(100)\n .optional()\n .describe('Number of items from the end (max: 100; 0 is omitted)'),\n },\n execute: async (\n args: {\n resource_type: ResourceType;\n project_id?: string;\n group_id?: string;\n iid?: number;\n sha?: string;\n snippet_id?: number;\n resolved?: boolean | string;\n first?: number;\n after?: string;\n before?: string;\n last?: number;\n },\n _ctx: ToolContext\n ) => {\n validateResourceParams(args.resource_type, args);\n\n const client = getGitLabClient();\n const paginationOptions = {\n first: args.first,\n after: args.after,\n before: args.before,\n last: args.last,\n };\n\n let result: DiscussionsResult;\n\n switch (args.resource_type) {\n case 'merge_request':\n result = await client.listMrDiscussions(args.project_id!, args.iid!, paginationOptions);\n break;\n case 'issue':\n result = await client.listIssueDiscussions(\n args.project_id!,\n args.iid!,\n paginationOptions\n );\n break;\n case 'epic':\n result = await client.listEpicDiscussions(args.group_id!, args.iid!, paginationOptions);\n break;\n case 'commit':\n // Commit discussions use REST API - return as-is (different structure)\n return JSON.stringify(\n await client.listCommitDiscussions(args.project_id!, args.sha!),\n null,\n 2\n );\n case 'snippet':\n result = await client.listSnippetDiscussions(\n args.project_id!,\n args.snippet_id!,\n paginationOptions\n );\n break;\n default:\n throw new Error(`Unsupported resource type: ${args.resource_type}`);\n }\n\n // Apply client-side filtering if resolved parameter is specified\n const filteredResult = filterDiscussionsByResolved(result, args.resolved);\n return JSON.stringify(filteredResult, null, 2);\n },\n }),\n\n /**\n * Get a specific discussion thread from any GitLab resource\n */\n gitlab_get_discussion: tool({\n description: `Get a specific discussion thread with all its replies.\nReturns the discussion with its 'notes' array containing all comments.\n\nUse this to get full context of a specific conversation.\n\nRequired parameters vary by resource type:\n- merge_request: project_id, iid, discussion_id\n- issue: project_id, iid, discussion_id \n- epic: group_id, iid, discussion_id\n- commit: project_id, sha, discussion_id\n- snippet: project_id, snippet_id, discussion_id`,\n args: {\n resource_type: z\n .enum(['merge_request', 'issue', 'epic', 'commit', 'snippet'])\n .describe('Type of GitLab resource'),\n discussion_id: z.string().describe('The ID of the discussion thread'),\n project_id: z.string().optional().describe('Project ID or path'),\n group_id: z.string().optional().describe('Group ID or path (for epic)'),\n iid: z.number().optional().describe('Internal ID (for merge_request, issue, epic)'),\n sha: z.string().optional().describe('Commit SHA (for commit)'),\n snippet_id: z.number().optional().describe('Snippet ID (for snippet)'),\n },\n execute: async (\n args: {\n resource_type: ResourceType;\n discussion_id: string;\n project_id?: string;\n group_id?: string;\n iid?: number;\n sha?: string;\n snippet_id?: number;\n },\n _ctx: ToolContext\n ) => {\n validateResourceParams(args.resource_type, args);\n\n const client = getGitLabClient();\n\n switch (args.resource_type) {\n case 'merge_request':\n return JSON.stringify(\n await client.getMrDiscussion(args.project_id!, args.iid!, args.discussion_id),\n null,\n 2\n );\n case 'issue':\n return JSON.stringify(\n await client.getIssueDiscussion(args.project_id!, args.iid!, args.discussion_id),\n null,\n 2\n );\n case 'epic':\n return JSON.stringify(\n await client.getEpicDiscussion(args.group_id!, args.iid!, args.discussion_id),\n null,\n 2\n );\n case 'commit':\n return JSON.stringify(\n await client.getCommitDiscussion(args.project_id!, args.sha!, args.discussion_id),\n null,\n 2\n );\n case 'snippet':\n return JSON.stringify(\n await client.getSnippetDiscussion(\n args.project_id!,\n args.snippet_id!,\n args.discussion_id\n ),\n null,\n 2\n );\n default:\n throw new Error(`Unsupported resource type: ${args.resource_type}`);\n }\n },\n }),\n\n /**\n * Create a new discussion thread or reply to an existing one\n */\n gitlab_create_discussion: tool({\n description: `Create a new discussion thread or reply to an existing one.\n\nREPLYING TO EXISTING THREADS:\nTo reply to an existing discussion, provide the discussion_id parameter.\nThis is the recommended way to reply in-thread rather than creating a standalone comment.\n\nSTARTING A NEW DISCUSSION:\nOmit discussion_id to create a new thread. For code-specific comments on MRs/commits, provide position information.\n\nExamples:\n- Reply to thread: resource_type=\"merge_request\", project_id=\"group/project\", iid=123, discussion_id=\"abc123def\", body=\"Thanks for the feedback!\"\n- New comment: resource_type=\"merge_request\", project_id=\"group/project\", iid=123, body=\"General comment\"\n- Code comment: resource_type=\"merge_request\", project_id=\"group/project\", iid=123, body=\"...\", position={base_sha, head_sha, new_path, new_line, ...}`,\n args: {\n resource_type: z\n .enum(['merge_request', 'issue', 'epic', 'commit', 'snippet'])\n .describe('Type of GitLab resource'),\n body: z.string().describe('The comment text (Markdown supported)'),\n project_id: z.string().optional().describe('Project ID or path'),\n group_id: z.string().optional().describe('Group ID or path (for epic)'),\n iid: z.number().optional().describe('Internal ID (for merge_request, issue, epic)'),\n sha: z.string().optional().describe('Commit SHA (for commit)'),\n snippet_id: z.number().optional().describe('Snippet ID (for snippet)'),\n discussion_id: z\n .string()\n .optional()\n .describe('If provided, replies to existing discussion. If omitted, creates new thread'),\n position: positionSchema\n .optional()\n .describe('Position for code-specific comments (MR/commit only)'),\n },\n execute: async (\n args: {\n resource_type: ResourceType;\n body: string;\n project_id?: string;\n group_id?: string;\n iid?: number;\n sha?: string;\n snippet_id?: number;\n discussion_id?: string;\n position?: {\n base_sha: string;\n start_sha: string;\n head_sha: string;\n position_type: 'text' | 'image';\n old_path?: string;\n new_path?: string;\n old_line?: number;\n new_line?: number;\n };\n },\n _ctx: ToolContext\n ) => {\n validateResourceParams(args.resource_type, args);\n\n const client = getGitLabClient();\n\n // If discussion_id is provided, this is a reply to existing thread\n if (args.discussion_id) {\n const note = await client.replyToDiscussion(\n args.resource_type,\n {\n projectId: args.project_id,\n groupId: args.group_id,\n iid: args.iid,\n sha: args.sha,\n snippetId: args.snippet_id,\n },\n args.discussion_id,\n args.body\n );\n return JSON.stringify(note, null, 2);\n }\n\n // Otherwise, create a new discussion\n switch (args.resource_type) {\n case 'merge_request':\n return JSON.stringify(\n await client.createMrDiscussion(args.project_id!, args.iid!, args.body, args.position),\n null,\n 2\n );\n case 'issue':\n // Issues don't support position-based discussions, create a note that starts a discussion\n return JSON.stringify(\n await client.createIssueNote(args.project_id!, args.iid!, args.body),\n null,\n 2\n );\n case 'epic':\n return JSON.stringify(\n await client.createEpicNote(args.group_id!, args.iid!, args.body),\n null,\n 2\n );\n case 'commit':\n return JSON.stringify(\n await client.createCommitDiscussion(\n args.project_id!,\n args.sha!,\n args.body,\n args.position\n ),\n null,\n 2\n );\n case 'snippet':\n return JSON.stringify(\n await client.createSnippetDiscussion(args.project_id!, args.snippet_id!, args.body),\n null,\n 2\n );\n default:\n throw new Error(`Unsupported resource type: ${args.resource_type}`);\n }\n },\n }),\n\n /**\n * Resolve or unresolve a discussion thread\n */\n gitlab_resolve_discussion: tool({\n description: `Mark a discussion thread as resolved or unresolve it.\nOnly works for resolvable discussions (MRs and issues only).\n\nUses GraphQL API which handles all discussion types including outdated discussions\n(those with resolved: null) that the REST API cannot handle.\n\nUse after addressing feedback to indicate the discussion is complete.`,\n args: {\n resource_type: z\n .enum(['merge_request', 'issue'])\n .describe('Type of resource (only MR and issue discussions can be resolved)'),\n action: z.enum(['resolve', 'unresolve']).describe('Whether to resolve or unresolve'),\n discussion_id: z.string().describe('The ID of the discussion thread'),\n project_id: z.string().describe('Project ID or path'),\n iid: z.number().describe('Internal ID of the MR or issue'),\n },\n execute: async (\n args: {\n resource_type: ResolvableResourceType;\n action: 'resolve' | 'unresolve';\n discussion_id: string;\n project_id: string;\n iid: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const resolve = args.action === 'resolve';\n\n // Use GraphQL API which handles all discussion types including outdated ones\n return JSON.stringify(\n await client.toggleDiscussionResolved(args.discussion_id, resolve),\n null,\n 2\n );\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\nimport type { NotesResult } from '../client/notes-types.js';\n\nconst z = tool.schema;\n\n/**\n * Helper to normalize resolved parameter which might come as string from some frameworks\n */\nfunction normalizeBoolean(value: unknown): boolean | undefined {\n if (typeof value === 'boolean') return value;\n if (value === 'true') return true;\n if (value === 'false') return false;\n return undefined;\n}\n\n/**\n * Helper to apply client-side resolved filter to notes\n * Note: GitLab API doesn't support server-side filtering by resolved status\n *\n * When filtering:\n * - resolved=true: Returns only resolved resolvable notes\n * - resolved=false: Returns only unresolved resolvable notes\n * - Only resolvable notes are included (system notes with resolvable=false are excluded)\n */\nfunction filterNotesByResolved(result: NotesResult, resolved?: boolean | string): NotesResult {\n const normalizedResolved = normalizeBoolean(resolved);\n if (normalizedResolved === undefined) {\n return result;\n }\n return {\n ...result,\n notes: {\n ...result.notes,\n nodes: result.notes.nodes.filter((n) => n.resolvable && n.resolved === normalizedResolved),\n },\n };\n}\n\n/**\n * Supported resource types for listing notes\n */\ntype ListNotesResourceType = 'merge_request' | 'issue' | 'epic' | 'snippet';\n\n/**\n * Supported resource types for getting a single note\n * Note: MR notes are accessed via discussions API, not individual note fetch\n */\ntype GetNoteResourceType = 'issue' | 'epic';\n\n/**\n * Supported resource types for creating notes\n */\ntype CreateNoteResourceType = 'merge_request' | 'issue' | 'epic' | 'snippet';\n\n/**\n * Supported resource types for updating notes\n */\ntype UpdateNoteResourceType = 'merge_request' | 'issue' | 'epic' | 'snippet';\n\n/**\n * Resource types supported by list/create/update operations (all four)\n */\nconst NOTE_RESOURCE_TYPES = ['merge_request', 'issue', 'epic', 'snippet'] as const;\n\n/**\n * Resource types supported by getting a single note (issue/epic only)\n */\nconst GET_NOTE_RESOURCE_TYPES = ['issue', 'epic'] as const;\n\n/**\n * Create a standardized validation error message\n */\nfunction validationError(param: string, resourceType: string): Error {\n return new Error(\n `Missing required parameter: '${param}' is required for resource_type '${resourceType}'`\n );\n}\n\n/**\n * Common arg shape accepted by note validators.\n * All fields are optional so a single validator can serve list/create/update/get.\n */\ninterface NoteValidationArgs {\n project_id?: string;\n group_id?: string;\n iid?: number;\n snippet_id?: number;\n note_id?: number;\n}\n\n/**\n * Unified validator for note tool parameters.\n *\n * - `allowedTypes` controls which resource types are valid (e.g. get supports only issue/epic).\n * - `requireNoteId` is set true for get/update operations.\n *\n * Per-resource-type required field rules are enforced for everyone:\n * merge_request: project_id + iid\n * issue: project_id + iid\n * epic: group_id + iid\n * snippet: project_id + snippet_id\n */\nfunction validateNoteParams(\n resourceType: string,\n args: NoteValidationArgs,\n opts: { allowedTypes: readonly string[]; requireNoteId?: boolean }\n): void {\n if (!opts.allowedTypes.includes(resourceType)) {\n throw new Error(\n `Invalid resource_type '${resourceType}'. Must be one of: ${opts.allowedTypes.join(', ')}`\n );\n }\n\n if (opts.requireNoteId && args.note_id == null) {\n throw validationError('note_id', resourceType);\n }\n\n switch (resourceType) {\n case 'merge_request':\n case 'issue':\n if (!args.project_id) throw validationError('project_id', resourceType);\n if (args.iid == null) throw validationError('iid', resourceType);\n break;\n case 'epic':\n if (!args.group_id) throw validationError('group_id', resourceType);\n if (args.iid == null) throw validationError('iid', resourceType);\n break;\n case 'snippet':\n if (!args.project_id) throw validationError('project_id', resourceType);\n if (args.snippet_id == null) throw validationError('snippet_id', resourceType);\n break;\n }\n}\n\nexport const notesUnifiedTools = {\n /**\n * List notes/comments for any GitLab resource type\n */\n gitlab_list_notes: tool({\n description: `List all notes/comments on any GitLab resource using GraphQL API with pagination support.\nReturns all comments including system notes in chronological order.\nThis is easier to read than discussions which have nested structure.\n\nThe response includes pagination information (pageInfo) with cursors for fetching additional pages.\nUse 'after' with the 'endCursor' from pageInfo to get the next page.\nUse 'before' with the 'startCursor' from pageInfo to get the previous page.\n\nExamples:\n- MR: resource_type=\"merge_request\", project_id=\"group/project\", iid=123\n- Issue: resource_type=\"issue\", project_id=\"group/project\", iid=456 \n- Epic: resource_type=\"epic\", group_id=\"my-group\", iid=1\n- Snippet: resource_type=\"snippet\", project_id=\"group/project\", snippet_id=789`,\n args: {\n resource_type: z\n .enum(['merge_request', 'issue', 'epic', 'snippet'])\n .describe('Type of GitLab resource'),\n project_id: z\n .string()\n .optional()\n .describe('Project ID or path. Required for merge_request, issue, snippet'),\n group_id: z.string().optional().describe('Group ID or path. Required for epic'),\n iid: z\n .number()\n .optional()\n .describe('Internal ID of the resource (for merge_request, issue, epic)'),\n snippet_id: z.number().optional().describe('Snippet ID (required for snippet)'),\n // Filtering\n resolved: z\n .boolean()\n .optional()\n .describe(\n 'Filter by resolved status: true for resolved, false for unresolved. Only returns resolvable notes (excludes system notes). Client-side filtering.'\n ),\n // Pagination\n first: z\n .number()\n .int()\n .min(0)\n .max(100)\n .optional()\n .describe(\n 'Number of items to return from the beginning (default: 20, max: 100; 0 uses the default)'\n ),\n after: z\n .string()\n .optional()\n .describe('Cursor for forward pagination - use endCursor from previous response'),\n last: z\n .number()\n .int()\n .min(0)\n .max(100)\n .optional()\n .describe('Number of items to return from the end (max: 100; 0 is omitted)'),\n before: z\n .string()\n .optional()\n .describe('Cursor for backward pagination - use startCursor from previous response'),\n },\n execute: async (\n args: {\n resource_type: ListNotesResourceType;\n project_id?: string;\n group_id?: string;\n iid?: number;\n snippet_id?: number;\n resolved?: boolean | string;\n first?: number;\n after?: string;\n last?: number;\n before?: string;\n },\n _ctx: ToolContext\n ) => {\n validateNoteParams(args.resource_type, args, { allowedTypes: NOTE_RESOURCE_TYPES });\n\n const client = getGitLabClient();\n const paginationOptions = {\n first: args.first,\n after: args.after,\n last: args.last,\n before: args.before,\n };\n\n let result: NotesResult;\n\n switch (args.resource_type) {\n case 'merge_request':\n result = await client.listMrNotes(args.project_id!, args.iid!, paginationOptions);\n break;\n case 'issue':\n result = await client.listIssueNotes(args.project_id!, args.iid!, paginationOptions);\n break;\n case 'epic':\n result = await client.listEpicNotes(args.group_id!, args.iid!, paginationOptions);\n break;\n case 'snippet':\n result = await client.listSnippetNotes(\n args.project_id!,\n args.snippet_id!,\n paginationOptions\n );\n break;\n default:\n throw new Error(`Unsupported resource type: ${args.resource_type}`);\n }\n\n // Apply client-side filtering if resolved parameter is specified\n const filteredResult = filterNotesByResolved(result, args.resolved);\n return JSON.stringify(filteredResult, null, 2);\n },\n }),\n\n /**\n * Get a single note/comment by its ID\n */\n gitlab_get_note: tool({\n description: `Get a single note/comment from an issue or epic by its ID.\nReturns the full details of a specific note including author, body, timestamps, and metadata.\nUseful when you need to retrieve a specific comment without fetching all notes.\n\nSupports: issues, epics (MR notes use discussions API)\n\nExamples:\n- Issue note: resource_type=\"issue\", project_id=\"group/project\", iid=456, note_id=123\n- Epic note: resource_type=\"epic\", group_id=\"my-group\", iid=1, note_id=456`,\n args: {\n resource_type: z\n .enum(['issue', 'epic'])\n .describe('Type of GitLab resource (issue or epic only)'),\n note_id: z.number().describe('The ID of the note to retrieve'),\n project_id: z.string().optional().describe('Project ID or path. Required for issue'),\n group_id: z.string().optional().describe('Group ID or path. Required for epic'),\n iid: z.number().describe('Internal ID of the issue or epic'),\n },\n execute: async (\n args: {\n resource_type: GetNoteResourceType;\n note_id: number;\n project_id?: string;\n group_id?: string;\n iid: number;\n },\n _ctx: ToolContext\n ) => {\n validateNoteParams(args.resource_type, args, {\n allowedTypes: GET_NOTE_RESOURCE_TYPES,\n requireNoteId: true,\n });\n\n const client = getGitLabClient();\n\n switch (args.resource_type) {\n case 'issue':\n return JSON.stringify(\n await client.getIssueNote(args.project_id!, args.iid, args.note_id),\n null,\n 2\n );\n case 'epic':\n return JSON.stringify(\n await client.getEpicNote(args.group_id!, args.iid, args.note_id),\n null,\n 2\n );\n default:\n throw new Error(`Unsupported resource type: ${args.resource_type}`);\n }\n },\n }),\n\n /**\n * Create a simple note/comment on any GitLab resource\n */\n gitlab_create_note: tool({\n description: `Add a simple comment/note to any GitLab resource.\nCreates a standalone comment (not part of a thread).\n\nFor replying to existing discussion threads, use gitlab_create_discussion \nwith discussion_id parameter instead.\n\nExamples:\n- MR comment: resource_type=\"merge_request\", project_id=\"group/project\", iid=123, body=\"LGTM!\"\n- Issue comment: resource_type=\"issue\", project_id=\"group/project\", iid=456, body=\"Working on this\"\n- Epic comment: resource_type=\"epic\", group_id=\"my-group\", iid=1, body=\"Planning complete\"\n- Snippet comment: resource_type=\"snippet\", project_id=\"group/project\", snippet_id=789, body=\"Nice code!\"`,\n args: {\n resource_type: z\n .enum(['merge_request', 'issue', 'epic', 'snippet'])\n .describe('Type of GitLab resource'),\n body: z.string().describe('The content of the note/comment (supports Markdown)'),\n project_id: z\n .string()\n .optional()\n .describe('Project ID or path. Required for merge_request, issue, snippet'),\n group_id: z.string().optional().describe('Group ID or path. Required for epic'),\n iid: z\n .number()\n .optional()\n .describe('Internal ID of the resource (for merge_request, issue, epic)'),\n snippet_id: z.number().optional().describe('Snippet ID (required for snippet)'),\n },\n execute: async (\n args: {\n resource_type: CreateNoteResourceType;\n body: string;\n project_id?: string;\n group_id?: string;\n iid?: number;\n snippet_id?: number;\n },\n _ctx: ToolContext\n ) => {\n validateNoteParams(args.resource_type, args, { allowedTypes: NOTE_RESOURCE_TYPES });\n\n const client = getGitLabClient();\n\n switch (args.resource_type) {\n case 'merge_request':\n return JSON.stringify(\n await client.createMrNote(args.project_id!, args.iid!, args.body),\n null,\n 2\n );\n case 'issue':\n return JSON.stringify(\n await client.createIssueNote(args.project_id!, args.iid!, args.body),\n null,\n 2\n );\n case 'epic':\n return JSON.stringify(\n await client.createEpicNote(args.group_id!, args.iid!, args.body),\n null,\n 2\n );\n case 'snippet':\n return JSON.stringify(\n await client.createSnippetNote(args.project_id!, args.snippet_id!, args.body),\n null,\n 2\n );\n default:\n throw new Error(`Unsupported resource type: ${args.resource_type}`);\n }\n },\n }),\n\n /**\n * Update an existing note/comment on any GitLab resource\n */\n gitlab_update_note: tool({\n description: `Update an existing note/comment on any GitLab resource.\nModifies the body content of an existing note. You can only update notes you authored.\n\nExamples:\n- MR note: resource_type=\"merge_request\", project_id=\"group/project\", iid=123, note_id=456, body=\"Updated comment\"\n- Issue note: resource_type=\"issue\", project_id=\"group/project\", iid=456, note_id=789, body=\"Updated comment\"\n- Epic note: resource_type=\"epic\", group_id=\"my-group\", iid=1, note_id=456, body=\"Updated comment\"\n- Snippet note: resource_type=\"snippet\", project_id=\"group/project\", snippet_id=789, note_id=123, body=\"Updated comment\"`,\n args: {\n resource_type: z\n .enum(['merge_request', 'issue', 'epic', 'snippet'])\n .describe('Type of GitLab resource'),\n note_id: z.number().describe('The ID of the note to update'),\n body: z.string().describe('The new content for the note (supports Markdown)'),\n project_id: z\n .string()\n .optional()\n .describe('Project ID or path. Required for merge_request, issue, snippet'),\n group_id: z.string().optional().describe('Group ID or path. Required for epic'),\n iid: z\n .number()\n .optional()\n .describe('Internal ID of the resource (for merge_request, issue, epic)'),\n snippet_id: z.number().optional().describe('Snippet ID (required for snippet)'),\n },\n execute: async (\n args: {\n resource_type: UpdateNoteResourceType;\n note_id: number;\n body: string;\n project_id?: string;\n group_id?: string;\n iid?: number;\n snippet_id?: number;\n },\n _ctx: ToolContext\n ) => {\n validateNoteParams(args.resource_type, args, {\n allowedTypes: NOTE_RESOURCE_TYPES,\n requireNoteId: true,\n });\n\n const client = getGitLabClient();\n\n switch (args.resource_type) {\n case 'merge_request':\n return JSON.stringify(\n await client.updateMrNote(args.project_id!, args.iid!, args.note_id, args.body),\n null,\n 2\n );\n case 'issue':\n return JSON.stringify(\n await client.updateIssueNote(args.project_id!, args.iid!, args.note_id, args.body),\n null,\n 2\n );\n case 'epic':\n return JSON.stringify(\n await client.updateEpicNote(args.group_id!, args.iid!, args.note_id, args.body),\n null,\n 2\n );\n case 'snippet':\n return JSON.stringify(\n await client.updateSnippetNote(\n args.project_id!,\n args.snippet_id!,\n args.note_id,\n args.body\n ),\n null,\n 2\n );\n default:\n throw new Error(`Unsupported resource type: ${args.resource_type}`);\n }\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { GitClient } from '../client/git.js';\n\nconst z = tool.schema;\n\n// Singleton instance of GitClient\nlet gitClient: GitClient | null = null;\n\nfunction getGitClient(): GitClient {\n if (!gitClient) {\n gitClient = new GitClient();\n }\n return gitClient;\n}\n\nexport const gitTools = {\n run_git_command: tool({\n description: `Execute safe, read-only git commands in the repository working directory.\n\nSecurity restrictions:\n- Only read-only git commands are allowed (status, log, show, diff, branch, tag, etc.)\n- Destructive operations are forbidden (push, pull, commit, add, rm, reset, merge, etc.)\n- Shell operators and command injection attempts are blocked\n- Commands are executed with a 30-second timeout and 10MB output buffer\n\nAllowed commands include:\n- status: Show working tree status\n- log: Show commit logs\n- show: Show various types of objects\n- diff: Show changes between commits, commit and working tree, etc.\n- branch: List, create, or delete branches (read-only: list only)\n- tag: List tags (read-only: list only)\n- remote: List remote repositories (read-only: list only)\n- ls-files: Show information about files in the index and working tree\n- ls-remote: List references in a remote repository\n- rev-parse: Parse revision (or other objects) names\n- describe: Give an object a human readable name based on an available ref\n- config: Get repository configuration (read-only: --get operations only)\n- blame: Show what revision and author last modified each line of a file\n- shortlog: Summarize git log output\n- reflog: Show reference logs\n- show-ref: List references in a local repository\n- ls-tree: List the contents of a tree object\n- cat-file: Provide content or type and size information for repository objects\n- rev-list: List commit objects in reverse chronological order\n- name-rev: Find symbolic names for given revs\n- show-branch: Show branches and their commits\n- whatchanged: Show logs with difference each commit introduces\n- grep: Print lines matching a pattern\n- annotate: Annotate file lines with commit information\n\nExamples:\n- run_git_command(\"status\", []) - Show working tree status\n- run_git_command(\"log\", [\"--oneline\", \"-10\"]) - Show last 10 commits\n- run_git_command(\"diff\", [\"HEAD~1\", \"HEAD\"]) - Show diff between last two commits\n- run_git_command(\"branch\", [\"-a\"]) - List all branches\n- run_git_command(\"show\", [\"HEAD:README.md\"]) - Show README.md from HEAD commit`,\n args: {\n command: z.string().describe('The git command to execute (without \"git\" prefix)'),\n args: z\n .array(z.string())\n .optional()\n .describe('Array of arguments for the git command (default: [])'),\n working_directory: z\n .string()\n .optional()\n .describe(\n 'Path to the git repository (default: current working directory). Use this to execute git commands in a specific repository.'\n ),\n },\n execute: async (\n args: {\n command: string;\n args?: string[];\n working_directory?: string;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitClient();\n\n // Set working directory if provided\n if (args.working_directory) {\n client.setWorkingDirectory(args.working_directory);\n }\n\n try {\n const output = await client.runGitCommand(args.command, args.args || []);\n return output;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Failed to execute git command: ${error.message}`);\n }\n throw error;\n }\n },\n }),\n};\n","import { execFile } from 'child_process';\nimport { promisify } from 'util';\nimport { existsSync, statSync } from 'fs';\nimport { resolve, join } from 'path';\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Git client for executing git commands in a repository\n * Security: Only allows safe, read-only git commands by default\n */\nexport class GitClient {\n private workingDirectory: string;\n\n // Whitelist of allowed git commands (read-only operations)\n private static readonly ALLOWED_COMMANDS = new Set([\n 'status',\n 'log',\n 'show',\n 'diff',\n 'branch',\n 'tag',\n 'remote',\n 'ls-files',\n 'ls-remote',\n 'rev-parse',\n 'describe',\n 'config',\n 'blame',\n 'shortlog',\n 'reflog',\n 'show-ref',\n 'ls-tree',\n 'cat-file',\n 'rev-list',\n 'name-rev',\n 'show-branch',\n 'whatchanged',\n 'grep',\n 'annotate',\n ]);\n\n // Commands that are explicitly forbidden (destructive operations)\n private static readonly FORBIDDEN_COMMANDS = new Set([\n 'push',\n 'pull',\n 'fetch',\n 'clone',\n 'commit',\n 'add',\n 'rm',\n 'mv',\n 'reset',\n 'rebase',\n 'merge',\n 'cherry-pick',\n 'revert',\n 'clean',\n 'checkout',\n 'switch',\n 'restore',\n 'stash',\n 'submodule',\n 'worktree',\n ]);\n\n // Shell operators that should be blocked\n private static readonly SHELL_OPERATORS = [';', '&&', '||', '|', '`', '$('];\n\n constructor(workingDirectory?: string) {\n this.workingDirectory = workingDirectory || process.cwd();\n }\n\n /**\n * Execute a git command in the repository working directory\n *\n * Security: Uses execFile() instead of exec() to prevent command injection.\n * Arguments are passed directly to git without shell interpretation, making\n * attacks like `--format=\"$(malicious)\"` impossible.\n *\n * @param command - The git command to execute (without 'git' prefix)\n * @param args - Array of arguments for the command\n * @returns Command output\n * @throws Error if command is not allowed or execution fails\n */\n async runGitCommand(command: string, args: string[] = []): Promise<string> {\n // Validate command\n this.validateCommand(command, args);\n\n try {\n // Use execFile instead of exec to avoid shell interpretation\n // This prevents command injection through git's own command substitution features\n const { stdout, stderr } = await execFileAsync('git', [command, ...args], {\n cwd: this.workingDirectory,\n maxBuffer: 10 * 1024 * 1024, // 10MB buffer\n timeout: 30000, // 30 second timeout\n });\n\n // Return stdout, but include stderr if present (git often uses stderr for warnings)\n return stderr ? `${stdout}\\n\\nWarnings/Info:\\n${stderr}` : stdout;\n } catch (error) {\n if (error instanceof Error) {\n throw new Error(`Git command failed: ${error.message}`);\n }\n throw error;\n }\n }\n\n /**\n * Validate that a git command is safe to execute\n * @param command - The git command\n * @param args - Command arguments\n * @throws Error if command is not allowed\n */\n private validateCommand(command: string, args: string[]): void {\n // Check if command is in the forbidden list\n if (GitClient.FORBIDDEN_COMMANDS.has(command)) {\n throw new Error(\n `Git command '${command}' is not allowed. Only read-only operations are permitted.`\n );\n }\n\n // Check if command is in the allowed list\n if (!GitClient.ALLOWED_COMMANDS.has(command)) {\n throw new Error(\n `Git command '${command}' is not in the allowed list. Only safe, read-only operations are permitted.`\n );\n }\n\n // Additional validation for specific commands with potentially dangerous flags\n if (command === 'branch' && args.some((arg) => arg === '-d' || arg === '-D' || arg === '-m')) {\n throw new Error('Branch deletion and renaming operations are not allowed.');\n }\n\n if (command === 'tag' && args.some((arg) => arg === '-d' || arg === '-f')) {\n throw new Error('Tag deletion and force operations are not allowed.');\n }\n\n if (\n command === 'remote' &&\n args.some((arg) => arg === 'add' || arg === 'remove' || arg === 'set-url')\n ) {\n throw new Error('Remote modification operations are not allowed.');\n }\n\n if (command === 'config' && args.length > 0 && !args.some((arg) => arg.startsWith('--get'))) {\n throw new Error('Only git config read operations (--get) are allowed.');\n }\n\n // Check for shell injection attempts\n const allArgs = [command, ...args].join(' ');\n if (GitClient.SHELL_OPERATORS.some((op) => allArgs.includes(op))) {\n throw new Error('Command contains potentially dangerous shell operators.');\n }\n }\n\n /**\n * Validate that a directory exists and is a git repository\n * @param directory - Path to validate\n * @throws Error if directory is invalid or not a git repository\n */\n private validateDirectory(directory: string): void {\n // Resolve to absolute path to prevent directory traversal\n const absolutePath = resolve(directory);\n\n // Check if directory exists\n if (!existsSync(absolutePath)) {\n throw new Error(`Directory does not exist: ${absolutePath}`);\n }\n\n // Check if it's actually a directory\n const stats = statSync(absolutePath);\n if (!stats.isDirectory()) {\n throw new Error(`Path is not a directory: ${absolutePath}`);\n }\n\n // Check if it's a git repository (contains .git directory or file)\n const gitDir = join(absolutePath, '.git');\n if (!existsSync(gitDir)) {\n throw new Error(`Not a git repository: ${absolutePath}`);\n }\n }\n\n /**\n * Get the current working directory\n */\n getWorkingDirectory(): string {\n return this.workingDirectory;\n }\n\n /**\n * Set the working directory for git commands\n * @param directory - Path to the git repository\n * @throws Error if directory is invalid or not a git repository\n */\n setWorkingDirectory(directory: string): void {\n // Validate the directory before setting it\n this.validateDirectory(directory);\n\n // Store as absolute path to prevent traversal attacks\n this.workingDirectory = resolve(directory);\n }\n}\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\nexport const auditTools = {\n gitlab_list_project_audit_events: tool({\n description: `List audit events for a project.\nReturns audit events including actions like project settings changes, member additions/removals, and other security-relevant activities.\nNote: Requires project owner role or higher.`,\n args: {\n project_id: z.string().describe('The project ID or URL-encoded path'),\n created_after: z\n .string()\n .optional()\n .describe('Return audit events created after this date (ISO 8601 format)'),\n created_before: z\n .string()\n .optional()\n .describe('Return audit events created before this date (ISO 8601 format)'),\n entity_type: z\n .string()\n .optional()\n .describe('Filter by entity type (e.g., \"User\", \"Project\", \"Group\")'),\n entity_id: z.number().optional().describe('Filter by entity ID'),\n author_id: z.number().optional().describe('Filter by author user ID'),\n per_page: z.number().optional().describe('Number of results per page (default: 20)'),\n page: z.number().optional().describe('Page number for pagination (default: 1)'),\n },\n execute: async (\n args: {\n project_id: string;\n created_after?: string;\n created_before?: string;\n entity_type?: string;\n entity_id?: number;\n author_id?: number;\n per_page?: number;\n page?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const events = await client.listProjectAuditEvents(args.project_id, {\n created_after: args.created_after,\n created_before: args.created_before,\n entity_type: args.entity_type,\n entity_id: args.entity_id,\n author_id: args.author_id,\n per_page: args.per_page,\n page: args.page,\n });\n return JSON.stringify(events, null, 2);\n },\n }),\n\n gitlab_list_group_audit_events: tool({\n description: `List audit events for a group.\nReturns audit events including actions like group settings changes, member additions/removals, subgroup operations, and other security-relevant activities.\nNote: Requires group owner role or higher.`,\n args: {\n group_id: z.string().describe('The group ID or URL-encoded path'),\n created_after: z\n .string()\n .optional()\n .describe('Return audit events created after this date (ISO 8601 format)'),\n created_before: z\n .string()\n .optional()\n .describe('Return audit events created before this date (ISO 8601 format)'),\n entity_type: z\n .string()\n .optional()\n .describe('Filter by entity type (e.g., \"User\", \"Project\", \"Group\")'),\n entity_id: z.number().optional().describe('Filter by entity ID'),\n author_id: z.number().optional().describe('Filter by author user ID'),\n per_page: z.number().optional().describe('Number of results per page (default: 20)'),\n page: z.number().optional().describe('Page number for pagination (default: 1)'),\n },\n execute: async (\n args: {\n group_id: string;\n created_after?: string;\n created_before?: string;\n entity_type?: string;\n entity_id?: number;\n author_id?: number;\n per_page?: number;\n page?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const events = await client.listGroupAuditEvents(args.group_id, {\n created_after: args.created_after,\n created_before: args.created_before,\n entity_type: args.entity_type,\n entity_id: args.entity_id,\n author_id: args.author_id,\n per_page: args.per_page,\n page: args.page,\n });\n return JSON.stringify(events, null, 2);\n },\n }),\n\n gitlab_list_instance_audit_events: tool({\n description: `List instance-level audit events.\nReturns audit events for the entire GitLab instance including actions like instance settings changes, user management, license changes, and other system-wide security-relevant activities.\nNote: Requires administrator access.`,\n args: {\n created_after: z\n .string()\n .optional()\n .describe('Return audit events created after this date (ISO 8601 format)'),\n created_before: z\n .string()\n .optional()\n .describe('Return audit events created before this date (ISO 8601 format)'),\n entity_type: z\n .string()\n .optional()\n .describe('Filter by entity type (e.g., \"User\", \"Project\", \"Group\")'),\n entity_id: z.number().optional().describe('Filter by entity ID'),\n author_id: z.number().optional().describe('Filter by author user ID'),\n per_page: z.number().optional().describe('Number of results per page (default: 20)'),\n page: z.number().optional().describe('Page number for pagination (default: 1)'),\n },\n execute: async (\n args: {\n created_after?: string;\n created_before?: string;\n entity_type?: string;\n entity_id?: number;\n author_id?: number;\n per_page?: number;\n page?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const events = await client.listInstanceAuditEvents({\n created_after: args.created_after,\n created_before: args.created_before,\n entity_type: args.entity_type,\n entity_id: args.entity_id,\n author_id: args.author_id,\n per_page: args.per_page,\n page: args.page,\n });\n return JSON.stringify(events, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\nimport type { AwardableResourceType, AwardEmojiResourceId } from '../client/award-emoji.js';\n\nconst z = tool.schema;\n\n/**\n * Helper to validate required parameters for award emoji operations\n */\nfunction validateAwardEmojiParams(args: {\n resource_type: AwardableResourceType;\n project_id: string;\n resource_iid: number;\n}): void {\n if (!args.project_id) {\n throw new Error('project_id is required');\n }\n if (args.resource_iid == null) {\n throw new Error('resource_iid is required');\n }\n}\n\n/**\n * Build the resource ID object from tool arguments\n */\nfunction buildResourceId(args: {\n project_id: string;\n resource_type: AwardableResourceType;\n resource_iid: number;\n note_id?: number;\n}): AwardEmojiResourceId {\n return {\n projectId: args.project_id,\n resourceType: args.resource_type,\n resourceIid: args.resource_iid,\n noteId: args.note_id,\n };\n}\n\nexport const awardEmojiTools = {\n /**\n * Add a reaction (award emoji) to a resource or note\n */\n gitlab_create_award_emoji: tool({\n description: `Add a reaction (award emoji) to a merge request, issue, snippet, or a note/comment on these resources.\n\nCommon emoji names: thumbsup, thumbsdown, smile, tada, rocket, eyes, heart, +1, -1\n\nTo react to a specific comment/note, provide the note_id parameter.\n\nExamples:\n- React to MR: resource_type=\"merge_request\", project_id=\"group/project\", resource_iid=123, name=\"thumbsup\"\n- React to issue comment: resource_type=\"issue\", project_id=\"group/project\", resource_iid=456, note_id=789, name=\"rocket\"`,\n args: {\n resource_type: z\n .enum(['merge_request', 'issue', 'snippet'])\n .describe('Type of resource to add the reaction to'),\n project_id: z.string().describe('Project ID or URL-encoded path'),\n resource_iid: z.number().describe('Internal ID of the merge request, issue, or snippet'),\n name: z\n .string()\n .describe(\n 'Emoji name without colons (e.g., \"thumbsup\", \"rocket\", \"eyes\", \"heart\", \"tada\")'\n ),\n note_id: z\n .number()\n .optional()\n .describe('Note/comment ID to add the reaction to (if reacting to a specific comment)'),\n },\n execute: async (\n args: {\n resource_type: AwardableResourceType;\n project_id: string;\n resource_iid: number;\n name: string;\n note_id?: number;\n },\n _ctx: ToolContext\n ) => {\n validateAwardEmojiParams(args);\n\n const client = getGitLabClient();\n const resource = buildResourceId(args);\n const result = await client.createAwardEmoji(resource, args.name);\n return JSON.stringify(result, null, 2);\n },\n }),\n\n /**\n * List all reactions on a resource or note\n */\n gitlab_list_award_emoji: tool({\n description: `List all reactions (award emoji) on a merge request, issue, snippet, or a specific note/comment.\n\nExamples:\n- List reactions on MR: resource_type=\"merge_request\", project_id=\"group/project\", resource_iid=123\n- List reactions on a comment: resource_type=\"issue\", project_id=\"group/project\", resource_iid=456, note_id=789`,\n args: {\n resource_type: z.enum(['merge_request', 'issue', 'snippet']).describe('Type of resource'),\n project_id: z.string().describe('Project ID or URL-encoded path'),\n resource_iid: z.number().describe('Internal ID of the merge request, issue, or snippet'),\n note_id: z\n .number()\n .optional()\n .describe('Note/comment ID to list reactions for (if listing for a specific comment)'),\n },\n execute: async (\n args: {\n resource_type: AwardableResourceType;\n project_id: string;\n resource_iid: number;\n note_id?: number;\n },\n _ctx: ToolContext\n ) => {\n validateAwardEmojiParams(args);\n\n const client = getGitLabClient();\n const resource = buildResourceId(args);\n const result = await client.listAwardEmoji(resource);\n return JSON.stringify(result, null, 2);\n },\n }),\n\n /**\n * Remove a reaction from a resource or note\n */\n gitlab_delete_award_emoji: tool({\n description: `Remove a reaction (award emoji) from a merge request, issue, snippet, or note/comment.\n\nYou need the award_id which can be found using gitlab_list_award_emoji.\n\nExamples:\n- Remove reaction from MR: resource_type=\"merge_request\", project_id=\"group/project\", resource_iid=123, award_id=456\n- Remove from comment: resource_type=\"issue\", ..., note_id=789, award_id=456`,\n args: {\n resource_type: z.enum(['merge_request', 'issue', 'snippet']).describe('Type of resource'),\n project_id: z.string().describe('Project ID or URL-encoded path'),\n resource_iid: z.number().describe('Internal ID of the merge request, issue, or snippet'),\n award_id: z.number().describe('ID of the award emoji to remove'),\n note_id: z\n .number()\n .optional()\n .describe('Note/comment ID if removing from a specific comment'),\n },\n execute: async (\n args: {\n resource_type: AwardableResourceType;\n project_id: string;\n resource_iid: number;\n award_id: number;\n note_id?: number;\n },\n _ctx: ToolContext\n ) => {\n validateAwardEmojiParams(args);\n\n const client = getGitLabClient();\n const resource = buildResourceId(args);\n await client.deleteAwardEmoji(resource, args.award_id);\n return JSON.stringify({ success: true, message: 'Award emoji removed' }, null, 2);\n },\n }),\n};\n","import { tool, type ToolContext } from '@opencode-ai/plugin';\nimport { getGitLabClient } from '../utils.js';\n\nconst z = tool.schema;\n\ninterface OrbitStatusResponse {\n status: string;\n version?: string;\n features?: string[];\n [key: string]: unknown;\n}\n\ninterface OrbitSchemaResponse {\n node_types: Array<{\n name: string;\n domain: string;\n properties: Array<{ name: string; type: string }>;\n }>;\n relationship_types: Array<{\n name: string;\n source_types: string[];\n target_types: string[];\n }>;\n [key: string]: unknown;\n}\n\ninterface OrbitQueryResponse {\n result?: {\n format_version: string;\n query_type: string;\n nodes: Array<{\n type: string;\n id: string;\n [key: string]: unknown;\n }>;\n edges: Array<{\n from: string;\n from_id: string;\n to: string;\n to_id: string;\n type: string;\n }>;\n };\n query_type?: string;\n row_count?: number;\n code?: string;\n message?: string;\n [key: string]: unknown;\n}\n\n/**\n * Tools for interacting with GitLab's Orbit Knowledge Graph API.\n *\n * Orbit provides rich SDLC graph data including relationships between\n * projects, users, MRs, pipelines, issues, and more.\n *\n * Note: Orbit is only available on Premium/Ultimate tiers with the feature flag enabled.\n * All tools gracefully handle unavailability with helpful error messages.\n *\n * @example\n * // Check if Orbit is available\n * gitlab_orbit_status()\n *\n * @example\n * // Get neighbors of a merge request\n * gitlab_orbit_neighbors({ entity_type: \"MergeRequest\", entity_id: 377844873 })\n */\nexport const orbitTools = {\n gitlab_orbit_status: tool({\n description: `Check GitLab Orbit Knowledge Graph API availability and health.\n\nReturns the status of the Orbit API for the connected GitLab instance.\nOrbit is GitLab's Knowledge Graph API that provides rich SDLC graph data.\n\nNote: Orbit is only available on Premium/Ultimate tiers and requires the feature flag to be enabled.\nIf unavailable, returns an error with suggestions for REST API alternatives.`,\n args: {},\n execute: async (_args: Record<string, never>, _ctx: ToolContext) => {\n const client = getGitLabClient();\n\n try {\n const status = await client.fetch<OrbitStatusResponse>('GET', '/orbit/status');\n return JSON.stringify(\n {\n ...status,\n available: true,\n message: 'Orbit Knowledge Graph API is available',\n },\n null,\n 2\n );\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n if (errorMessage.includes('404') || errorMessage.includes('not found')) {\n return JSON.stringify(\n {\n available: false,\n error: 'Orbit API not available',\n reason:\n 'The Orbit Knowledge Graph API is not enabled on this GitLab instance. ' +\n 'Orbit requires GitLab Premium/Ultimate tier and the feature flag to be enabled.',\n alternatives: [\n 'Use REST API endpoints for MRs, issues, pipelines',\n 'Use GraphQL API for complex queries',\n 'Use gitlab_search for finding related entities',\n ],\n },\n null,\n 2\n );\n }\n\n if (errorMessage.includes('403') || errorMessage.includes('forbidden')) {\n return JSON.stringify(\n {\n available: false,\n error: 'Orbit API access forbidden',\n reason:\n 'Your access token does not have permission to use the Orbit API. ' +\n 'This may require specific scopes or Premium/Ultimate tier.',\n alternatives: [\n 'Check token scopes include api or read_api',\n 'Verify your GitLab tier supports Orbit',\n 'Use REST/GraphQL APIs as fallback',\n ],\n },\n null,\n 2\n );\n }\n\n if (errorMessage.includes('502')) {\n return JSON.stringify(\n {\n available: false,\n error: 'Orbit API temporarily unavailable',\n reason: 'The Orbit API returned a 502 error. This may be temporary.',\n suggestion: 'Try again later or use REST/GraphQL APIs as fallback.',\n },\n null,\n 2\n );\n }\n\n return JSON.stringify(\n {\n available: false,\n error: 'Orbit API error',\n message: errorMessage,\n alternatives: ['Use REST/GraphQL APIs as fallback'],\n },\n null,\n 2\n );\n }\n },\n }),\n\n gitlab_orbit_schema: tool({\n description: `Get the Orbit Knowledge Graph schema.\n\nReturns the available node types, relationship types, and their properties.\nUse this to understand what entities and relationships can be queried.\n\nNode type domains include:\n- Core: Project, Group, User\n- Source Code: File, Definition, Commit\n- Code Review: MergeRequest, Diff, Review\n- CI/CD: Pipeline, Job, Deployment\n- Planning: WorkItem (issues, epics, tasks)\n- Security: Vulnerability\n\nNote: Requires Orbit API to be available (Premium/Ultimate tier).`,\n args: {},\n execute: async (_args: Record<string, never>, _ctx: ToolContext) => {\n const client = getGitLabClient();\n\n try {\n const schema = await client.fetch<OrbitSchemaResponse>('GET', '/orbit/schema');\n return JSON.stringify(schema, null, 2);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n if (errorMessage.includes('404') || errorMessage.includes('not found')) {\n return JSON.stringify(\n {\n error: 'Orbit API not available',\n suggestion: 'Use gitlab_orbit_status to check API availability',\n },\n null,\n 2\n );\n }\n\n if (errorMessage.includes('502')) {\n return JSON.stringify(\n {\n error: 'Orbit API temporarily unavailable',\n suggestion:\n 'The Orbit API returned a 502 error. This may be temporary - try again later.',\n },\n null,\n 2\n );\n }\n\n throw error;\n }\n },\n }),\n\n gitlab_orbit_query: tool({\n description: `Execute a query against the Orbit Knowledge Graph.\n\nQuery types:\n- traversal: Walk the graph from a starting node\n- neighbors: Get immediate neighbors of a node\n\nIMPORTANT: The query format uses variable names for node references.\n- \"id\" in node definition is a VARIABLE NAME (alias), not the actual entity ID\n- Actual IDs go in \"filters\" with {\"field\": {\"op\": \"eq\", \"value\": X}} format\n\nExample neighbors query to get a project's connections:\n{\n \"query_type\": \"neighbors\",\n \"node\": {\n \"entity\": \"Project\",\n \"id\": \"p\",\n \"filters\": {\"id\": {\"op\": \"eq\", \"value\": 278964}}\n },\n \"neighbors\": {\"node\": \"p\", \"direction\": \"incoming\"},\n \"aggregations\": [],\n \"path\": {\"type\": \"shortest\", \"from\": \"p\", \"to\": \"p\", \"max_depth\": 1}\n}\n\nExample traversal query:\n{\n \"query_type\": \"traversal\",\n \"node\": {\n \"entity\": \"MergeRequest\",\n \"id\": \"mr\",\n \"filters\": {\"id\": {\"op\": \"eq\", \"value\": 377844873}}\n },\n \"neighbors\": {\"node\": \"mr\", \"direction\": \"both\"},\n \"aggregations\": [],\n \"path\": {\"type\": \"shortest\", \"from\": \"mr\", \"to\": \"mr\", \"max_depth\": 1}\n}\n\nNote: Use gitlab_get_merge_request to get the internal ID from an IID.\nReturns nodes array and edges array with relationship types.`,\n args: {\n // Using a JSON string rather than a structured zod schema because the Orbit query\n // format is still evolving. This allows flexibility as the API changes without\n // requiring schema updates for each iteration.\n query: z\n .string()\n .describe(\n 'JSON string containing the full query object. Must include query_type, node, neighbors, aggregations, and path fields. ' +\n 'See description for format details.'\n ),\n limit: z.number().optional().describe('Maximum number of results (default: 30)'),\n },\n execute: async (args: { query: string; limit?: number }, _ctx: ToolContext) => {\n const client = getGitLabClient();\n\n let queryObj: unknown;\n try {\n queryObj = JSON.parse(args.query);\n } catch {\n return JSON.stringify(\n {\n error: 'Invalid JSON in query parameter',\n suggestion: 'Ensure the query parameter is valid JSON',\n },\n null,\n 2\n );\n }\n\n const requestBody: Record<string, unknown> = {\n query: queryObj,\n };\n if (args.limit) {\n requestBody.limit = args.limit;\n }\n\n try {\n const result = await client.fetch<OrbitQueryResponse>('POST', '/orbit/query', requestBody);\n\n if (result.code) {\n return JSON.stringify(\n {\n error: 'Query compilation error',\n code: result.code,\n message: result.message,\n suggestion:\n 'Check query structure. Node \"id\" is a variable name, actual IDs go in filters.',\n },\n null,\n 2\n );\n }\n\n return JSON.stringify(result, null, 2);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n if (errorMessage.includes('404') || errorMessage.includes('not found')) {\n return JSON.stringify(\n {\n error: 'Orbit API not available',\n suggestion: 'Use gitlab_orbit_status to check API availability',\n },\n null,\n 2\n );\n }\n\n if (errorMessage.includes('502')) {\n return JSON.stringify(\n {\n error: 'Orbit query failed',\n message:\n 'The Orbit API returned a 502 error. This is a known issue with some entity types (e.g., source_code domain).',\n suggestion: 'Try a different entity type or use REST/GraphQL APIs as fallback.',\n },\n null,\n 2\n );\n }\n\n throw error;\n }\n },\n }),\n\n gitlab_orbit_neighbors: tool({\n description: `Get immediate neighbors of a node in the Orbit Knowledge Graph.\n\nThis is a simplified wrapper that builds the query for you.\nReturns nodes directly connected to the specified node.\n\nCommon use cases:\n- Get all connections to a project (users, groups, pipelines, MRs)\n- Get pipelines for an MR\n- Get files changed in a commit\n- Get deployments from a pipeline\n\nNote: Use GitLab internal numeric IDs (not IIDs).\nExample: For MR !123 in gitlab-org/gitlab, first get the internal ID via gitlab_get_merge_request,\nthen use that ID (e.g., 377844873).`,\n args: {\n entity_type: z\n .string()\n .describe(\n 'Type of the entity (e.g., Project, MergeRequest, User, Pipeline, Commit, WorkItem, Group)'\n ),\n entity_id: z\n .number()\n .describe(\n 'GitLab internal numeric ID (not IID). Get this from REST/GraphQL API responses.'\n ),\n direction: z\n .enum(['incoming', 'outgoing', 'both'])\n .optional()\n .describe('Direction of relationships to traverse (default: both)'),\n limit: z.number().optional().describe('Maximum number of neighbors to return (default: 30)'),\n },\n execute: async (\n args: {\n entity_type: string;\n entity_id: number;\n direction?: 'incoming' | 'outgoing' | 'both';\n limit?: number;\n },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n\n const direction = args.direction || 'both';\n const queryObj = {\n query_type: 'neighbors',\n node: {\n entity: args.entity_type,\n id: 'n',\n filters: {\n id: { op: 'eq', value: args.entity_id },\n },\n },\n neighbors: {\n node: 'n',\n direction: direction,\n },\n aggregations: [],\n path: { type: 'shortest', from: 'n', to: 'n', max_depth: 1 },\n };\n\n const requestBody: Record<string, unknown> = {\n query: queryObj,\n };\n if (args.limit) {\n requestBody.limit = args.limit;\n }\n\n try {\n const result = await client.fetch<OrbitQueryResponse>('POST', '/orbit/query', requestBody);\n\n if (result.code) {\n return JSON.stringify(\n {\n error: 'Query error',\n code: result.code,\n message: result.message,\n entity_type: args.entity_type,\n entity_id: args.entity_id,\n },\n null,\n 2\n );\n }\n\n return JSON.stringify(result, null, 2);\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n if (errorMessage.includes('404') || errorMessage.includes('not found')) {\n return JSON.stringify(\n {\n error: 'Orbit API not available',\n entity_type: args.entity_type,\n entity_id: args.entity_id,\n suggestion: 'Use gitlab_orbit_status to check API availability',\n },\n null,\n 2\n );\n }\n\n if (errorMessage.includes('502')) {\n return JSON.stringify(\n {\n error: 'Orbit query failed',\n entity_type: args.entity_type,\n entity_id: args.entity_id,\n message:\n 'The Orbit API returned a 502 error. This is a known issue with some entity types.',\n suggestion: 'Try a different entity type or use REST/GraphQL APIs as fallback.',\n },\n null,\n 2\n );\n }\n\n throw error;\n }\n },\n }),\n};\n","import type { ToolDefinition } from '@opencode-ai/plugin';\n\nimport { mergeRequestTools } from './merge-requests.js';\nimport { issueTools } from './issues.js';\nimport { epicTools } from './epics.js';\nimport { pipelineTools } from './pipelines.js';\nimport { repositoryTools } from './repository.js';\nimport { searchTools } from './search.js';\nimport { projectTools } from './projects.js';\nimport { userTools } from './users.js';\nimport { securityTools } from './security.js';\nimport { todoTools } from './todos.js';\nimport { wikiTools } from './wikis.js';\nimport { workItemTools } from './work-items.js';\nimport { discussionsUnifiedTools } from './discussions-unified.js';\nimport { notesUnifiedTools } from './notes-unified.js';\nimport { gitTools } from './git.js';\nimport { auditTools } from './audit.js';\nimport { awardEmojiTools } from './award-emoji.js';\nimport { orbitTools } from './orbit.js';\n\n/**\n * Tools exposed over the standalone MCP server (`opencode-gitlab-plugin` binary).\n */\nexport const mcpTools: Record<string, ToolDefinition> = {\n ...mergeRequestTools,\n ...issueTools,\n ...epicTools,\n ...pipelineTools,\n ...repositoryTools,\n ...searchTools,\n ...projectTools,\n ...userTools,\n ...securityTools,\n ...todoTools,\n ...wikiTools,\n ...workItemTools,\n ...discussionsUnifiedTools,\n ...notesUnifiedTools,\n ...gitTools,\n ...auditTools,\n ...awardEmojiTools,\n};\n\n/**\n * Every tool registered by the OpenCode plugin.\n */\nexport const allTools: Record<string, ToolDefinition> = {\n ...mcpTools,\n ...orbitTools,\n};\n","import { Plugin } from '@opencode/plugin';\n\nimport { allTools } from '../tools/index.js';\nimport { adaptTools } from './tool-adapter.js';\n\nexport const PLUGIN_ID = 'gitlab';\n\n/**\n * Guidance injected when tool registration is disabled via\n * `{ \"options\": { \"tools\": false } }`, so the model still knows where the\n * GitLab tools live.\n */\nexport const LAZY_MCP_HINT =\n `## GitLab Tools via lazy-mcp\\n` +\n `GitLab API tools (MRs, issues, pipelines, security, search, repos, users, todos, work items, ` +\n `discussions, notes, audit, git, award emoji) are served via the \"gitlab\" MCP server through lazy-mcp. ` +\n `Use lazy-mcp_list_commands with server \"gitlab\" to discover and call them.\\n` +\n `DAP tools (agents, flows, memory, skills) are on the \"gitlab-dap\" server instead.`;\n\n/**\n * GitLab Tools Plugin for OpenCode (plugin SDK v2)\n *\n * Provides tools for interacting with GitLab:\n * - Merge requests: get, list, changes, create, update, commits, pipelines, diffs (paginated), auto-merge\n * - Issues: create, get, list\n * - Epics: get, list, create, update, manage issues\n * - Pipelines: list, get, jobs, logs, retry, failing jobs, CI linter\n * - Repository: get file, commits, diff, branches, tree, create commit, commit comments\n * - Search: projects, issues, MRs, blobs, commits, etc.\n * - Projects: get project, list members\n * - Users: get current user\n * - TODOs: list, mark as done, get count\n * - Security: list vulnerabilities, get vulnerability details\n * - Audit: list project/group/instance audit events\n * - Wikis: get wiki page\n * - Work Items: get, list, create, update, notes\n * - Discussions: unified tools for all resource types (list, get, create/reply, resolve)\n * - Notes: list/get notes (flat view) for MR, issue, epic, snippet\n * - Git: execute safe, read-only git commands in repository\n * - Orbit: Knowledge Graph API (status, schema, query, neighbors)\n */\nexport const gitlabPluginV2 = Plugin.define({\n id: PLUGIN_ID,\n async setup(ctx) {\n if (ctx.options['tools'] === false) {\n await ctx.session.hook('context', (event) => {\n event.system.push({ type: 'text', text: LAZY_MCP_HINT });\n });\n return;\n }\n\n const directory = ctx.location.directory;\n const worktree = ctx.location.project.directory ?? directory;\n const tools = adaptTools(allTools, { directory, worktree });\n\n await ctx.tool.transform((editor) => {\n for (const definition of tools) {\n editor.add(definition);\n }\n });\n },\n});\n","import { tool, type ToolDefinition } from '@opencode-ai/plugin';\nimport type { Tool } from '@opencode/schema/tool';\nimport type { ToolContext } from '@opencode/plugin/promise/tool';\n\nconst z = tool.schema;\n\ntype JsonSchemaObject = Record<string, unknown>;\n\n/** Widest shape a V1 tool can return. */\ntype LegacyToolResult =\n | string\n | {\n title?: string;\n output: string;\n metadata?: Record<string, unknown>;\n attachments?: unknown[];\n };\n\n/**\n * Convert the zod raw shape used by the V1 `tool()` helper into a JSON Schema\n * object, which is what the V2 tool registry expects for `input`.\n */\nfunction toInputSchema(args: ToolDefinition['args']): JsonSchemaObject {\n const schema = z.toJSONSchema(z.object(args ?? {}), { io: 'input' }) as JsonSchemaObject;\n delete schema['$schema'];\n return {\n type: 'object',\n properties: {},\n additionalProperties: false,\n ...schema,\n };\n}\n\n/**\n * Convert a V1 `ToolResult` (string, or `{ title, output, metadata }`) into a\n * V2 `Tool.Result`.\n */\nfunction toToolResult(result: LegacyToolResult): Tool.Result {\n if (typeof result === 'string') {\n return { content: result };\n }\n\n const metadata: Record<string, unknown> = { ...(result.metadata ?? {}) };\n if (result.title !== undefined) metadata['title'] = result.title;\n if (result.attachments !== undefined) metadata['attachments'] = result.attachments;\n\n return {\n content: result.output,\n ...(Object.keys(metadata).length > 0 ? { metadata } : {}),\n };\n}\n\n/**\n * Build the V1 `ToolContext` the existing tool implementations expect from the\n * V2 execution context. None of the GitLab tools read it today, but keeping it\n * populated means tool bodies do not need to change.\n */\nfunction toLegacyContext(context: ToolContext, directory: string, worktree: string) {\n return {\n sessionID: context.sessionID,\n messageID: context.messageID,\n agent: context.agent,\n directory,\n worktree,\n abort: context.signal,\n metadata: (update: { title?: string; metadata?: Record<string, unknown> }) =>\n void context.progress(update as Tool.Metadata),\n ask: async () => {},\n };\n}\n\nexport interface AdaptOptions {\n directory: string;\n worktree: string;\n}\n\n/**\n * Adapt a single V1 tool definition to a V2 tool definition.\n *\n * Input is validated with the original zod schema before `execute` runs, so the\n * V1 tool implementations keep their runtime guarantees.\n */\nexport function adaptTool(name: string, definition: ToolDefinition, options: AdaptOptions) {\n const validator = z.object(definition.args ?? {});\n\n return {\n name,\n description: definition.description,\n input: toInputSchema(definition.args),\n async execute(input: unknown, context: ToolContext): Promise<Tool.Result> {\n const parsed = validator.parse(input ?? {});\n const legacyContext = toLegacyContext(context, options.directory, options.worktree);\n const result = (await definition.execute(\n parsed as never,\n legacyContext as never\n )) as LegacyToolResult;\n return toToolResult(result);\n },\n };\n}\n\n/**\n * Adapt a record of V1 tool definitions to V2 tool definitions.\n */\nexport function adaptTools(tools: Record<string, ToolDefinition>, options: AdaptOptions) {\n return Object.entries(tools).map(([name, definition]) => adaptTool(name, definition, options));\n}\n","import { type Plugin, type PluginInput } from '@opencode-ai/plugin';\n\nimport { allTools } from './tools/index.js';\nimport { gitlabPluginV2, LAZY_MCP_HINT } from './v2/plugin.js';\n\nexport { allTools, mcpTools } from './tools/index.js';\nexport { gitlabPluginV2, PLUGIN_ID } from './v2/plugin.js';\n\n/**\n * GitLab Tools Plugin for OpenCode — legacy (v1) plugin SDK entrypoint.\n *\n * Kept so the package keeps working on OpenCode v1. New installs use the v2\n * `setup()` implementation in `./v2/plugin.ts`.\n *\n * @deprecated Use the default export with the v2 plugin SDK.\n */\nexport const gitlabPlugin: Plugin = async (\n _input: PluginInput,\n options?: Record<string, unknown>\n) => {\n if (options?.['tools'] === false) {\n return {\n 'experimental.chat.system.transform': async (_hookInput: any, output: any) => {\n output.system.push(LAZY_MCP_HINT);\n },\n };\n }\n\n return { tool: allTools };\n};\n\n/**\n * Dual entrypoint: OpenCode v2 calls `setup()`, OpenCode v1 calls `server()`.\n *\n * See https://opencode.ai/v2/docs/build/plugins/migrate-v1\n */\nexport default {\n ...gitlabPluginV2,\n server: gitlabPlugin,\n};\n"],"mappings":"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","names":["path","path","resolve","path","path","path","path","path","tool","z","tool","tool","z","tool","tool","z","tool","tool","z","tool","tool","z","tool","validationError","tool","z","tool","tool","z","tool","tool","z","tool","tool","z","tool","tool","z","tool","tool","z","tool","tool","z","tool","resolve","tool","z","tool","normalizeBoolean","validationError","tool","z","tool","tool","z","tool","tool","z","tool","tool","z","tool","tool","z"]}