chat-adapter-gitlab
v0.1.0
Published
GitLab adapter for Vercel Chat SDK — supports gitlab.com and self-hosted instances
Downloads
15
Maintainers
Readme
chat-adapter-gitlab
GitLab adapter for the Vercel Chat SDK. Maps GitLab issues and merge requests to Chat SDK threads using webhooks for inbound events and the GitLab REST API for outbound operations.
Supports both gitlab.com and self-hosted/enterprise GitLab instances.
Install
pnpm add chat-adapter-gitlab chat @chat-adapter/sharedQuick Start
import { Chat } from "chat";
import { createGitLabAdapter } from "chat-adapter-gitlab";
const adapter = createGitLabAdapter({
token: process.env.GITLAB_TOKEN,
webhookSecret: process.env.GITLAB_WEBHOOK_SECRET,
// For self-hosted instances:
// baseUrl: "https://gitlab.example.com",
});
const chat = new Chat({
adapter,
async onMessage({ message, thread, reply }) {
await reply(`Thanks for your comment, ${message.author.userName}!`);
},
});
// Mount the webhook handler on your HTTP server
// POST /api/webhooks/gitlab → chat.handleWebhook(request)Configuration
Environment Variables
| Variable | Required | Description |
|---|---|---|
| GITLAB_TOKEN | Yes | Access token with api scope |
| GITLAB_WEBHOOK_SECRET | Yes | Webhook verification token |
| GITLAB_BASE_URL | No | Instance URL (default: https://gitlab.com) |
| GITLAB_BOT_USERNAME | No | Bot username (auto-detected if omitted) |
| GITLAB_BOT_USER_ID | No | Bot user ID (auto-detected if omitted) |
Self-Hosted Instances
The only difference from gitlab.com is the baseUrl. All API paths, authentication, and webhook formats are identical.
const adapter = createGitLabAdapter({
baseUrl: "https://gitlab.example.com",
token: "glpat-...",
webhookSecret: "my-secret",
});GitLab Webhook Setup
In your GitLab project, go to Settings → Webhooks and add:
- URL: Your webhook endpoint (e.g.,
https://your-app.com/api/webhooks/gitlab) - Secret token: Same value as
GITLAB_WEBHOOK_SECRET - Trigger events: Check "Comments" (and optionally "Issues events", "Merge request events")
Features
Issue and Merge Request Comments
Inbound comments on issues and merge requests are delivered as Chat SDK messages. The adapter handles both top-level comments and threaded discussions.
async onMessage({ message, reply }) {
// message.threadId encodes the project, type (issue/MR), and IID
await reply("Got it, looking into this now.");
}Threaded Discussions (Diff Comments)
Line-level comments on merge request diffs are tracked as separate discussion threads. Replies are posted within the correct thread.
Edit and Delete Comments
// Edit a comment
await chat.editMessage(threadId, messageId, "Updated response");
// Delete a comment
await chat.deleteMessage(threadId, messageId);Emoji Reactions
Add and remove emoji reactions on comments:
await chat.addReaction(threadId, messageId, "thumbsup");
await chat.removeReaction(threadId, messageId, "thumbsup");Supports standard gemojione names: thumbsup, thumbsdown, heart, tada, rocket, eyes, fire, 100, thinking, etc.
Fetch Message History
Retrieve comment history for an issue or merge request:
const { messages, nextCursor } = await chat.fetchMessages(threadId, { limit: 50 });List Open Merge Requests
const { threads } = await chat.listThreads(channelId);Markdown Rendering
Messages are rendered as GitLab-flavored markdown. Cards are converted to formatted markdown with bold titles, field labels, links, and GFM tables.
await reply({ markdown: "**Status:** Deployed to production :rocket:" });Thread ID Format
Thread IDs encode the project path, type, and IID:
| Type | Format | Example |
|---|---|---|
| Issue | gitlab:{project}:issue:{iid} | gitlab:my-group/my-project:issue:42 |
| Merge Request | gitlab:{project}:mr:{iid} | gitlab:my-group/my-project:mr:100 |
| Discussion | gitlab:{project}:mr:{iid}:d:{id} | gitlab:my-group/my-project:mr:100:d:abc123 |
Unsupported Operations
These methods throw NotImplementedError as they have no GitLab equivalent:
startTyping()— no GitLab equivalentstream()— GitLab rejects rapid editsopenModal()/postEphemeral()/scheduleMessage()— no GitLab equivalent
Self-Echo Prevention
The adapter automatically skips:
- Comments from the bot's own user ID (resolved on
initialize()) - System-generated notes (assignments, label changes, etc.)
License
MIT
