JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 23736
  • Score
    100M100P100Q15608F
  • License Apache-2.0

GitLab Duo provider for Vercel AI SDK

Package Exports

  • @gitlab/gitlab-ai-provider
  • @gitlab/gitlab-ai-provider/package.json

Readme

GitLab AI Provider

A comprehensive TypeScript provider for integrating GitLab Duo AI capabilities with the Vercel AI SDK. This package enables seamless access to GitLab's AI-powered features including chat, agentic workflows, and tool calling through a unified interface.

🌟 Features

  • 🤖 Agentic Chat: Native tool calling support via GitLab's Anthropic proxy
  • 🔐 Multiple Authentication: Support for OAuth, Personal Access Tokens, and OpenCode auth
  • 🌐 Self-Hosted Support: Works with both GitLab.com and self-hosted instances
  • 📦 Tool Executors: Built-in Anthropic and GitLab API tool executors
  • 🔍 Project Detection: Automatic GitLab project detection from git remotes
  • 💾 Smart Caching: Project and token caching for optimal performance
  • 🎯 Type-Safe: Complete TypeScript definitions with Zod validation

📦 Installation

npm install @gitlab/gitlab-ai-provider

Peer Dependencies

npm install @ai-sdk/provider @ai-sdk/provider-utils

🚀 Quick Start

Basic Chat

import { createGitLab } from '@gitlab/gitlab-ai-provider';
import { generateText } from 'ai';

const gitlab = createGitLab({
  apiKey: process.env.GITLAB_TOKEN,
  instanceUrl: 'https://gitlab.com', // optional, defaults to gitlab.com
});

// All equivalent ways to create a chat model:
const model = gitlab('duo-chat'); // callable provider
const model2 = gitlab.chat('duo-chat'); // .chat() alias (recommended)
const model3 = gitlab.languageModel('duo-chat'); // explicit method

const { text } = await generateText({
  model: gitlab.chat('duo-chat'),
  prompt: 'Explain how to create a merge request in GitLab',
});

console.log(text);

Agentic Chat with Tool Calling

import { createGitLab } from '@gitlab/gitlab-ai-provider';
import { generateText } from 'ai';

const gitlab = createGitLab({
  apiKey: process.env.GITLAB_TOKEN,
});

// Use agentic model for native tool calling support
const model = gitlab.agenticChat('duo-chat', {
  anthropicModel: 'claude-sonnet-4-20250514',
  maxTokens: 8192,
});

const { text } = await generateText({
  model,
  prompt: 'List all open merge requests in my project',
  tools: {
    // Your custom tools here
  },
});

Agentic Chat with Feature Flags

You can pass feature flags to enable experimental features in GitLab's Anthropic proxy:

import { createGitLab } from '@gitlab/gitlab-ai-provider';

// Option 1: Set feature flags globally for all agentic chat models
const gitlab = createGitLab({
  apiKey: process.env.GITLAB_TOKEN,
  featureFlags: {
    duo_agent_platform_agentic_chat: true,
    duo_agent_platform: true,
  },
});

const model = gitlab.agenticChat('duo-chat');

// Option 2: Set feature flags per model (overrides global flags)
const modelWithFlags = gitlab.agenticChat('duo-chat', {
  featureFlags: {
    duo_agent_platform_agentic_chat: true,
    duo_agent_platform: true,
    custom_feature_flag: false,
  },
});

// Option 3: Merge both (model-level flags take precedence)
const gitlab2 = createGitLab({
  featureFlags: {
    duo_agent_platform: true, // will be overridden
  },
});

const mergedModel = gitlab2.agenticChat('duo-chat', {
  featureFlags: {
    duo_agent_platform: false, // overrides provider-level
    duo_agent_platform_agentic_chat: true, // adds new flag
  },
});

🔑 Authentication

Personal Access Token

const gitlab = createGitLab({
  apiKey: 'glpat-xxxxxxxxxxxxxxxxxxxx',
});

Environment Variable

export GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx
const gitlab = createGitLab(); // Automatically uses GITLAB_TOKEN

OAuth (OpenCode Auth)

The provider automatically detects and uses OpenCode authentication if available:

const gitlab = createGitLab({
  instanceUrl: 'https://gitlab.com',
  // OAuth tokens are loaded from ~/.opencode/auth.json
});

Custom Headers

const gitlab = createGitLab({
  apiKey: 'your-token',
  headers: {
    'X-Custom-Header': 'value',
  },
});

🏗️ Architecture

Core Components

1. GitLabProvider

Main provider factory that creates language models with different capabilities.

interface GitLabProvider {
  (modelId: string): LanguageModelV2;
  languageModel(modelId: string): LanguageModelV2;
  agenticChat(modelId: string, options?: GitLabAgenticOptions): GitLabAgenticLanguageModel;
}

2. GitLabAgenticLanguageModel

Provides native tool calling through GitLab's Anthropic proxy.

  • Uses Claude models via https://cloud.gitlab.com/ai/v1/proxy/anthropic/
  • Automatic token refresh and retry logic
  • Direct access token management
  • Supports all Anthropic tool calling features

Tool Executors

AnthropicToolExecutor

Executes local file system and command tools:

  • list_dir - List directory contents
  • read_file - Read file contents
  • write_file - Write to files
  • edit_file - Edit file with find/replace
  • find_files - Find files by pattern
  • mkdir - Create directories
  • grep - Search file contents
  • run_command - Execute shell commands
  • run_git_command - Execute git commands

