opencode-gitlab-plugin 2.0.3 → 2.1.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.
@@ -0,0 +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/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 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 (default: 20)'),\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 },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const mrs = 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 });\n return JSON.stringify(mrs, 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 },\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 },\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 });\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 'Auto-merge strategy. MERGE_WHEN_CHECKS_PASS (default) waits for all checks including approvals. ADD_TO_MERGE_TRAIN_WHEN_CHECKS_PASS adds to merge train 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.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_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 * 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 async fetch<T>(method: string, path: string, body?: unknown): Promise<T> {\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 // 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 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 } 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 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 }) {\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.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.fetch<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 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 }\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 ) {\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 throw new Error(`Failed to set auto-merge: ${result.mergeRequestAccept.errors.join(', ')}`);\n }\n\n if (!result.mergeRequestAccept.mergeRequest) {\n throw new Error('Failed to set auto-merge: No merge request returned');\n }\n\n return result.mergeRequestAccept.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","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_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 }) {\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.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.fetch<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","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\nconst CREATE_WORK_ITEM_MUTATION = `\n mutation createWorkItem(\n $projectPath: ID!\n $title: String!\n $workItemTypeId: WorkItemsTypeID!\n $description: String\n $labelIds: [LabelID!]\n $assigneeIds: [UserID!]\n ) {\n workItemCreate(input: {\n projectPath: $projectPath\n title: $title\n workItemTypeId: $workItemTypeId\n descriptionWidget: { description: $description }\n labelsWidget: { labelIds: $labelIds }\n assigneesWidget: { assigneeIds: $assigneeIds }\n }) {\n workItem {\n ${WORK_ITEM_FIELDS}\n }\n errors\n }\n }\n`;\n\nconst UPDATE_WORK_ITEM_MUTATION = `\n mutation updateWorkItem(\n $id: WorkItemID!\n $title: String\n $description: String\n $stateEvent: WorkItemStateEvent\n $labelIds: [LabelID!]\n $assigneeIds: [UserID!]\n ) {\n workItemUpdate(input: {\n id: $id\n title: $title\n descriptionWidget: { description: $description }\n stateEvent: $stateEvent\n labelsWidget: { labelIds: $labelIds }\n assigneesWidget: { assigneeIds: $assigneeIds }\n }) {\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 result = await this.fetchGraphQL<{\n workItemCreate: {\n workItem: Record<string, unknown>;\n errors: string[];\n };\n }>(CREATE_WORK_ITEM_MUTATION, {\n projectPath: projectId,\n title: options.title,\n workItemTypeId: toGid('WorkItems::Type', options.work_item_type_id),\n description: options.description,\n labelIds: labelIds?.length ? labelIds : undefined,\n assigneeIds: assigneeIds?.length ? assigneeIds : undefined,\n });\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 result = await this.fetchGraphQL<{\n workItemUpdate: {\n workItem: Record<string, unknown>;\n errors: string[];\n };\n }>(UPDATE_WORK_ITEM_MUTATION, {\n id: gid,\n title: options.title,\n description: options.description,\n stateEvent,\n labelIds: labelIds?.length ? labelIds : undefined,\n assigneeIds: assigneeIds?.length ? assigneeIds : undefined,\n });\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","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","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 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 (default: 20)'),\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 },\n _ctx: ToolContext\n ) => {\n const client = getGitLabClient();\n const issues = 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 });\n return JSON.stringify(issues, 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 * Valid resource types for each operation\n */\nconst VALID_LIST_CREATE_TYPES = ['merge_request', 'issue', 'epic', 'snippet'] as const;\nconst VALID_GET_NOTE_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 * Helper to validate required parameters based on resource type for list/create operations\n */\nfunction validateListCreateParams(\n resourceType: ListNotesResourceType | CreateNoteResourceType,\n args: {\n project_id?: string;\n group_id?: string;\n iid?: number;\n snippet_id?: number;\n }\n): void {\n // Validate resource type\n if (!VALID_LIST_CREATE_TYPES.includes(resourceType as (typeof VALID_LIST_CREATE_TYPES)[number])) {\n throw new Error(\n `Invalid resource_type '${resourceType}'. Must be one of: ${VALID_LIST_CREATE_TYPES.join(', ')}`\n );\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\n/**\n * Helper to validate required parameters for get note operations\n */\nfunction validateGetNoteParams(\n resourceType: GetNoteResourceType,\n args: {\n project_id?: string;\n group_id?: string;\n iid?: number;\n note_id?: number;\n }\n): void {\n // Validate resource type\n if (!VALID_GET_NOTE_TYPES.includes(resourceType as (typeof VALID_GET_NOTE_TYPES)[number])) {\n throw new Error(\n `Invalid resource_type '${resourceType}'. Must be one of: ${VALID_GET_NOTE_TYPES.join(', ')}`\n );\n }\n\n if (args.note_id == null) throw validationError('note_id', resourceType);\n\n switch (resourceType) {\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 }\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 validateListCreateParams(args.resource_type, args);\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 validateGetNoteParams(args.resource_type, args);\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 validateListCreateParams(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.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","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 { 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';\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 */\nexport const gitlabPlugin: Plugin = async (\n _input: PluginInput,\n options?: Record<string, unknown>\n) => {\n if (options?.tools === false) {\n return {};\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 },\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"]}