mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-21 13:00:04 +08:00
feat(gitlab): add repository, code-review, and CI job tools + validation fixes (#5205)
* feat(gitlab): add repository, code-review, and CI job tools + validation fixes Expand the GitLab integration with 12 new tools (all host-aware via getGitLabApiBase, wired through types/index/registry/block): - Repository: list_repository_tree, get_file, create_file, update_file, create_branch, list_branches, list_commits - Code review: get_merge_request_changes, approve_merge_request - CI jobs: list_pipeline_jobs, get_job_log, play_job Validation fixes from /validate-integration: - Correct the block inputs key (credential -> accessToken) so it matches the subBlock id and the params the block reads - Trim projectId before encoding in all tool request URLs (input hygiene) /validate-connector and /validate-trigger passed clean against the GitLab REST API v4 docs — no changes required. * fix(gitlab): address review feedback + regen docs - get_merge_request_changes: use the /diffs endpoint (/changes was removed in GitLab 18.0); return the diff array + count (drops the MR envelope that /diffs no longer provides), fetch max page size in a single call - create_file/update_file: send explicit `encoding: 'text'` for clarity - Remove `// =====` separator comments from types.ts (repo convention) - Regenerate GitLab integration docs + catalog for the 12 new tools
This commit is contained in:
@@ -41,6 +41,7 @@ List GitLab projects accessible to the authenticated user
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `owned` | boolean | No | Limit to projects owned by the current user |
|
||||
| `membership` | boolean | No | Limit to projects the current user is a member of |
|
||||
| `search` | string | No | Search projects by name |
|
||||
@@ -65,6 +66,7 @@ Get details of a specific GitLab project
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path \(e.g., "namespace/project"\) |
|
||||
|
||||
#### Output
|
||||
@@ -81,6 +83,7 @@ List issues in a GitLab project
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `state` | string | No | Filter by state \(opened, closed, all\) |
|
||||
| `labels` | string | No | Comma-separated list of label names |
|
||||
@@ -107,6 +110,7 @@ Get details of a specific GitLab issue
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `issueIid` | number | Yes | Issue number within the project \(the # shown in GitLab UI\) |
|
||||
|
||||
@@ -124,6 +128,7 @@ Create a new issue in a GitLab project
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `title` | string | Yes | Issue title |
|
||||
| `description` | string | No | Issue description \(Markdown supported\) |
|
||||
@@ -147,6 +152,7 @@ Update an existing issue in a GitLab project
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `issueIid` | number | Yes | Issue internal ID \(IID\) |
|
||||
| `title` | string | No | New issue title |
|
||||
@@ -172,6 +178,7 @@ Delete an issue from a GitLab project
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `issueIid` | number | Yes | Issue internal ID \(IID\) |
|
||||
|
||||
@@ -189,6 +196,7 @@ Add a comment to a GitLab issue
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `issueIid` | number | Yes | Issue internal ID \(IID\) |
|
||||
| `body` | string | Yes | Comment body \(Markdown supported\) |
|
||||
@@ -207,6 +215,7 @@ List merge requests in a GitLab project
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `state` | string | No | Filter by state \(opened, closed, merged, all\) |
|
||||
| `labels` | string | No | Comma-separated list of label names |
|
||||
@@ -232,6 +241,7 @@ Get details of a specific GitLab merge request
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `mergeRequestIid` | number | Yes | Merge request internal ID \(IID\) |
|
||||
|
||||
@@ -249,6 +259,7 @@ Create a new merge request in a GitLab project
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `sourceBranch` | string | Yes | Source branch name |
|
||||
| `targetBranch` | string | Yes | Target branch name |
|
||||
@@ -275,6 +286,7 @@ Update an existing merge request in a GitLab project
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `mergeRequestIid` | number | Yes | Merge request internal ID \(IID\) |
|
||||
| `title` | string | No | New merge request title |
|
||||
@@ -302,6 +314,7 @@ Merge a merge request in a GitLab project
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `mergeRequestIid` | number | Yes | Merge request internal ID \(IID\) |
|
||||
| `mergeCommitMessage` | string | No | Custom merge commit message |
|
||||
@@ -324,6 +337,7 @@ Add a comment to a GitLab merge request
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `mergeRequestIid` | number | Yes | Merge request internal ID \(IID\) |
|
||||
| `body` | string | Yes | Comment body \(Markdown supported\) |
|
||||
@@ -342,6 +356,7 @@ List pipelines in a GitLab project
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `ref` | string | No | Filter by ref \(branch or tag\) |
|
||||
| `status` | string | No | Filter by status \(created, waiting_for_resource, preparing, pending, running, success, failed, canceled, skipped, manual, scheduled\) |
|
||||
@@ -365,6 +380,7 @@ Get details of a specific GitLab pipeline
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `pipelineId` | number | Yes | Pipeline ID |
|
||||
|
||||
@@ -382,6 +398,7 @@ Trigger a new pipeline in a GitLab project
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `ref` | string | Yes | Branch or tag to run the pipeline on |
|
||||
| `variables` | array | No | Array of variables for the pipeline \(each with key, value, and optional variable_type\) |
|
||||
@@ -400,6 +417,7 @@ Retry a failed GitLab pipeline
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `pipelineId` | number | Yes | Pipeline ID |
|
||||
|
||||
@@ -417,6 +435,7 @@ Cancel a running GitLab pipeline
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `pipelineId` | number | Yes | Pipeline ID |
|
||||
|
||||
@@ -426,4 +445,449 @@ Cancel a running GitLab pipeline
|
||||
| --------- | ---- | ----------- |
|
||||
| `pipeline` | object | The cancelled GitLab pipeline |
|
||||
|
||||
### `gitlab_list_repository_tree`
|
||||
|
||||
List files and directories in a GitLab project repository
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `path` | string | No | Path inside the repository to list |
|
||||
| `ref` | string | No | Branch, tag, or commit SHA to list from |
|
||||
| `recursive` | boolean | No | Whether to list files recursively |
|
||||
| `perPage` | number | No | Number of results per page \(default 20, max 100\) |
|
||||
| `page` | number | No | Page number for pagination |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `tree` | array | List of repository tree entries |
|
||||
| `total` | number | Total number of tree entries |
|
||||
|
||||
### `gitlab_get_file`
|
||||
|
||||
Get the contents of a file from a GitLab project repository
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `filePath` | string | Yes | Path to the file in the repository |
|
||||
| `ref` | string | Yes | Branch, tag, or commit SHA |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `filePath` | string | The file path |
|
||||
| `fileName` | string | The file name |
|
||||
| `size` | number | The file size in bytes |
|
||||
| `ref` | string | The branch, tag, or commit SHA |
|
||||
| `blobId` | string | The blob ID |
|
||||
| `lastCommitId` | string | The last commit ID that modified the file |
|
||||
| `content` | string | The decoded file content |
|
||||
|
||||
### `gitlab_create_file`
|
||||
|
||||
Create a new file in a GitLab project repository
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `filePath` | string | Yes | Path to the file in the repository |
|
||||
| `branch` | string | Yes | Branch to commit the new file to |
|
||||
| `content` | string | Yes | File content |
|
||||
| `commitMessage` | string | Yes | Commit message |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `filePath` | string | The created file path |
|
||||
| `branch` | string | The branch the file was committed to |
|
||||
|
||||
### `gitlab_update_file`
|
||||
|
||||
Update an existing file in a GitLab project repository
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `filePath` | string | Yes | Path to the file in the repository |
|
||||
| `branch` | string | Yes | Branch to commit the update to |
|
||||
| `content` | string | Yes | New file content |
|
||||
| `commitMessage` | string | Yes | Commit message |
|
||||
| `lastCommitId` | string | No | Last known commit ID for the file \(optimistic locking\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `filePath` | string | The updated file path |
|
||||
| `branch` | string | The branch the update was committed to |
|
||||
|
||||
### `gitlab_create_branch`
|
||||
|
||||
Create a new branch in a GitLab project repository
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `branch` | string | Yes | Name of the new branch |
|
||||
| `ref` | string | Yes | Source branch/tag/SHA |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `name` | string | The created branch name |
|
||||
| `webUrl` | string | The web URL of the branch |
|
||||
| `protected` | boolean | Whether the branch is protected |
|
||||
| `commit` | object | The commit the branch points to |
|
||||
|
||||
### `gitlab_list_branches`
|
||||
|
||||
List branches in a GitLab project repository
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `search` | string | No | Filter branches by name |
|
||||
| `perPage` | number | No | Number of results per page \(default 20, max 100\) |
|
||||
| `page` | number | No | Page number for pagination |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `branches` | array | List of branches |
|
||||
| `total` | number | Total number of branches |
|
||||
|
||||
### `gitlab_list_commits`
|
||||
|
||||
List commits in a GitLab project repository
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `refName` | string | No | Branch, tag, or revision range to list commits from |
|
||||
| `since` | string | No | Only commits after this ISO 8601 date |
|
||||
| `until` | string | No | Only commits before this ISO 8601 date |
|
||||
| `path` | string | No | Only commits affecting this file path |
|
||||
| `author` | string | No | Filter commits by author |
|
||||
| `perPage` | number | No | Number of results per page \(default 20, max 100\) |
|
||||
| `page` | number | No | Page number for pagination |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `commits` | array | List of commits |
|
||||
| `total` | number | Total number of commits |
|
||||
|
||||
### `gitlab_get_merge_request_changes`
|
||||
|
||||
Get the file changes (diffs) of a GitLab merge request
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `mergeRequestIid` | number | Yes | Merge request internal ID \(IID\) |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `mergeRequestIid` | number | The merge request internal ID \(IID\) |
|
||||
| `changes` | array | List of file changes \(diffs\) |
|
||||
| `changesCount` | number | Number of changed files returned |
|
||||
|
||||
### `gitlab_approve_merge_request`
|
||||
|
||||
Approve a GitLab merge request
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `mergeRequestIid` | number | Yes | Merge request internal ID \(IID\) |
|
||||
| `sha` | string | No | HEAD SHA of the merge request to approve |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `approvalsRequired` | number | Number of approvals required |
|
||||
| `approvalsLeft` | number | Number of approvals still needed |
|
||||
| `approvedBy` | array | List of approvers |
|
||||
|
||||
### `gitlab_list_pipeline_jobs`
|
||||
|
||||
List jobs for a GitLab pipeline
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `pipelineId` | number | Yes | Pipeline ID |
|
||||
| `scope` | string | No | Filter jobs by scope \(e.g. created, running, success, failed\) |
|
||||
| `includeRetried` | boolean | No | Whether to include retried jobs |
|
||||
| `perPage` | number | No | Number of results per page \(default 20, max 100\) |
|
||||
| `page` | number | No | Page number for pagination |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `jobs` | array | List of pipeline jobs |
|
||||
| `total` | number | Total number of jobs |
|
||||
|
||||
### `gitlab_get_job_log`
|
||||
|
||||
Get the log (trace) of a GitLab job
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `jobId` | number | Yes | Job ID |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `log` | string | The job log \(trace\) output |
|
||||
|
||||
### `gitlab_play_job`
|
||||
|
||||
Trigger (play) a manual GitLab job
|
||||
|
||||
#### Input
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `host` | string | No | Self-managed GitLab host \(e.g. gitlab.example.com\). Defaults to gitlab.com. |
|
||||
| `projectId` | string | Yes | Project ID or URL-encoded path |
|
||||
| `jobId` | number | Yes | Job ID |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `id` | number | The job ID |
|
||||
| `name` | string | The job name |
|
||||
| `status` | string | The job status |
|
||||
| `webUrl` | string | The web URL of the job |
|
||||
|
||||
|
||||
|
||||
## Triggers
|
||||
|
||||
A **Trigger** is a block that starts a workflow when an event happens in this service.
|
||||
|
||||
### GitLab Comment
|
||||
|
||||
Trigger workflow when a comment is added on a commit, merge request, or issue
|
||||
|
||||
#### Configuration
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `accessToken` | string | Yes | Used to create the webhook in your project. Requires the Maintainer or Owner role. |
|
||||
| `projectId` | string | Yes | The GitLab project to register the webhook on. |
|
||||
| `host` | string | No | Self-managed GitLab host. Leave blank for gitlab.com. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `object_kind` | string | Event kind \(note\) |
|
||||
| `event_type` | string | GitLab event type from the X-Gitlab-Event header |
|
||||
| `object_attributes` | object | object_attributes output from the tool |
|
||||
| ↳ `id` | number | Comment ID |
|
||||
| ↳ `note` | string | Comment body |
|
||||
| ↳ `noteable_type` | string | What the comment is on \(Commit, MergeRequest, Issue, Snippet\) |
|
||||
| ↳ `action` | string | Action \(create, update\) |
|
||||
| ↳ `url` | string | Comment URL |
|
||||
|
||||
|
||||
---
|
||||
|
||||
### GitLab Event
|
||||
|
||||
Trigger workflow from any GitLab webhook event
|
||||
|
||||
#### Configuration
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `accessToken` | string | Yes | Used to create the webhook in your project. Requires the Maintainer or Owner role. |
|
||||
| `projectId` | string | Yes | The GitLab project to register the webhook on. |
|
||||
| `host` | string | No | Self-managed GitLab host. Leave blank for gitlab.com. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `object_kind` | string | Event kind \(push, merge_request, issue, etc.\) |
|
||||
| `event_type` | string | GitLab event type from the X-Gitlab-Event header |
|
||||
| `user` | json | Actor that triggered the event \(when present\) |
|
||||
| `object_attributes` | json | Event-specific attributes \(varies by object_kind\) |
|
||||
|
||||
|
||||
---
|
||||
|
||||
### GitLab Issue
|
||||
|
||||
Trigger workflow when an issue is opened, updated, or closed in GitLab
|
||||
|
||||
#### Configuration
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `accessToken` | string | Yes | Used to create the webhook in your project. Requires the Maintainer or Owner role. |
|
||||
| `projectId` | string | Yes | The GitLab project to register the webhook on. |
|
||||
| `host` | string | No | Self-managed GitLab host. Leave blank for gitlab.com. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `object_kind` | string | Event kind \(issue\) |
|
||||
| `event_type` | string | GitLab event type from the X-Gitlab-Event header |
|
||||
| `object_attributes` | object | object_attributes output from the tool |
|
||||
| ↳ `id` | number | Global issue ID |
|
||||
| ↳ `iid` | number | Project-scoped issue number |
|
||||
| ↳ `title` | string | Issue title |
|
||||
| ↳ `state` | string | State \(opened, closed\) |
|
||||
| ↳ `action` | string | Action \(open, close, reopen, update\) |
|
||||
| ↳ `description` | string | Issue description |
|
||||
| ↳ `confidential` | boolean | Whether the issue is confidential |
|
||||
| ↳ `url` | string | Issue URL |
|
||||
|
||||
|
||||
---
|
||||
|
||||
### GitLab Merge Request
|
||||
|
||||
Trigger workflow when a merge request is opened, updated, or merged in GitLab
|
||||
|
||||
#### Configuration
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `accessToken` | string | Yes | Used to create the webhook in your project. Requires the Maintainer or Owner role. |
|
||||
| `projectId` | string | Yes | The GitLab project to register the webhook on. |
|
||||
| `host` | string | No | Self-managed GitLab host. Leave blank for gitlab.com. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `object_kind` | string | Event kind \(merge_request\) |
|
||||
| `event_type` | string | GitLab event type from the X-Gitlab-Event header |
|
||||
| `object_attributes` | object | object_attributes output from the tool |
|
||||
| ↳ `id` | number | Global merge request ID |
|
||||
| ↳ `iid` | number | Project-scoped merge request number |
|
||||
| ↳ `title` | string | Merge request title |
|
||||
| ↳ `state` | string | State \(opened, closed, merged, locked\) |
|
||||
| ↳ `action` | string | Action \(open, close, reopen, update, merge, etc.\) |
|
||||
| ↳ `source_branch` | string | Source branch |
|
||||
| ↳ `target_branch` | string | Target branch |
|
||||
| ↳ `merge_status` | string | Merge status |
|
||||
| ↳ `draft` | boolean | Whether the merge request is a draft |
|
||||
| ↳ `url` | string | Merge request URL |
|
||||
|
||||
|
||||
---
|
||||
|
||||
### GitLab Pipeline
|
||||
|
||||
Trigger workflow when a pipeline status changes in GitLab
|
||||
|
||||
#### Configuration
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `accessToken` | string | Yes | Used to create the webhook in your project. Requires the Maintainer or Owner role. |
|
||||
| `projectId` | string | Yes | The GitLab project to register the webhook on. |
|
||||
| `host` | string | No | Self-managed GitLab host. Leave blank for gitlab.com. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `object_kind` | string | Event kind \(pipeline\) |
|
||||
| `event_type` | string | GitLab event type from the X-Gitlab-Event header |
|
||||
| `object_attributes` | object | object_attributes output from the tool |
|
||||
| ↳ `id` | number | Pipeline ID |
|
||||
| ↳ `status` | string | Pipeline status \(success, failed, running, etc.\) |
|
||||
| ↳ `detailed_status` | string | Detailed pipeline status |
|
||||
| ↳ `ref` | string | Ref the pipeline ran on |
|
||||
| ↳ `sha` | string | Commit SHA |
|
||||
| ↳ `source` | string | Pipeline source \(push, web, schedule, etc.\) |
|
||||
| ↳ `duration` | number | Pipeline duration in seconds |
|
||||
| ↳ `url` | string | Pipeline URL |
|
||||
|
||||
|
||||
---
|
||||
|
||||
### GitLab Push
|
||||
|
||||
Trigger workflow when commits are pushed to a GitLab project
|
||||
|
||||
#### Configuration
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
| --------- | ---- | -------- | ----------- |
|
||||
| `accessToken` | string | Yes | Used to create the webhook in your project. Requires the Maintainer or Owner role. |
|
||||
| `projectId` | string | Yes | The GitLab project to register the webhook on. |
|
||||
| `host` | string | No | Self-managed GitLab host. Leave blank for gitlab.com. |
|
||||
|
||||
#### Output
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------- | ---- | ----------- |
|
||||
| `object_kind` | string | Event kind \(push\) |
|
||||
| `event_type` | string | GitLab event type from the X-Gitlab-Event header |
|
||||
| `ref` | string | Git ref that was pushed \(e.g. refs/heads/main\) |
|
||||
| `branch` | string | Branch name derived from ref |
|
||||
| `before` | string | SHA before the push |
|
||||
| `after` | string | SHA after the push |
|
||||
| `checkout_sha` | string | SHA of the most recent commit |
|
||||
| `user_username` | string | Username of the pusher |
|
||||
| `user_name` | string | Display name of the pusher |
|
||||
| `user_email` | string | Email of the pusher |
|
||||
| `total_commits_count` | number | Number of commits in the push |
|
||||
| `commits` | json | Array of commit objects included in this push |
|
||||
|
||||
|
||||
@@ -46,6 +46,21 @@ export const GitLabBlock: BlockConfig<GitLabResponse> = {
|
||||
{ label: 'Create Pipeline', id: 'gitlab_create_pipeline' },
|
||||
{ label: 'Retry Pipeline', id: 'gitlab_retry_pipeline' },
|
||||
{ label: 'Cancel Pipeline', id: 'gitlab_cancel_pipeline' },
|
||||
// Repository Operations
|
||||
{ label: 'List Repository Tree', id: 'gitlab_list_repository_tree' },
|
||||
{ label: 'Get File', id: 'gitlab_get_file' },
|
||||
{ label: 'Create File', id: 'gitlab_create_file' },
|
||||
{ label: 'Update File', id: 'gitlab_update_file' },
|
||||
{ label: 'List Commits', id: 'gitlab_list_commits' },
|
||||
{ label: 'List Branches', id: 'gitlab_list_branches' },
|
||||
{ label: 'Create Branch', id: 'gitlab_create_branch' },
|
||||
// Additional Merge Request Operations
|
||||
{ label: 'Get MR Changes', id: 'gitlab_get_merge_request_changes' },
|
||||
{ label: 'Approve Merge Request', id: 'gitlab_approve_merge_request' },
|
||||
// Job Operations
|
||||
{ label: 'List Pipeline Jobs', id: 'gitlab_list_pipeline_jobs' },
|
||||
{ label: 'Get Job Log', id: 'gitlab_get_job_log' },
|
||||
{ label: 'Play Job', id: 'gitlab_play_job' },
|
||||
],
|
||||
value: () => 'gitlab_list_projects',
|
||||
},
|
||||
@@ -94,6 +109,18 @@ export const GitLabBlock: BlockConfig<GitLabResponse> = {
|
||||
'gitlab_create_pipeline',
|
||||
'gitlab_retry_pipeline',
|
||||
'gitlab_cancel_pipeline',
|
||||
'gitlab_list_repository_tree',
|
||||
'gitlab_get_file',
|
||||
'gitlab_create_file',
|
||||
'gitlab_update_file',
|
||||
'gitlab_list_commits',
|
||||
'gitlab_list_branches',
|
||||
'gitlab_create_branch',
|
||||
'gitlab_get_merge_request_changes',
|
||||
'gitlab_approve_merge_request',
|
||||
'gitlab_list_pipeline_jobs',
|
||||
'gitlab_get_job_log',
|
||||
'gitlab_play_job',
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -128,6 +155,8 @@ export const GitLabBlock: BlockConfig<GitLabResponse> = {
|
||||
'gitlab_update_merge_request',
|
||||
'gitlab_merge_merge_request',
|
||||
'gitlab_create_merge_request_note',
|
||||
'gitlab_get_merge_request_changes',
|
||||
'gitlab_approve_merge_request',
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -140,7 +169,12 @@ export const GitLabBlock: BlockConfig<GitLabResponse> = {
|
||||
required: true,
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['gitlab_get_pipeline', 'gitlab_retry_pipeline', 'gitlab_cancel_pipeline'],
|
||||
value: [
|
||||
'gitlab_get_pipeline',
|
||||
'gitlab_retry_pipeline',
|
||||
'gitlab_cancel_pipeline',
|
||||
'gitlab_list_pipeline_jobs',
|
||||
],
|
||||
},
|
||||
},
|
||||
// Title (for issue/MR creation)
|
||||
@@ -247,7 +281,135 @@ Return ONLY the comment text - no explanations, no extra formatting.`,
|
||||
required: true,
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['gitlab_create_pipeline'],
|
||||
value: ['gitlab_create_pipeline', 'gitlab_get_file', 'gitlab_create_branch'],
|
||||
},
|
||||
},
|
||||
// File Path
|
||||
{
|
||||
id: 'filePath',
|
||||
title: 'File Path',
|
||||
type: 'short-input',
|
||||
placeholder: 'Path to file (e.g., src/index.ts)',
|
||||
required: true,
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['gitlab_get_file', 'gitlab_create_file', 'gitlab_update_file'],
|
||||
},
|
||||
},
|
||||
// Branch
|
||||
{
|
||||
id: 'branch',
|
||||
title: 'Branch',
|
||||
type: 'short-input',
|
||||
placeholder: 'Branch name',
|
||||
required: true,
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['gitlab_create_file', 'gitlab_update_file', 'gitlab_create_branch'],
|
||||
},
|
||||
},
|
||||
// File Content
|
||||
{
|
||||
id: 'content',
|
||||
title: 'File Content',
|
||||
type: 'long-input',
|
||||
placeholder: 'File content',
|
||||
required: true,
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['gitlab_create_file', 'gitlab_update_file'],
|
||||
},
|
||||
},
|
||||
// Commit Message
|
||||
{
|
||||
id: 'commitMessage',
|
||||
title: 'Commit Message',
|
||||
type: 'short-input',
|
||||
placeholder: 'Commit message',
|
||||
required: true,
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['gitlab_create_file', 'gitlab_update_file'],
|
||||
},
|
||||
},
|
||||
// Job ID
|
||||
{
|
||||
id: 'jobId',
|
||||
title: 'Job ID',
|
||||
type: 'short-input',
|
||||
placeholder: 'Enter job ID',
|
||||
required: true,
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['gitlab_get_job_log', 'gitlab_play_job'],
|
||||
},
|
||||
},
|
||||
// Subdirectory path (for repository tree)
|
||||
{
|
||||
id: 'path',
|
||||
title: 'Path',
|
||||
type: 'short-input',
|
||||
placeholder: 'Subdirectory path (optional)',
|
||||
mode: 'advanced',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['gitlab_list_repository_tree'],
|
||||
},
|
||||
},
|
||||
// Recursive tree listing
|
||||
{
|
||||
id: 'recursive',
|
||||
title: 'Recursive',
|
||||
type: 'switch',
|
||||
mode: 'advanced',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['gitlab_list_repository_tree'],
|
||||
},
|
||||
},
|
||||
// Ref name filter (for list commits)
|
||||
{
|
||||
id: 'refName',
|
||||
title: 'Ref (branch/tag)',
|
||||
type: 'short-input',
|
||||
placeholder: 'Branch or tag (optional)',
|
||||
mode: 'advanced',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['gitlab_list_commits'],
|
||||
},
|
||||
},
|
||||
// Job scope filter (for list pipeline jobs)
|
||||
{
|
||||
id: 'scope',
|
||||
title: 'Job Scope',
|
||||
type: 'dropdown',
|
||||
options: [
|
||||
{ label: 'All', id: '' },
|
||||
{ label: 'Failed', id: 'failed' },
|
||||
{ label: 'Success', id: 'success' },
|
||||
{ label: 'Running', id: 'running' },
|
||||
{ label: 'Pending', id: 'pending' },
|
||||
{ label: 'Canceled', id: 'canceled' },
|
||||
{ label: 'Manual', id: 'manual' },
|
||||
],
|
||||
value: () => '',
|
||||
mode: 'advanced',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['gitlab_list_pipeline_jobs'],
|
||||
},
|
||||
},
|
||||
// Commit SHA (for approve merge request)
|
||||
{
|
||||
id: 'sha',
|
||||
title: 'Commit SHA',
|
||||
type: 'short-input',
|
||||
placeholder: 'Optional HEAD SHA to approve',
|
||||
mode: 'advanced',
|
||||
condition: {
|
||||
field: 'operation',
|
||||
value: ['gitlab_approve_merge_request'],
|
||||
},
|
||||
},
|
||||
// Labels
|
||||
@@ -427,6 +589,10 @@ Return ONLY the commit message - no explanations, no extra text.`,
|
||||
'gitlab_list_issues',
|
||||
'gitlab_list_merge_requests',
|
||||
'gitlab_list_pipelines',
|
||||
'gitlab_list_repository_tree',
|
||||
'gitlab_list_branches',
|
||||
'gitlab_list_commits',
|
||||
'gitlab_list_pipeline_jobs',
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -444,6 +610,10 @@ Return ONLY the commit message - no explanations, no extra text.`,
|
||||
'gitlab_list_issues',
|
||||
'gitlab_list_merge_requests',
|
||||
'gitlab_list_pipelines',
|
||||
'gitlab_list_repository_tree',
|
||||
'gitlab_list_branches',
|
||||
'gitlab_list_commits',
|
||||
'gitlab_list_pipeline_jobs',
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -475,6 +645,18 @@ Return ONLY the commit message - no explanations, no extra text.`,
|
||||
'gitlab_create_pipeline',
|
||||
'gitlab_retry_pipeline',
|
||||
'gitlab_cancel_pipeline',
|
||||
'gitlab_list_repository_tree',
|
||||
'gitlab_get_file',
|
||||
'gitlab_create_file',
|
||||
'gitlab_update_file',
|
||||
'gitlab_create_branch',
|
||||
'gitlab_list_branches',
|
||||
'gitlab_list_commits',
|
||||
'gitlab_get_merge_request_changes',
|
||||
'gitlab_approve_merge_request',
|
||||
'gitlab_list_pipeline_jobs',
|
||||
'gitlab_get_job_log',
|
||||
'gitlab_play_job',
|
||||
],
|
||||
config: {
|
||||
tool: (params) => {
|
||||
@@ -710,6 +892,140 @@ Return ONLY the commit message - no explanations, no extra text.`,
|
||||
pipelineId: Number(params.pipelineId),
|
||||
}
|
||||
|
||||
case 'gitlab_list_repository_tree':
|
||||
if (!params.projectId?.trim()) {
|
||||
throw new Error('Project ID is required.')
|
||||
}
|
||||
return {
|
||||
...baseParams,
|
||||
projectId: params.projectId.trim(),
|
||||
path: params.path?.trim() || undefined,
|
||||
recursive: params.recursive || undefined,
|
||||
perPage: params.perPage ? Number(params.perPage) : undefined,
|
||||
page: params.page ? Number(params.page) : undefined,
|
||||
}
|
||||
|
||||
case 'gitlab_get_file':
|
||||
if (!params.projectId?.trim() || !params.filePath?.trim() || !params.ref?.trim()) {
|
||||
throw new Error('Project ID, file path, and ref are required.')
|
||||
}
|
||||
return {
|
||||
...baseParams,
|
||||
projectId: params.projectId.trim(),
|
||||
filePath: params.filePath.trim(),
|
||||
ref: params.ref.trim(),
|
||||
}
|
||||
|
||||
case 'gitlab_create_file':
|
||||
case 'gitlab_update_file':
|
||||
if (
|
||||
!params.projectId?.trim() ||
|
||||
!params.filePath?.trim() ||
|
||||
!params.branch?.trim() ||
|
||||
!params.content ||
|
||||
!params.commitMessage?.trim()
|
||||
) {
|
||||
throw new Error(
|
||||
'Project ID, file path, branch, content, and commit message are required.'
|
||||
)
|
||||
}
|
||||
return {
|
||||
...baseParams,
|
||||
projectId: params.projectId.trim(),
|
||||
filePath: params.filePath.trim(),
|
||||
branch: params.branch.trim(),
|
||||
content: params.content,
|
||||
commitMessage: params.commitMessage.trim(),
|
||||
}
|
||||
|
||||
case 'gitlab_create_branch':
|
||||
if (!params.projectId?.trim() || !params.branch?.trim() || !params.ref?.trim()) {
|
||||
throw new Error('Project ID, branch name, and source ref are required.')
|
||||
}
|
||||
return {
|
||||
...baseParams,
|
||||
projectId: params.projectId.trim(),
|
||||
branch: params.branch.trim(),
|
||||
ref: params.ref.trim(),
|
||||
}
|
||||
|
||||
case 'gitlab_list_branches':
|
||||
if (!params.projectId?.trim()) {
|
||||
throw new Error('Project ID is required.')
|
||||
}
|
||||
return {
|
||||
...baseParams,
|
||||
projectId: params.projectId.trim(),
|
||||
perPage: params.perPage ? Number(params.perPage) : undefined,
|
||||
page: params.page ? Number(params.page) : undefined,
|
||||
}
|
||||
|
||||
case 'gitlab_list_commits':
|
||||
if (!params.projectId?.trim()) {
|
||||
throw new Error('Project ID is required.')
|
||||
}
|
||||
return {
|
||||
...baseParams,
|
||||
projectId: params.projectId.trim(),
|
||||
refName: params.refName?.trim() || undefined,
|
||||
perPage: params.perPage ? Number(params.perPage) : undefined,
|
||||
page: params.page ? Number(params.page) : undefined,
|
||||
}
|
||||
|
||||
case 'gitlab_get_merge_request_changes':
|
||||
if (!params.projectId?.trim() || !params.mergeRequestIid) {
|
||||
throw new Error('Project ID and Merge Request IID are required.')
|
||||
}
|
||||
return {
|
||||
...baseParams,
|
||||
projectId: params.projectId.trim(),
|
||||
mergeRequestIid: Number(params.mergeRequestIid),
|
||||
}
|
||||
|
||||
case 'gitlab_approve_merge_request':
|
||||
if (!params.projectId?.trim() || !params.mergeRequestIid) {
|
||||
throw new Error('Project ID and Merge Request IID are required.')
|
||||
}
|
||||
return {
|
||||
...baseParams,
|
||||
projectId: params.projectId.trim(),
|
||||
mergeRequestIid: Number(params.mergeRequestIid),
|
||||
sha: params.sha?.trim() || undefined,
|
||||
}
|
||||
|
||||
case 'gitlab_list_pipeline_jobs':
|
||||
if (!params.projectId?.trim() || !params.pipelineId) {
|
||||
throw new Error('Project ID and Pipeline ID are required.')
|
||||
}
|
||||
return {
|
||||
...baseParams,
|
||||
projectId: params.projectId.trim(),
|
||||
pipelineId: Number(params.pipelineId),
|
||||
scope: params.scope || undefined,
|
||||
perPage: params.perPage ? Number(params.perPage) : undefined,
|
||||
page: params.page ? Number(params.page) : undefined,
|
||||
}
|
||||
|
||||
case 'gitlab_get_job_log':
|
||||
if (!params.projectId?.trim() || !params.jobId) {
|
||||
throw new Error('Project ID and Job ID are required.')
|
||||
}
|
||||
return {
|
||||
...baseParams,
|
||||
projectId: params.projectId.trim(),
|
||||
jobId: Number(params.jobId),
|
||||
}
|
||||
|
||||
case 'gitlab_play_job':
|
||||
if (!params.projectId?.trim() || !params.jobId) {
|
||||
throw new Error('Project ID and Job ID are required.')
|
||||
}
|
||||
return {
|
||||
...baseParams,
|
||||
projectId: params.projectId.trim(),
|
||||
jobId: Number(params.jobId),
|
||||
}
|
||||
|
||||
default:
|
||||
return baseParams
|
||||
}
|
||||
@@ -718,7 +1034,7 @@ Return ONLY the commit message - no explanations, no extra text.`,
|
||||
},
|
||||
inputs: {
|
||||
operation: { type: 'string', description: 'Operation to perform' },
|
||||
credential: { type: 'string', description: 'GitLab access token' },
|
||||
accessToken: { type: 'string', description: 'GitLab Personal Access Token' },
|
||||
host: { type: 'string', description: 'Self-managed GitLab host (defaults to gitlab.com)' },
|
||||
projectId: { type: 'string', description: 'Project ID or URL-encoded path' },
|
||||
issueIid: { type: 'number', description: 'Issue internal ID' },
|
||||
@@ -745,6 +1061,16 @@ Return ONLY the commit message - no explanations, no extra text.`,
|
||||
mergeCommitMessage: { type: 'string', description: 'Custom merge commit message' },
|
||||
perPage: { type: 'number', description: 'Results per page' },
|
||||
page: { type: 'number', description: 'Page number' },
|
||||
filePath: { type: 'string', description: 'Path to file in the repository' },
|
||||
branch: { type: 'string', description: 'Branch name' },
|
||||
content: { type: 'string', description: 'File content' },
|
||||
commitMessage: { type: 'string', description: 'Commit message' },
|
||||
jobId: { type: 'number', description: 'Job ID' },
|
||||
path: { type: 'string', description: 'Subdirectory path for repository tree' },
|
||||
recursive: { type: 'boolean', description: 'Recursively list repository tree' },
|
||||
refName: { type: 'string', description: 'Branch or tag name filter' },
|
||||
scope: { type: 'string', description: 'Job scope filter' },
|
||||
sha: { type: 'string', description: 'Commit SHA' },
|
||||
},
|
||||
outputs: {
|
||||
// Project outputs
|
||||
@@ -761,6 +1087,21 @@ Return ONLY the commit message - no explanations, no extra text.`,
|
||||
pipeline: { type: 'json', description: 'Pipeline details' },
|
||||
// Note outputs
|
||||
note: { type: 'json', description: 'Comment/note details' },
|
||||
// Repository outputs
|
||||
tree: { type: 'json', description: 'Repository tree entries' },
|
||||
content: { type: 'string', description: 'File contents (decoded)' },
|
||||
fileName: { type: 'string', description: 'File name' },
|
||||
branches: { type: 'json', description: 'List of branches' },
|
||||
commits: { type: 'json', description: 'List of commits' },
|
||||
name: { type: 'string', description: 'Created branch name' },
|
||||
webUrl: { type: 'string', description: 'Web URL' },
|
||||
// Merge request change outputs
|
||||
changes: { type: 'json', description: 'Merge request file changes/diffs' },
|
||||
approvalsRequired: { type: 'number', description: 'Approvals required' },
|
||||
approvalsLeft: { type: 'number', description: 'Approvals remaining' },
|
||||
// Job outputs
|
||||
jobs: { type: 'json', description: 'Pipeline jobs' },
|
||||
log: { type: 'string', description: 'Job log output' },
|
||||
// Success indicator
|
||||
success: { type: 'boolean', description: 'Operation success status' },
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"updatedAt": "2026-06-18",
|
||||
"updatedAt": "2026-06-25",
|
||||
"integrations": [
|
||||
{
|
||||
"type": "onepassword",
|
||||
@@ -5628,11 +5628,90 @@
|
||||
{
|
||||
"name": "Cancel Pipeline",
|
||||
"description": "Cancel a running GitLab pipeline"
|
||||
},
|
||||
{
|
||||
"name": "List Repository Tree",
|
||||
"description": "List files and directories in a GitLab project repository"
|
||||
},
|
||||
{
|
||||
"name": "Get File",
|
||||
"description": "Get the contents of a file from a GitLab project repository"
|
||||
},
|
||||
{
|
||||
"name": "Create File",
|
||||
"description": "Create a new file in a GitLab project repository"
|
||||
},
|
||||
{
|
||||
"name": "Update File",
|
||||
"description": "Update an existing file in a GitLab project repository"
|
||||
},
|
||||
{
|
||||
"name": "List Commits",
|
||||
"description": "List commits in a GitLab project repository"
|
||||
},
|
||||
{
|
||||
"name": "List Branches",
|
||||
"description": "List branches in a GitLab project repository"
|
||||
},
|
||||
{
|
||||
"name": "Create Branch",
|
||||
"description": "Create a new branch in a GitLab project repository"
|
||||
},
|
||||
{
|
||||
"name": "Get MR Changes",
|
||||
"description": "Get the file changes (diffs) of a GitLab merge request"
|
||||
},
|
||||
{
|
||||
"name": "Approve Merge Request",
|
||||
"description": "Approve a GitLab merge request"
|
||||
},
|
||||
{
|
||||
"name": "List Pipeline Jobs",
|
||||
"description": "List jobs for a GitLab pipeline"
|
||||
},
|
||||
{
|
||||
"name": "Get Job Log",
|
||||
"description": "Get the log (trace) of a GitLab job"
|
||||
},
|
||||
{
|
||||
"name": "Play Job",
|
||||
"description": "Trigger (play) a manual GitLab job"
|
||||
}
|
||||
],
|
||||
"operationCount": 19,
|
||||
"triggers": [],
|
||||
"triggerCount": 0,
|
||||
"operationCount": 31,
|
||||
"triggers": [
|
||||
{
|
||||
"id": "gitlab_push",
|
||||
"name": "GitLab Push",
|
||||
"description": "Trigger workflow when commits are pushed to a GitLab project"
|
||||
},
|
||||
{
|
||||
"id": "gitlab_merge_request",
|
||||
"name": "GitLab Merge Request",
|
||||
"description": "Trigger workflow when a merge request is opened, updated, or merged in GitLab"
|
||||
},
|
||||
{
|
||||
"id": "gitlab_issue",
|
||||
"name": "GitLab Issue",
|
||||
"description": "Trigger workflow when an issue is opened, updated, or closed in GitLab"
|
||||
},
|
||||
{
|
||||
"id": "gitlab_pipeline",
|
||||
"name": "GitLab Pipeline",
|
||||
"description": "Trigger workflow when a pipeline status changes in GitLab"
|
||||
},
|
||||
{
|
||||
"id": "gitlab_comment",
|
||||
"name": "GitLab Comment",
|
||||
"description": "Trigger workflow when a comment is added on a commit, merge request, or issue"
|
||||
},
|
||||
{
|
||||
"id": "gitlab_webhook",
|
||||
"name": "GitLab Event",
|
||||
"description": "Trigger workflow from any GitLab webhook event"
|
||||
}
|
||||
],
|
||||
"triggerCount": 6,
|
||||
"authType": "api-key",
|
||||
"category": "tools",
|
||||
"integrationType": "devops",
|
||||
@@ -11233,8 +11312,39 @@
|
||||
}
|
||||
],
|
||||
"operationCount": 6,
|
||||
"triggers": [],
|
||||
"triggerCount": 0,
|
||||
"triggers": [
|
||||
{
|
||||
"id": "pagerduty_incident_triggered",
|
||||
"name": "PagerDuty Incident Triggered",
|
||||
"description": "Trigger workflow when a new incident is triggered in PagerDuty"
|
||||
},
|
||||
{
|
||||
"id": "pagerduty_incident_acknowledged",
|
||||
"name": "PagerDuty Incident Acknowledged",
|
||||
"description": "Trigger workflow when an incident is acknowledged in PagerDuty"
|
||||
},
|
||||
{
|
||||
"id": "pagerduty_incident_resolved",
|
||||
"name": "PagerDuty Incident Resolved",
|
||||
"description": "Trigger workflow when an incident is resolved in PagerDuty"
|
||||
},
|
||||
{
|
||||
"id": "pagerduty_incident_escalated",
|
||||
"name": "PagerDuty Incident Escalated",
|
||||
"description": "Trigger workflow when an incident is escalated in PagerDuty"
|
||||
},
|
||||
{
|
||||
"id": "pagerduty_incident_reassigned",
|
||||
"name": "PagerDuty Incident Reassigned",
|
||||
"description": "Trigger workflow when an incident is reassigned in PagerDuty"
|
||||
},
|
||||
{
|
||||
"id": "pagerduty_webhook",
|
||||
"name": "PagerDuty Incident Event",
|
||||
"description": "Trigger workflow from any PagerDuty incident event"
|
||||
}
|
||||
],
|
||||
"triggerCount": 6,
|
||||
"authType": "api-key",
|
||||
"category": "tools",
|
||||
"integrationType": "observability",
|
||||
@@ -18289,8 +18399,34 @@
|
||||
}
|
||||
],
|
||||
"operationCount": 26,
|
||||
"triggers": [],
|
||||
"triggerCount": 0,
|
||||
"triggers": [
|
||||
{
|
||||
"id": "zendesk_ticket_created",
|
||||
"name": "Zendesk Ticket Created",
|
||||
"description": "Trigger workflow when a new ticket is created in Zendesk"
|
||||
},
|
||||
{
|
||||
"id": "zendesk_ticket_status_changed",
|
||||
"name": "Zendesk Ticket Status Changed",
|
||||
"description": "Trigger workflow when a ticket status changes in Zendesk"
|
||||
},
|
||||
{
|
||||
"id": "zendesk_ticket_comment_added",
|
||||
"name": "Zendesk Ticket Comment Added",
|
||||
"description": "Trigger workflow when a comment is added to a Zendesk ticket"
|
||||
},
|
||||
{
|
||||
"id": "zendesk_ticket_priority_changed",
|
||||
"name": "Zendesk Ticket Priority Changed",
|
||||
"description": "Trigger workflow when a ticket priority changes in Zendesk"
|
||||
},
|
||||
{
|
||||
"id": "zendesk_webhook",
|
||||
"name": "Zendesk Ticket Event",
|
||||
"description": "Trigger workflow from any Zendesk ticket event"
|
||||
}
|
||||
],
|
||||
"triggerCount": 5,
|
||||
"authType": "api-key",
|
||||
"category": "tools",
|
||||
"integrationType": "support",
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
import type {
|
||||
GitLabApproveMergeRequestParams,
|
||||
GitLabApproveMergeRequestResponse,
|
||||
} from '@/tools/gitlab/types'
|
||||
import { getGitLabApiBase } from '@/tools/gitlab/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const gitlabApproveMergeRequestTool: ToolConfig<
|
||||
GitLabApproveMergeRequestParams,
|
||||
GitLabApproveMergeRequestResponse
|
||||
> = {
|
||||
id: 'gitlab_approve_merge_request',
|
||||
name: 'GitLab Approve Merge Request',
|
||||
description: 'Approve a GitLab merge request',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'GitLab Personal Access Token',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Self-managed GitLab host (e.g. gitlab.example.com). Defaults to gitlab.com.',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or URL-encoded path',
|
||||
},
|
||||
mergeRequestIid: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Merge request internal ID (IID)',
|
||||
},
|
||||
sha: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'HEAD SHA of the merge request to approve',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/merge_requests/${params.mergeRequestIid}/approve`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
'PRIVATE-TOKEN': params.accessToken,
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, unknown> = {}
|
||||
|
||||
if (params.sha) body.sha = params.sha
|
||||
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return {
|
||||
success: false,
|
||||
error: `GitLab API error: ${response.status} ${errorText}`,
|
||||
output: {},
|
||||
}
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
approvalsRequired: data.approvals_required ?? null,
|
||||
approvalsLeft: data.approvals_left ?? null,
|
||||
approvedBy: data.approved_by ?? [],
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
approvalsRequired: {
|
||||
type: 'number',
|
||||
description: 'Number of approvals required',
|
||||
},
|
||||
approvalsLeft: {
|
||||
type: 'number',
|
||||
description: 'Number of approvals still needed',
|
||||
},
|
||||
approvedBy: {
|
||||
type: 'array',
|
||||
description: 'List of approvers',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -40,7 +40,7 @@ export const gitlabCancelPipelineTool: ToolConfig<
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId))
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/pipelines/${params.pipelineId}/cancel`
|
||||
},
|
||||
method: 'POST',
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
import type { GitLabCreateBranchParams, GitLabCreateBranchResponse } from '@/tools/gitlab/types'
|
||||
import { getGitLabApiBase } from '@/tools/gitlab/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const gitlabCreateBranchTool: ToolConfig<
|
||||
GitLabCreateBranchParams,
|
||||
GitLabCreateBranchResponse
|
||||
> = {
|
||||
id: 'gitlab_create_branch',
|
||||
name: 'GitLab Create Branch',
|
||||
description: 'Create a new branch in a GitLab project repository',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'GitLab Personal Access Token',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Self-managed GitLab host (e.g. gitlab.example.com). Defaults to gitlab.com.',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or URL-encoded path',
|
||||
},
|
||||
branch: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Name of the new branch',
|
||||
},
|
||||
ref: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Source branch/tag/SHA',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
const queryParams = new URLSearchParams()
|
||||
queryParams.append('branch', String(params.branch))
|
||||
queryParams.append('ref', String(params.ref))
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/repository/branches?${queryParams.toString()}`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'PRIVATE-TOKEN': params.accessToken,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return {
|
||||
success: false,
|
||||
error: `GitLab API error: ${response.status} ${errorText}`,
|
||||
output: {},
|
||||
}
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
name: data.name ?? null,
|
||||
webUrl: data.web_url ?? null,
|
||||
protected: data.protected ?? null,
|
||||
commit: data.commit ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'The created branch name',
|
||||
},
|
||||
webUrl: {
|
||||
type: 'string',
|
||||
description: 'The web URL of the branch',
|
||||
},
|
||||
protected: {
|
||||
type: 'boolean',
|
||||
description: 'Whether the branch is protected',
|
||||
},
|
||||
commit: {
|
||||
type: 'object',
|
||||
description: 'The commit the branch points to',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
import type { GitLabCreateFileParams, GitLabCreateFileResponse } from '@/tools/gitlab/types'
|
||||
import { getGitLabApiBase } from '@/tools/gitlab/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const gitlabCreateFileTool: ToolConfig<GitLabCreateFileParams, GitLabCreateFileResponse> = {
|
||||
id: 'gitlab_create_file',
|
||||
name: 'GitLab Create File',
|
||||
description: 'Create a new file in a GitLab project repository',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'GitLab Personal Access Token',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Self-managed GitLab host (e.g. gitlab.example.com). Defaults to gitlab.com.',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or URL-encoded path',
|
||||
},
|
||||
filePath: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Path to the file in the repository',
|
||||
},
|
||||
branch: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Branch to commit the new file to',
|
||||
},
|
||||
content: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'File content',
|
||||
},
|
||||
commitMessage: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Commit message',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
const encodedPath = encodeURIComponent(String(params.filePath))
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/repository/files/${encodedPath}`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
'PRIVATE-TOKEN': params.accessToken,
|
||||
}),
|
||||
body: (params) => ({
|
||||
branch: params.branch,
|
||||
content: params.content,
|
||||
commit_message: params.commitMessage,
|
||||
encoding: 'text',
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return {
|
||||
success: false,
|
||||
error: `GitLab API error: ${response.status} ${errorText}`,
|
||||
output: {},
|
||||
}
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
filePath: data.file_path ?? null,
|
||||
branch: data.branch ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
filePath: {
|
||||
type: 'string',
|
||||
description: 'The created file path',
|
||||
},
|
||||
branch: {
|
||||
type: 'string',
|
||||
description: 'The branch the file was committed to',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -74,7 +74,7 @@ export const gitlabCreateIssueTool: ToolConfig<GitLabCreateIssueParams, GitLabCr
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId))
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/issues`
|
||||
},
|
||||
method: 'POST',
|
||||
|
||||
@@ -46,7 +46,7 @@ export const gitlabCreateIssueNoteTool: ToolConfig<
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId))
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/issues/${params.issueIid}/notes`
|
||||
},
|
||||
method: 'POST',
|
||||
|
||||
@@ -97,7 +97,7 @@ export const gitlabCreateMergeRequestTool: ToolConfig<
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId))
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/merge_requests`
|
||||
},
|
||||
method: 'POST',
|
||||
|
||||
@@ -49,7 +49,7 @@ export const gitlabCreateMergeRequestNoteTool: ToolConfig<
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId))
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/merge_requests/${params.mergeRequestIid}/notes`
|
||||
},
|
||||
method: 'POST',
|
||||
|
||||
@@ -47,7 +47,7 @@ export const gitlabCreatePipelineTool: ToolConfig<
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId))
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/pipeline`
|
||||
},
|
||||
method: 'POST',
|
||||
|
||||
@@ -38,7 +38,7 @@ export const gitlabDeleteIssueTool: ToolConfig<GitLabDeleteIssueParams, GitLabDe
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId))
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/issues/${params.issueIid}`
|
||||
},
|
||||
method: 'DELETE',
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
import type { GitLabGetFileParams, GitLabGetFileResponse } from '@/tools/gitlab/types'
|
||||
import { getGitLabApiBase } from '@/tools/gitlab/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const gitlabGetFileTool: ToolConfig<GitLabGetFileParams, GitLabGetFileResponse> = {
|
||||
id: 'gitlab_get_file',
|
||||
name: 'GitLab Get File',
|
||||
description: 'Get the contents of a file from a GitLab project repository',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'GitLab Personal Access Token',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Self-managed GitLab host (e.g. gitlab.example.com). Defaults to gitlab.com.',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or URL-encoded path',
|
||||
},
|
||||
filePath: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Path to the file in the repository',
|
||||
},
|
||||
ref: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Branch, tag, or commit SHA',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
const encodedPath = encodeURIComponent(String(params.filePath))
|
||||
const ref = encodeURIComponent(String(params.ref))
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/repository/files/${encodedPath}?ref=${ref}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'PRIVATE-TOKEN': params.accessToken,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return {
|
||||
success: false,
|
||||
error: `GitLab API error: ${response.status} ${errorText}`,
|
||||
output: {},
|
||||
}
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
const decoded = Buffer.from(data.content ?? '', 'base64').toString('utf-8')
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
filePath: data.file_path ?? null,
|
||||
fileName: data.file_name ?? null,
|
||||
size: data.size ?? null,
|
||||
ref: data.ref ?? null,
|
||||
blobId: data.blob_id ?? null,
|
||||
lastCommitId: data.last_commit_id ?? null,
|
||||
content: decoded,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
filePath: {
|
||||
type: 'string',
|
||||
description: 'The file path',
|
||||
},
|
||||
fileName: {
|
||||
type: 'string',
|
||||
description: 'The file name',
|
||||
},
|
||||
size: {
|
||||
type: 'number',
|
||||
description: 'The file size in bytes',
|
||||
},
|
||||
ref: {
|
||||
type: 'string',
|
||||
description: 'The branch, tag, or commit SHA',
|
||||
},
|
||||
blobId: {
|
||||
type: 'string',
|
||||
description: 'The blob ID',
|
||||
},
|
||||
lastCommitId: {
|
||||
type: 'string',
|
||||
description: 'The last commit ID that modified the file',
|
||||
},
|
||||
content: {
|
||||
type: 'string',
|
||||
description: 'The decoded file content',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -37,7 +37,7 @@ export const gitlabGetIssueTool: ToolConfig<GitLabGetIssueParams, GitLabGetIssue
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId))
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/issues/${params.issueIid}`
|
||||
},
|
||||
method: 'GET',
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import type { GitLabGetJobLogParams, GitLabGetJobLogResponse } from '@/tools/gitlab/types'
|
||||
import { getGitLabApiBase } from '@/tools/gitlab/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const gitlabGetJobLogTool: ToolConfig<GitLabGetJobLogParams, GitLabGetJobLogResponse> = {
|
||||
id: 'gitlab_get_job_log',
|
||||
name: 'GitLab Get Job Log',
|
||||
description: 'Get the log (trace) of a GitLab job',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'GitLab Personal Access Token',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Self-managed GitLab host (e.g. gitlab.example.com). Defaults to gitlab.com.',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or URL-encoded path',
|
||||
},
|
||||
jobId: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Job ID',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/jobs/${params.jobId}/trace`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'PRIVATE-TOKEN': params.accessToken,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return {
|
||||
success: false,
|
||||
error: `GitLab API error: ${response.status} ${errorText}`,
|
||||
output: {},
|
||||
}
|
||||
}
|
||||
|
||||
const log = await response.text()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
log,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
log: {
|
||||
type: 'string',
|
||||
description: 'The job log (trace) output',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -43,7 +43,7 @@ export const gitlabGetMergeRequestTool: ToolConfig<
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId))
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/merge_requests/${params.mergeRequestIid}`
|
||||
},
|
||||
method: 'GET',
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
import type {
|
||||
GitLabGetMergeRequestChangesParams,
|
||||
GitLabGetMergeRequestChangesResponse,
|
||||
} from '@/tools/gitlab/types'
|
||||
import { getGitLabApiBase } from '@/tools/gitlab/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const gitlabGetMergeRequestChangesTool: ToolConfig<
|
||||
GitLabGetMergeRequestChangesParams,
|
||||
GitLabGetMergeRequestChangesResponse
|
||||
> = {
|
||||
id: 'gitlab_get_merge_request_changes',
|
||||
name: 'GitLab Get Merge Request Changes',
|
||||
description: 'Get the file changes (diffs) of a GitLab merge request',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'GitLab Personal Access Token',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Self-managed GitLab host (e.g. gitlab.example.com). Defaults to gitlab.com.',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or URL-encoded path',
|
||||
},
|
||||
mergeRequestIid: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Merge request internal ID (IID)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
/**
|
||||
* Uses the `/diffs` endpoint (the `/changes` endpoint was deprecated in
|
||||
* GitLab 15.7 and removed in 18.0). `/diffs` returns the diff array directly
|
||||
* and is paginated; we request the max page size (100) to return the changes
|
||||
* in a single call, which covers the vast majority of merge requests.
|
||||
*/
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/merge_requests/${params.mergeRequestIid}/diffs?per_page=100`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'PRIVATE-TOKEN': params.accessToken,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response, params) => {
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return {
|
||||
success: false,
|
||||
error: `GitLab API error: ${response.status} ${errorText}`,
|
||||
output: {},
|
||||
}
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
const changes = Array.isArray(data) ? data : []
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
mergeRequestIid: params?.mergeRequestIid ?? null,
|
||||
changes,
|
||||
changesCount: changes.length,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
mergeRequestIid: {
|
||||
type: 'number',
|
||||
description: 'The merge request internal ID (IID)',
|
||||
},
|
||||
changes: {
|
||||
type: 'array',
|
||||
description: 'List of file changes (diffs)',
|
||||
},
|
||||
changesCount: {
|
||||
type: 'number',
|
||||
description: 'Number of changed files returned',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -38,7 +38,7 @@ export const gitlabGetPipelineTool: ToolConfig<GitLabGetPipelineParams, GitLabGe
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId))
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/pipelines/${params.pipelineId}`
|
||||
},
|
||||
method: 'GET',
|
||||
|
||||
@@ -31,7 +31,7 @@ export const gitlabGetProjectTool: ToolConfig<GitLabGetProjectParams, GitLabGetP
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId))
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}`
|
||||
},
|
||||
method: 'GET',
|
||||
|
||||
@@ -1,20 +1,32 @@
|
||||
import { gitlabApproveMergeRequestTool } from '@/tools/gitlab/approve_merge_request'
|
||||
import { gitlabCancelPipelineTool } from '@/tools/gitlab/cancel_pipeline'
|
||||
import { gitlabCreateBranchTool } from '@/tools/gitlab/create_branch'
|
||||
import { gitlabCreateFileTool } from '@/tools/gitlab/create_file'
|
||||
import { gitlabCreateIssueTool } from '@/tools/gitlab/create_issue'
|
||||
import { gitlabCreateIssueNoteTool } from '@/tools/gitlab/create_issue_note'
|
||||
import { gitlabCreateMergeRequestTool } from '@/tools/gitlab/create_merge_request'
|
||||
import { gitlabCreateMergeRequestNoteTool } from '@/tools/gitlab/create_merge_request_note'
|
||||
import { gitlabCreatePipelineTool } from '@/tools/gitlab/create_pipeline'
|
||||
import { gitlabDeleteIssueTool } from '@/tools/gitlab/delete_issue'
|
||||
import { gitlabGetFileTool } from '@/tools/gitlab/get_file'
|
||||
import { gitlabGetIssueTool } from '@/tools/gitlab/get_issue'
|
||||
import { gitlabGetJobLogTool } from '@/tools/gitlab/get_job_log'
|
||||
import { gitlabGetMergeRequestTool } from '@/tools/gitlab/get_merge_request'
|
||||
import { gitlabGetMergeRequestChangesTool } from '@/tools/gitlab/get_merge_request_changes'
|
||||
import { gitlabGetPipelineTool } from '@/tools/gitlab/get_pipeline'
|
||||
import { gitlabGetProjectTool } from '@/tools/gitlab/get_project'
|
||||
import { gitlabListBranchesTool } from '@/tools/gitlab/list_branches'
|
||||
import { gitlabListCommitsTool } from '@/tools/gitlab/list_commits'
|
||||
import { gitlabListIssuesTool } from '@/tools/gitlab/list_issues'
|
||||
import { gitlabListMergeRequestsTool } from '@/tools/gitlab/list_merge_requests'
|
||||
import { gitlabListPipelineJobsTool } from '@/tools/gitlab/list_pipeline_jobs'
|
||||
import { gitlabListPipelinesTool } from '@/tools/gitlab/list_pipelines'
|
||||
import { gitlabListProjectsTool } from '@/tools/gitlab/list_projects'
|
||||
import { gitlabListRepositoryTreeTool } from '@/tools/gitlab/list_repository_tree'
|
||||
import { gitlabMergeMergeRequestTool } from '@/tools/gitlab/merge_merge_request'
|
||||
import { gitlabPlayJobTool } from '@/tools/gitlab/play_job'
|
||||
import { gitlabRetryPipelineTool } from '@/tools/gitlab/retry_pipeline'
|
||||
import { gitlabUpdateFileTool } from '@/tools/gitlab/update_file'
|
||||
import { gitlabUpdateIssueTool } from '@/tools/gitlab/update_issue'
|
||||
import { gitlabUpdateMergeRequestTool } from '@/tools/gitlab/update_merge_request'
|
||||
|
||||
@@ -36,10 +48,26 @@ export {
|
||||
gitlabUpdateMergeRequestTool,
|
||||
gitlabMergeMergeRequestTool,
|
||||
gitlabCreateMergeRequestNoteTool,
|
||||
gitlabGetMergeRequestChangesTool,
|
||||
gitlabApproveMergeRequestTool,
|
||||
// Pipelines
|
||||
gitlabListPipelinesTool,
|
||||
gitlabGetPipelineTool,
|
||||
gitlabCreatePipelineTool,
|
||||
gitlabRetryPipelineTool,
|
||||
gitlabCancelPipelineTool,
|
||||
// Jobs
|
||||
gitlabListPipelineJobsTool,
|
||||
gitlabGetJobLogTool,
|
||||
gitlabPlayJobTool,
|
||||
// Repository Files & Tree
|
||||
gitlabListRepositoryTreeTool,
|
||||
gitlabGetFileTool,
|
||||
gitlabCreateFileTool,
|
||||
gitlabUpdateFileTool,
|
||||
// Branches
|
||||
gitlabListBranchesTool,
|
||||
gitlabCreateBranchTool,
|
||||
// Commits
|
||||
gitlabListCommitsTool,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
import type { GitLabListBranchesParams, GitLabListBranchesResponse } from '@/tools/gitlab/types'
|
||||
import { getGitLabApiBase } from '@/tools/gitlab/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const gitlabListBranchesTool: ToolConfig<
|
||||
GitLabListBranchesParams,
|
||||
GitLabListBranchesResponse
|
||||
> = {
|
||||
id: 'gitlab_list_branches',
|
||||
name: 'GitLab List Branches',
|
||||
description: 'List branches in a GitLab project repository',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'GitLab Personal Access Token',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Self-managed GitLab host (e.g. gitlab.example.com). Defaults to gitlab.com.',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or URL-encoded path',
|
||||
},
|
||||
search: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter branches by name',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page (default 20, max 100)',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.search) queryParams.append('search', params.search)
|
||||
if (params.perPage) queryParams.append('per_page', String(params.perPage))
|
||||
if (params.page) queryParams.append('page', String(params.page))
|
||||
|
||||
const query = queryParams.toString()
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/repository/branches${query ? `?${query}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'PRIVATE-TOKEN': params.accessToken,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return {
|
||||
success: false,
|
||||
error: `GitLab API error: ${response.status} ${errorText}`,
|
||||
output: {},
|
||||
}
|
||||
}
|
||||
|
||||
const branches = await response.json()
|
||||
const total = response.headers.get('x-total')
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
branches: branches ?? [],
|
||||
total: total ? Number.parseInt(total, 10) : (branches?.length ?? 0),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
branches: {
|
||||
type: 'array',
|
||||
description: 'List of branches',
|
||||
},
|
||||
total: {
|
||||
type: 'number',
|
||||
description: 'Total number of branches',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
import type { GitLabListCommitsParams, GitLabListCommitsResponse } from '@/tools/gitlab/types'
|
||||
import { getGitLabApiBase } from '@/tools/gitlab/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const gitlabListCommitsTool: ToolConfig<GitLabListCommitsParams, GitLabListCommitsResponse> =
|
||||
{
|
||||
id: 'gitlab_list_commits',
|
||||
name: 'GitLab List Commits',
|
||||
description: 'List commits in a GitLab project repository',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'GitLab Personal Access Token',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Self-managed GitLab host (e.g. gitlab.example.com). Defaults to gitlab.com.',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or URL-encoded path',
|
||||
},
|
||||
refName: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Branch, tag, or revision range to list commits from',
|
||||
},
|
||||
since: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Only commits after this ISO 8601 date',
|
||||
},
|
||||
until: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Only commits before this ISO 8601 date',
|
||||
},
|
||||
path: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Only commits affecting this file path',
|
||||
},
|
||||
author: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter commits by author',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page (default 20, max 100)',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.refName) queryParams.append('ref_name', params.refName)
|
||||
if (params.since) queryParams.append('since', params.since)
|
||||
if (params.until) queryParams.append('until', params.until)
|
||||
if (params.path) queryParams.append('path', params.path)
|
||||
if (params.author) queryParams.append('author', params.author)
|
||||
if (params.perPage) queryParams.append('per_page', String(params.perPage))
|
||||
if (params.page) queryParams.append('page', String(params.page))
|
||||
|
||||
const query = queryParams.toString()
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/repository/commits${query ? `?${query}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'PRIVATE-TOKEN': params.accessToken,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return {
|
||||
success: false,
|
||||
error: `GitLab API error: ${response.status} ${errorText}`,
|
||||
output: {},
|
||||
}
|
||||
}
|
||||
|
||||
const commits = await response.json()
|
||||
const total = response.headers.get('x-total')
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
commits: commits ?? [],
|
||||
total: total ? Number.parseInt(total, 10) : (commits?.length ?? 0),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
commits: {
|
||||
type: 'array',
|
||||
description: 'List of commits',
|
||||
},
|
||||
total: {
|
||||
type: 'number',
|
||||
description: 'Total number of commits',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -85,7 +85,7 @@ export const gitlabListIssuesTool: ToolConfig<GitLabListIssuesParams, GitLabList
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId))
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.state) queryParams.append('state', params.state)
|
||||
|
||||
@@ -85,7 +85,7 @@ export const gitlabListMergeRequestsTool: ToolConfig<
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId))
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.state) queryParams.append('state', params.state)
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
import type {
|
||||
GitLabListPipelineJobsParams,
|
||||
GitLabListPipelineJobsResponse,
|
||||
} from '@/tools/gitlab/types'
|
||||
import { getGitLabApiBase } from '@/tools/gitlab/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const gitlabListPipelineJobsTool: ToolConfig<
|
||||
GitLabListPipelineJobsParams,
|
||||
GitLabListPipelineJobsResponse
|
||||
> = {
|
||||
id: 'gitlab_list_pipeline_jobs',
|
||||
name: 'GitLab List Pipeline Jobs',
|
||||
description: 'List jobs for a GitLab pipeline',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'GitLab Personal Access Token',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Self-managed GitLab host (e.g. gitlab.example.com). Defaults to gitlab.com.',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or URL-encoded path',
|
||||
},
|
||||
pipelineId: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Pipeline ID',
|
||||
},
|
||||
scope: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Filter jobs by scope (e.g. created, running, success, failed)',
|
||||
},
|
||||
includeRetried: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Whether to include retried jobs',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page (default 20, max 100)',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.scope) queryParams.append('scope', params.scope)
|
||||
if (params.includeRetried) queryParams.append('include_retried', 'true')
|
||||
if (params.perPage) queryParams.append('per_page', String(params.perPage))
|
||||
if (params.page) queryParams.append('page', String(params.page))
|
||||
|
||||
const query = queryParams.toString()
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/pipelines/${params.pipelineId}/jobs${query ? `?${query}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'PRIVATE-TOKEN': params.accessToken,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return {
|
||||
success: false,
|
||||
error: `GitLab API error: ${response.status} ${errorText}`,
|
||||
output: {},
|
||||
}
|
||||
}
|
||||
|
||||
const jobs = await response.json()
|
||||
const total = response.headers.get('x-total')
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
jobs: jobs ?? [],
|
||||
total: total ? Number.parseInt(total, 10) : (jobs?.length ?? 0),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
jobs: {
|
||||
type: 'array',
|
||||
description: 'List of pipeline jobs',
|
||||
},
|
||||
total: {
|
||||
type: 'number',
|
||||
description: 'Total number of jobs',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -71,7 +71,7 @@ export const gitlabListPipelinesTool: ToolConfig<
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId))
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.ref) queryParams.append('ref', params.ref)
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
import type {
|
||||
GitLabListRepositoryTreeParams,
|
||||
GitLabListRepositoryTreeResponse,
|
||||
} from '@/tools/gitlab/types'
|
||||
import { getGitLabApiBase } from '@/tools/gitlab/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const gitlabListRepositoryTreeTool: ToolConfig<
|
||||
GitLabListRepositoryTreeParams,
|
||||
GitLabListRepositoryTreeResponse
|
||||
> = {
|
||||
id: 'gitlab_list_repository_tree',
|
||||
name: 'GitLab List Repository Tree',
|
||||
description: 'List files and directories in a GitLab project repository',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'GitLab Personal Access Token',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Self-managed GitLab host (e.g. gitlab.example.com). Defaults to gitlab.com.',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or URL-encoded path',
|
||||
},
|
||||
path: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Path inside the repository to list',
|
||||
},
|
||||
ref: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Branch, tag, or commit SHA to list from',
|
||||
},
|
||||
recursive: {
|
||||
type: 'boolean',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Whether to list files recursively',
|
||||
},
|
||||
perPage: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Number of results per page (default 20, max 100)',
|
||||
},
|
||||
page: {
|
||||
type: 'number',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Page number for pagination',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
const queryParams = new URLSearchParams()
|
||||
|
||||
if (params.path) queryParams.append('path', params.path)
|
||||
if (params.ref) queryParams.append('ref', params.ref)
|
||||
if (params.recursive) queryParams.append('recursive', 'true')
|
||||
if (params.perPage) queryParams.append('per_page', String(params.perPage))
|
||||
if (params.page) queryParams.append('page', String(params.page))
|
||||
|
||||
const query = queryParams.toString()
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/repository/tree${query ? `?${query}` : ''}`
|
||||
},
|
||||
method: 'GET',
|
||||
headers: (params) => ({
|
||||
'PRIVATE-TOKEN': params.accessToken,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return {
|
||||
success: false,
|
||||
error: `GitLab API error: ${response.status} ${errorText}`,
|
||||
output: {},
|
||||
}
|
||||
}
|
||||
|
||||
const tree = await response.json()
|
||||
const total = response.headers.get('x-total')
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
tree: tree ?? [],
|
||||
total: total ? Number.parseInt(total, 10) : (tree?.length ?? 0),
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
tree: {
|
||||
type: 'array',
|
||||
description: 'List of repository tree entries',
|
||||
},
|
||||
total: {
|
||||
type: 'number',
|
||||
description: 'Total number of tree entries',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -73,7 +73,7 @@ export const gitlabMergeMergeRequestTool: ToolConfig<
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId))
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/merge_requests/${params.mergeRequestIid}/merge`
|
||||
},
|
||||
method: 'PUT',
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
import type { GitLabPlayJobParams, GitLabPlayJobResponse } from '@/tools/gitlab/types'
|
||||
import { getGitLabApiBase } from '@/tools/gitlab/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const gitlabPlayJobTool: ToolConfig<GitLabPlayJobParams, GitLabPlayJobResponse> = {
|
||||
id: 'gitlab_play_job',
|
||||
name: 'GitLab Play Job',
|
||||
description: 'Trigger (play) a manual GitLab job',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'GitLab Personal Access Token',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Self-managed GitLab host (e.g. gitlab.example.com). Defaults to gitlab.com.',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or URL-encoded path',
|
||||
},
|
||||
jobId: {
|
||||
type: 'number',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Job ID',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/jobs/${params.jobId}/play`
|
||||
},
|
||||
method: 'POST',
|
||||
headers: (params) => ({
|
||||
'PRIVATE-TOKEN': params.accessToken,
|
||||
}),
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return {
|
||||
success: false,
|
||||
error: `GitLab API error: ${response.status} ${errorText}`,
|
||||
output: {},
|
||||
}
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
id: data.id ?? null,
|
||||
name: data.name ?? null,
|
||||
status: data.status ?? null,
|
||||
webUrl: data.web_url ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
id: {
|
||||
type: 'number',
|
||||
description: 'The job ID',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
description: 'The job name',
|
||||
},
|
||||
status: {
|
||||
type: 'string',
|
||||
description: 'The job status',
|
||||
},
|
||||
webUrl: {
|
||||
type: 'string',
|
||||
description: 'The web URL of the job',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -40,7 +40,7 @@ export const gitlabRetryPipelineTool: ToolConfig<
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId))
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/pipelines/${params.pipelineId}/retry`
|
||||
},
|
||||
method: 'POST',
|
||||
|
||||
+207
-27
@@ -1,7 +1,5 @@
|
||||
import type { ToolResponse } from '@/tools/types'
|
||||
|
||||
// ===== Core Types =====
|
||||
|
||||
interface GitLabProject {
|
||||
id: number
|
||||
name: string
|
||||
@@ -124,6 +122,46 @@ interface GitLabPipeline {
|
||||
}
|
||||
}
|
||||
|
||||
interface GitLabTreeEntry {
|
||||
id: string
|
||||
name: string
|
||||
type: string
|
||||
path: string
|
||||
mode: string
|
||||
}
|
||||
|
||||
interface GitLabCommit {
|
||||
id: string
|
||||
short_id: string
|
||||
title: string
|
||||
message: string
|
||||
author_name: string
|
||||
authored_date: string
|
||||
created_at: string
|
||||
web_url: string
|
||||
}
|
||||
|
||||
interface GitLabJob {
|
||||
id: number
|
||||
name: string
|
||||
stage: string
|
||||
status: string
|
||||
started_at?: string | null
|
||||
finished_at?: string | null
|
||||
duration?: number | null
|
||||
web_url: string
|
||||
ref?: string
|
||||
}
|
||||
|
||||
interface GitLabMergeRequestChange {
|
||||
old_path: string
|
||||
new_path: string
|
||||
diff: string
|
||||
new_file: boolean
|
||||
deleted_file: boolean
|
||||
renamed_file: boolean
|
||||
}
|
||||
|
||||
interface GitLabBranch {
|
||||
name: string
|
||||
merged: boolean
|
||||
@@ -190,8 +228,6 @@ interface GitLabMilestone {
|
||||
web_url: string
|
||||
}
|
||||
|
||||
// ===== Common Parameters =====
|
||||
|
||||
interface GitLabBaseParams {
|
||||
accessToken: string
|
||||
/**
|
||||
@@ -201,8 +237,6 @@ interface GitLabBaseParams {
|
||||
host?: string
|
||||
}
|
||||
|
||||
// ===== Project Parameters =====
|
||||
|
||||
export interface GitLabListProjectsParams extends GitLabBaseParams {
|
||||
owned?: boolean
|
||||
membership?: boolean
|
||||
@@ -218,8 +252,6 @@ export interface GitLabGetProjectParams extends GitLabBaseParams {
|
||||
projectId: string | number
|
||||
}
|
||||
|
||||
// ===== Issue Parameters =====
|
||||
|
||||
export interface GitLabListIssuesParams extends GitLabBaseParams {
|
||||
projectId: string | number
|
||||
state?: 'opened' | 'closed' | 'all'
|
||||
@@ -267,8 +299,6 @@ export interface GitLabDeleteIssueParams extends GitLabBaseParams {
|
||||
issueIid: number
|
||||
}
|
||||
|
||||
// ===== Merge Request Parameters =====
|
||||
|
||||
export interface GitLabListMergeRequestsParams extends GitLabBaseParams {
|
||||
projectId: string | number
|
||||
state?: 'opened' | 'closed' | 'merged' | 'all'
|
||||
@@ -325,8 +355,6 @@ export interface GitLabMergeMergeRequestParams extends GitLabBaseParams {
|
||||
mergeWhenPipelineSucceeds?: boolean
|
||||
}
|
||||
|
||||
// ===== Pipeline Parameters =====
|
||||
|
||||
export interface GitLabListPipelinesParams extends GitLabBaseParams {
|
||||
projectId: string | number
|
||||
ref?: string
|
||||
@@ -369,9 +397,7 @@ export interface GitLabCancelPipelineParams extends GitLabBaseParams {
|
||||
pipelineId: number
|
||||
}
|
||||
|
||||
// ===== Branch Parameters =====
|
||||
|
||||
interface GitLabListBranchesParams extends GitLabBaseParams {
|
||||
export interface GitLabListBranchesParams extends GitLabBaseParams {
|
||||
projectId: string | number
|
||||
search?: string
|
||||
perPage?: number
|
||||
@@ -383,7 +409,7 @@ interface GitLabGetBranchParams extends GitLabBaseParams {
|
||||
branch: string
|
||||
}
|
||||
|
||||
interface GitLabCreateBranchParams extends GitLabBaseParams {
|
||||
export interface GitLabCreateBranchParams extends GitLabBaseParams {
|
||||
projectId: string | number
|
||||
branch: string
|
||||
ref: string
|
||||
@@ -394,7 +420,78 @@ interface GitLabDeleteBranchParams extends GitLabBaseParams {
|
||||
branch: string
|
||||
}
|
||||
|
||||
// ===== Note/Comment Parameters =====
|
||||
export interface GitLabListRepositoryTreeParams extends GitLabBaseParams {
|
||||
projectId: string | number
|
||||
path?: string
|
||||
ref?: string
|
||||
recursive?: boolean
|
||||
perPage?: number
|
||||
page?: number
|
||||
}
|
||||
|
||||
export interface GitLabGetFileParams extends GitLabBaseParams {
|
||||
projectId: string | number
|
||||
filePath: string
|
||||
ref: string
|
||||
}
|
||||
|
||||
export interface GitLabCreateFileParams extends GitLabBaseParams {
|
||||
projectId: string | number
|
||||
filePath: string
|
||||
branch: string
|
||||
content: string
|
||||
commitMessage: string
|
||||
}
|
||||
|
||||
export interface GitLabUpdateFileParams extends GitLabBaseParams {
|
||||
projectId: string | number
|
||||
filePath: string
|
||||
branch: string
|
||||
content: string
|
||||
commitMessage: string
|
||||
lastCommitId?: string
|
||||
}
|
||||
|
||||
export interface GitLabListCommitsParams extends GitLabBaseParams {
|
||||
projectId: string | number
|
||||
refName?: string
|
||||
since?: string
|
||||
until?: string
|
||||
path?: string
|
||||
author?: string
|
||||
perPage?: number
|
||||
page?: number
|
||||
}
|
||||
|
||||
export interface GitLabGetMergeRequestChangesParams extends GitLabBaseParams {
|
||||
projectId: string | number
|
||||
mergeRequestIid: number
|
||||
}
|
||||
|
||||
export interface GitLabApproveMergeRequestParams extends GitLabBaseParams {
|
||||
projectId: string | number
|
||||
mergeRequestIid: number
|
||||
sha?: string
|
||||
}
|
||||
|
||||
export interface GitLabListPipelineJobsParams extends GitLabBaseParams {
|
||||
projectId: string | number
|
||||
pipelineId: number
|
||||
scope?: string
|
||||
includeRetried?: boolean
|
||||
perPage?: number
|
||||
page?: number
|
||||
}
|
||||
|
||||
export interface GitLabGetJobLogParams extends GitLabBaseParams {
|
||||
projectId: string | number
|
||||
jobId: number
|
||||
}
|
||||
|
||||
export interface GitLabPlayJobParams extends GitLabBaseParams {
|
||||
projectId: string | number
|
||||
jobId: number
|
||||
}
|
||||
|
||||
interface GitLabListIssueNotesParams extends GitLabBaseParams {
|
||||
projectId: string | number
|
||||
@@ -426,8 +523,6 @@ export interface GitLabCreateMergeRequestNoteParams extends GitLabBaseParams {
|
||||
body: string
|
||||
}
|
||||
|
||||
// ===== Label Parameters =====
|
||||
|
||||
interface GitLabListLabelsParams extends GitLabBaseParams {
|
||||
projectId: string | number
|
||||
search?: string
|
||||
@@ -442,8 +537,6 @@ interface GitLabCreateLabelParams extends GitLabBaseParams {
|
||||
description?: string
|
||||
}
|
||||
|
||||
// ===== User Parameters =====
|
||||
|
||||
interface GitLabGetCurrentUserParams extends GitLabBaseParams {}
|
||||
|
||||
interface GitLabListUsersParams extends GitLabBaseParams {
|
||||
@@ -452,8 +545,6 @@ interface GitLabListUsersParams extends GitLabBaseParams {
|
||||
page?: number
|
||||
}
|
||||
|
||||
// ===== Response Types =====
|
||||
|
||||
export interface GitLabListProjectsResponse extends ToolResponse {
|
||||
output: {
|
||||
projects?: GitLabProject[]
|
||||
@@ -560,7 +651,7 @@ export interface GitLabCancelPipelineResponse extends ToolResponse {
|
||||
}
|
||||
}
|
||||
|
||||
interface GitLabListBranchesResponse extends ToolResponse {
|
||||
export interface GitLabListBranchesResponse extends ToolResponse {
|
||||
output: {
|
||||
branches?: GitLabBranch[]
|
||||
total?: number
|
||||
@@ -573,9 +664,12 @@ interface GitLabGetBranchResponse extends ToolResponse {
|
||||
}
|
||||
}
|
||||
|
||||
interface GitLabCreateBranchResponse extends ToolResponse {
|
||||
export interface GitLabCreateBranchResponse extends ToolResponse {
|
||||
output: {
|
||||
branch?: GitLabBranch
|
||||
name?: string | null
|
||||
webUrl?: string | null
|
||||
protected?: boolean | null
|
||||
commit?: GitLabBranch['commit'] | null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -624,7 +718,83 @@ interface GitLabListUsersResponse extends ToolResponse {
|
||||
}
|
||||
}
|
||||
|
||||
// ===== Union Response Type =====
|
||||
export interface GitLabListRepositoryTreeResponse extends ToolResponse {
|
||||
output: {
|
||||
tree?: GitLabTreeEntry[]
|
||||
total?: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface GitLabGetFileResponse extends ToolResponse {
|
||||
output: {
|
||||
filePath?: string | null
|
||||
fileName?: string | null
|
||||
size?: number | null
|
||||
ref?: string | null
|
||||
blobId?: string | null
|
||||
lastCommitId?: string | null
|
||||
content?: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface GitLabCreateFileResponse extends ToolResponse {
|
||||
output: {
|
||||
filePath?: string | null
|
||||
branch?: string | null
|
||||
}
|
||||
}
|
||||
|
||||
export interface GitLabUpdateFileResponse extends ToolResponse {
|
||||
output: {
|
||||
filePath?: string | null
|
||||
branch?: string | null
|
||||
}
|
||||
}
|
||||
|
||||
export interface GitLabListCommitsResponse extends ToolResponse {
|
||||
output: {
|
||||
commits?: GitLabCommit[]
|
||||
total?: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface GitLabGetMergeRequestChangesResponse extends ToolResponse {
|
||||
output: {
|
||||
mergeRequestIid?: number | null
|
||||
changes?: GitLabMergeRequestChange[]
|
||||
changesCount?: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface GitLabApproveMergeRequestResponse extends ToolResponse {
|
||||
output: {
|
||||
approvalsRequired?: number | null
|
||||
approvalsLeft?: number | null
|
||||
approvedBy?: unknown[]
|
||||
}
|
||||
}
|
||||
|
||||
export interface GitLabListPipelineJobsResponse extends ToolResponse {
|
||||
output: {
|
||||
jobs?: GitLabJob[]
|
||||
total?: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface GitLabGetJobLogResponse extends ToolResponse {
|
||||
output: {
|
||||
log?: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface GitLabPlayJobResponse extends ToolResponse {
|
||||
output: {
|
||||
id?: number | null
|
||||
name?: string | null
|
||||
status?: string | null
|
||||
webUrl?: string | null
|
||||
}
|
||||
}
|
||||
|
||||
export type GitLabResponse =
|
||||
| GitLabListProjectsResponse
|
||||
@@ -654,3 +824,13 @@ export type GitLabResponse =
|
||||
| GitLabCreateLabelResponse
|
||||
| GitLabGetCurrentUserResponse
|
||||
| GitLabListUsersResponse
|
||||
| GitLabListRepositoryTreeResponse
|
||||
| GitLabGetFileResponse
|
||||
| GitLabCreateFileResponse
|
||||
| GitLabUpdateFileResponse
|
||||
| GitLabListCommitsResponse
|
||||
| GitLabGetMergeRequestChangesResponse
|
||||
| GitLabApproveMergeRequestResponse
|
||||
| GitLabListPipelineJobsResponse
|
||||
| GitLabGetJobLogResponse
|
||||
| GitLabPlayJobResponse
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
import type { GitLabUpdateFileParams, GitLabUpdateFileResponse } from '@/tools/gitlab/types'
|
||||
import { getGitLabApiBase } from '@/tools/gitlab/utils'
|
||||
import type { ToolConfig } from '@/tools/types'
|
||||
|
||||
export const gitlabUpdateFileTool: ToolConfig<GitLabUpdateFileParams, GitLabUpdateFileResponse> = {
|
||||
id: 'gitlab_update_file',
|
||||
name: 'GitLab Update File',
|
||||
description: 'Update an existing file in a GitLab project repository',
|
||||
version: '1.0.0',
|
||||
|
||||
params: {
|
||||
accessToken: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-only',
|
||||
description: 'GitLab Personal Access Token',
|
||||
},
|
||||
host: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-only',
|
||||
description: 'Self-managed GitLab host (e.g. gitlab.example.com). Defaults to gitlab.com.',
|
||||
},
|
||||
projectId: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Project ID or URL-encoded path',
|
||||
},
|
||||
filePath: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Path to the file in the repository',
|
||||
},
|
||||
branch: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Branch to commit the update to',
|
||||
},
|
||||
content: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'New file content',
|
||||
},
|
||||
commitMessage: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Commit message',
|
||||
},
|
||||
lastCommitId: {
|
||||
type: 'string',
|
||||
required: false,
|
||||
visibility: 'user-or-llm',
|
||||
description: 'Last known commit ID for the file (optimistic locking)',
|
||||
},
|
||||
},
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
const encodedPath = encodeURIComponent(String(params.filePath))
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/repository/files/${encodedPath}`
|
||||
},
|
||||
method: 'PUT',
|
||||
headers: (params) => ({
|
||||
'Content-Type': 'application/json',
|
||||
'PRIVATE-TOKEN': params.accessToken,
|
||||
}),
|
||||
body: (params) => {
|
||||
const body: Record<string, unknown> = {
|
||||
branch: params.branch,
|
||||
content: params.content,
|
||||
commit_message: params.commitMessage,
|
||||
encoding: 'text',
|
||||
}
|
||||
|
||||
if (params.lastCommitId) body.last_commit_id = params.lastCommitId
|
||||
|
||||
return body
|
||||
},
|
||||
},
|
||||
|
||||
transformResponse: async (response) => {
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text()
|
||||
return {
|
||||
success: false,
|
||||
error: `GitLab API error: ${response.status} ${errorText}`,
|
||||
output: {},
|
||||
}
|
||||
}
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
filePath: data.file_path ?? null,
|
||||
branch: data.branch ?? null,
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
filePath: {
|
||||
type: 'string',
|
||||
description: 'The updated file path',
|
||||
},
|
||||
branch: {
|
||||
type: 'string',
|
||||
description: 'The branch the update was committed to',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -86,7 +86,7 @@ export const gitlabUpdateIssueTool: ToolConfig<GitLabUpdateIssueParams, GitLabUp
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId))
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/issues/${params.issueIid}`
|
||||
},
|
||||
method: 'PUT',
|
||||
|
||||
@@ -103,7 +103,7 @@ export const gitlabUpdateMergeRequestTool: ToolConfig<
|
||||
|
||||
request: {
|
||||
url: (params) => {
|
||||
const encodedId = encodeURIComponent(String(params.projectId))
|
||||
const encodedId = encodeURIComponent(String(params.projectId).trim())
|
||||
return `${getGitLabApiBase(params.host)}/projects/${encodedId}/merge_requests/${params.mergeRequestIid}`
|
||||
},
|
||||
method: 'PUT',
|
||||
|
||||
+42
-18
@@ -1082,23 +1082,35 @@ import {
|
||||
githubUpdateReleaseV2Tool,
|
||||
} from '@/tools/github'
|
||||
import {
|
||||
gitlabApproveMergeRequestTool,
|
||||
gitlabCancelPipelineTool,
|
||||
gitlabCreateBranchTool,
|
||||
gitlabCreateFileTool,
|
||||
gitlabCreateIssueNoteTool,
|
||||
gitlabCreateIssueTool,
|
||||
gitlabCreateMergeRequestNoteTool,
|
||||
gitlabCreateMergeRequestTool,
|
||||
gitlabCreatePipelineTool,
|
||||
gitlabDeleteIssueTool,
|
||||
gitlabGetFileTool,
|
||||
gitlabGetIssueTool,
|
||||
gitlabGetJobLogTool,
|
||||
gitlabGetMergeRequestChangesTool,
|
||||
gitlabGetMergeRequestTool,
|
||||
gitlabGetPipelineTool,
|
||||
gitlabGetProjectTool,
|
||||
gitlabListBranchesTool,
|
||||
gitlabListCommitsTool,
|
||||
gitlabListIssuesTool,
|
||||
gitlabListMergeRequestsTool,
|
||||
gitlabListPipelineJobsTool,
|
||||
gitlabListPipelinesTool,
|
||||
gitlabListProjectsTool,
|
||||
gitlabListRepositoryTreeTool,
|
||||
gitlabMergeMergeRequestTool,
|
||||
gitlabPlayJobTool,
|
||||
gitlabRetryPipelineTool,
|
||||
gitlabUpdateFileTool,
|
||||
gitlabUpdateIssueTool,
|
||||
gitlabUpdateMergeRequestTool,
|
||||
} from '@/tools/gitlab'
|
||||
@@ -5477,25 +5489,37 @@ export const tools: Record<string, ToolConfig> = {
|
||||
github_check_star_v2: githubCheckStarV2Tool,
|
||||
github_list_stargazers: githubListStargazersTool,
|
||||
github_list_stargazers_v2: githubListStargazersV2Tool,
|
||||
gitlab_list_projects: gitlabListProjectsTool,
|
||||
gitlab_get_project: gitlabGetProjectTool,
|
||||
gitlab_list_issues: gitlabListIssuesTool,
|
||||
gitlab_get_issue: gitlabGetIssueTool,
|
||||
gitlab_create_issue: gitlabCreateIssueTool,
|
||||
gitlab_update_issue: gitlabUpdateIssueTool,
|
||||
gitlab_delete_issue: gitlabDeleteIssueTool,
|
||||
gitlab_create_issue_note: gitlabCreateIssueNoteTool,
|
||||
gitlab_list_merge_requests: gitlabListMergeRequestsTool,
|
||||
gitlab_get_merge_request: gitlabGetMergeRequestTool,
|
||||
gitlab_create_merge_request: gitlabCreateMergeRequestTool,
|
||||
gitlab_update_merge_request: gitlabUpdateMergeRequestTool,
|
||||
gitlab_merge_merge_request: gitlabMergeMergeRequestTool,
|
||||
gitlab_create_merge_request_note: gitlabCreateMergeRequestNoteTool,
|
||||
gitlab_list_pipelines: gitlabListPipelinesTool,
|
||||
gitlab_get_pipeline: gitlabGetPipelineTool,
|
||||
gitlab_create_pipeline: gitlabCreatePipelineTool,
|
||||
gitlab_retry_pipeline: gitlabRetryPipelineTool,
|
||||
gitlab_approve_merge_request: gitlabApproveMergeRequestTool,
|
||||
gitlab_cancel_pipeline: gitlabCancelPipelineTool,
|
||||
gitlab_create_branch: gitlabCreateBranchTool,
|
||||
gitlab_create_file: gitlabCreateFileTool,
|
||||
gitlab_create_issue: gitlabCreateIssueTool,
|
||||
gitlab_create_issue_note: gitlabCreateIssueNoteTool,
|
||||
gitlab_create_merge_request: gitlabCreateMergeRequestTool,
|
||||
gitlab_create_merge_request_note: gitlabCreateMergeRequestNoteTool,
|
||||
gitlab_create_pipeline: gitlabCreatePipelineTool,
|
||||
gitlab_delete_issue: gitlabDeleteIssueTool,
|
||||
gitlab_get_file: gitlabGetFileTool,
|
||||
gitlab_get_issue: gitlabGetIssueTool,
|
||||
gitlab_get_job_log: gitlabGetJobLogTool,
|
||||
gitlab_get_merge_request: gitlabGetMergeRequestTool,
|
||||
gitlab_get_merge_request_changes: gitlabGetMergeRequestChangesTool,
|
||||
gitlab_get_pipeline: gitlabGetPipelineTool,
|
||||
gitlab_get_project: gitlabGetProjectTool,
|
||||
gitlab_list_branches: gitlabListBranchesTool,
|
||||
gitlab_list_commits: gitlabListCommitsTool,
|
||||
gitlab_list_issues: gitlabListIssuesTool,
|
||||
gitlab_list_merge_requests: gitlabListMergeRequestsTool,
|
||||
gitlab_list_pipeline_jobs: gitlabListPipelineJobsTool,
|
||||
gitlab_list_pipelines: gitlabListPipelinesTool,
|
||||
gitlab_list_projects: gitlabListProjectsTool,
|
||||
gitlab_list_repository_tree: gitlabListRepositoryTreeTool,
|
||||
gitlab_merge_merge_request: gitlabMergeMergeRequestTool,
|
||||
gitlab_play_job: gitlabPlayJobTool,
|
||||
gitlab_retry_pipeline: gitlabRetryPipelineTool,
|
||||
gitlab_update_file: gitlabUpdateFileTool,
|
||||
gitlab_update_issue: gitlabUpdateIssueTool,
|
||||
gitlab_update_merge_request: gitlabUpdateMergeRequestTool,
|
||||
grain_list_recordings: grainListRecordingsTool,
|
||||
grain_get_recording: grainGetRecordingTool,
|
||||
grain_get_transcript: grainGetTranscriptTool,
|
||||
|
||||
Reference in New Issue
Block a user