GitLabApiToolExecutor

Executes GitLab API operations:

  • Merge Requests: get, list, changes, discussions, notes
  • Issues: get, list, notes
  • Pipelines: list, get, jobs, logs
  • Repository: files, commits, branches
  • Search: global and project search
  • Projects: get, members

Supporting Utilities

GitLabProjectDetector

Automatically detects GitLab projects from git remotes.

const detector = new GitLabProjectDetector({
  instanceUrl: 'https://gitlab.com',
  getHeaders: () => ({ Authorization: `Bearer ${token}` }),
});

const project = await detector.detectProject(process.cwd());
// Returns: { id: 12345, path: 'group/project', namespaceId: 67890 }

GitLabProjectCache

Caches project information with TTL.

const cache = new GitLabProjectCache(5 * 60 * 1000); // 5 minutes
cache.set('key', project);
const cached = cache.get('key');

GitLabOAuthManager

Manages OAuth token lifecycle.

const oauthManager = new GitLabOAuthManager();

// Exchange authorization code
const tokens = await oauthManager.exchangeAuthorizationCode({
  instanceUrl: 'https://gitlab.com',
  code: 'auth-code',
  codeVerifier: 'verifier',
});

// Refresh tokens
const refreshed = await oauthManager.refreshIfNeeded(tokens);

GitLabDirectAccessClient

Manages direct access tokens for Anthropic proxy.

const client = new GitLabDirectAccessClient({
  instanceUrl: 'https://gitlab.com',
  getHeaders: () => ({ Authorization: `Bearer ${token}` }),
});

const directToken = await client.getDirectAccessToken();
// Returns: { token: 'xxx', headers: {...}, expiresAt: 123456 }

📚 API Reference

Provider Configuration

interface GitLabProviderSettings {
  instanceUrl?: string; // Default: 'https://gitlab.com'
  apiKey?: string; // PAT or OAuth access token
  refreshToken?: string; // OAuth refresh token
  name?: string; // Provider name prefix
  headers?: Record<string, string>; // Custom headers
  fetch?: typeof fetch; // Custom fetch implementation
}

Agentic Chat Options

interface GitLabAgenticOptions {
  anthropicModel?: string; // Default: 'claude-sonnet-4-20250514'
  maxTokens?: number; // Default: 8192
}

Error Handling

import { GitLabError } from '@gitlab/gitlab-ai-provider';

try {
  const result = await generateText({ model, prompt });
} catch (error) {
  if (error instanceof GitLabError) {
    if (error.isAuthError()) {
      console.error('Authentication failed');
    } else if (error.isRateLimitError()) {
      console.error('Rate limit exceeded');
    } else if (error.isServerError()) {
      console.error('Server error:', error.statusCode);
    }
  }
}

🔧 Development

Build

npm run build          # Build once
npm run build:watch    # Build in watch mode

Testing

npm test              # Run all tests
npm run test:watch    # Run tests in watch mode

Code Quality

npm run lint          # Lint code
npm run lint:fix      # Lint and auto-fix
npm run format        # Format code
npm run format:check  # Check formatting
npm run type-check    # TypeScript type checking

Project Structure

gitlab-ai-provider/
├── src/
│   ├── index.ts                          # Main exports
│   ├── gitlab-provider.ts                # Provider factory
│   ├── gitlab-agentic-language-model.ts  # Agentic chat model
│   ├── gitlab-direct-access.ts           # Direct access tokens
│   ├── gitlab-oauth-manager.ts           # OAuth management
│   ├── gitlab-oauth-types.ts             # OAuth types
│   ├── gitlab-project-detector.ts        # Project detection
│   ├── gitlab-project-cache.ts           # Project caching
│   ├── gitlab-anthropic-tools.ts         # Anthropic tool executor
│   ├── gitlab-api-tools.ts               # GitLab API tool executor
│   ├── gitlab-api-types.ts               # API types
│   ├── gitlab-error.ts                   # Error handling
│   └── gitlab-workflow-debug.ts          # Debug logging
├── tests/                                # Test files
├── dist/                                 # Build output
├── package.json
├── tsconfig.json
├── tsup.config.ts
└── vitest.config.ts

📝 Code Style

  • Imports: Named imports, organized by external → internal → types
  • Formatting: Single quotes, semicolons, 100 char line width, 2 space indent
  • Types: Interfaces for public APIs, Zod schemas for runtime validation
  • Naming: camelCase (variables/functions), PascalCase (classes/types), kebab-case (files)
  • Exports: Named exports only (no default exports)
  • Comments: JSDoc for public APIs with @param/@returns

Assistant

🤝 Contributing

Contributions are welcome! Please see our Contributing Guide for detailed guidelines on:

  • Code style and conventions
  • Development workflow
  • Testing requirements
  • Submitting merge requests
  • Developer Certificate of Origin and License

Quick Start for Contributors:

  1. Commit Messages: Use conventional commits format

    feat(scope): add new feature
    fix(scope): fix bug
    docs(scope): update documentation
  2. Code Quality: Ensure all checks pass

    npm run lint
    npm run type-check
    npm test
  3. Testing: Add tests for new features

🙏 Acknowledgments

This project is built on top of:


Made with ❤️ for the OpenCode community