@gitlab/gitlab-ai-provider 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +251 -0
- package/LICENSE +28 -0
- package/README.md +432 -0
- package/dist/index.d.mts +525 -0
- package/dist/index.d.ts +572 -0
- package/dist/index.js +2401 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2350 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +99 -0
package/README.md
ADDED
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
# GitLab AI Provider
|
|
2
|
+
|
|
3
|
+
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.
|
|
4
|
+
|
|
5
|
+
## 🌟 Features
|
|
6
|
+
|
|
7
|
+
- **🤖 Agentic Chat**: Native tool calling support via GitLab's Anthropic proxy
|
|
8
|
+
- **🔐 Multiple Authentication**: Support for OAuth, Personal Access Tokens, and OpenCode auth
|
|
9
|
+
- **🌐 Self-Hosted Support**: Works with both GitLab.com and self-hosted instances
|
|
10
|
+
- **📦 Tool Executors**: Built-in Anthropic and GitLab API tool executors
|
|
11
|
+
- **🔍 Project Detection**: Automatic GitLab project detection from git remotes
|
|
12
|
+
- **💾 Smart Caching**: Project and token caching for optimal performance
|
|
13
|
+
- **🎯 Type-Safe**: Complete TypeScript definitions with Zod validation
|
|
14
|
+
|
|
15
|
+
## 📦 Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @gitlab/gitlab-ai-provider
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Peer Dependencies
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install @ai-sdk/provider @ai-sdk/provider-utils
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## 🚀 Quick Start
|
|
28
|
+
|
|
29
|
+
### Basic Chat
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { createGitLab } from '@gitlab/gitlab-ai-provider';
|
|
33
|
+
import { generateText } from 'ai';
|
|
34
|
+
|
|
35
|
+
const gitlab = createGitLab({
|
|
36
|
+
apiKey: process.env.GITLAB_TOKEN,
|
|
37
|
+
instanceUrl: 'https://gitlab.com', // optional, defaults to gitlab.com
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// All equivalent ways to create a chat model:
|
|
41
|
+
const model = gitlab('duo-chat'); // callable provider
|
|
42
|
+
const model2 = gitlab.chat('duo-chat'); // .chat() alias (recommended)
|
|
43
|
+
const model3 = gitlab.languageModel('duo-chat'); // explicit method
|
|
44
|
+
|
|
45
|
+
const { text } = await generateText({
|
|
46
|
+
model: gitlab.chat('duo-chat'),
|
|
47
|
+
prompt: 'Explain how to create a merge request in GitLab',
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
console.log(text);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Agentic Chat with Tool Calling
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { createGitLab } from '@gitlab/gitlab-ai-provider';
|
|
57
|
+
import { generateText } from 'ai';
|
|
58
|
+
|
|
59
|
+
const gitlab = createGitLab({
|
|
60
|
+
apiKey: process.env.GITLAB_TOKEN,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Use agentic model for native tool calling support
|
|
64
|
+
const model = gitlab.agenticChat('duo-chat', {
|
|
65
|
+
anthropicModel: 'claude-sonnet-4-20250514',
|
|
66
|
+
maxTokens: 8192,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const { text } = await generateText({
|
|
70
|
+
model,
|
|
71
|
+
prompt: 'List all open merge requests in my project',
|
|
72
|
+
tools: {
|
|
73
|
+
// Your custom tools here
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Agentic Chat with Feature Flags
|
|
79
|
+
|
|
80
|
+
You can pass feature flags to enable experimental features in GitLab's Anthropic proxy:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
import { createGitLab } from '@gitlab/gitlab-ai-provider';
|
|
84
|
+
|
|
85
|
+
// Option 1: Set feature flags globally for all agentic chat models
|
|
86
|
+
const gitlab = createGitLab({
|
|
87
|
+
apiKey: process.env.GITLAB_TOKEN,
|
|
88
|
+
featureFlags: {
|
|
89
|
+
duo_agent_platform_agentic_chat: true,
|
|
90
|
+
duo_agent_platform: true,
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const model = gitlab.agenticChat('duo-chat');
|
|
95
|
+
|
|
96
|
+
// Option 2: Set feature flags per model (overrides global flags)
|
|
97
|
+
const modelWithFlags = gitlab.agenticChat('duo-chat', {
|
|
98
|
+
featureFlags: {
|
|
99
|
+
duo_agent_platform_agentic_chat: true,
|
|
100
|
+
duo_agent_platform: true,
|
|
101
|
+
custom_feature_flag: false,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Option 3: Merge both (model-level flags take precedence)
|
|
106
|
+
const gitlab2 = createGitLab({
|
|
107
|
+
featureFlags: {
|
|
108
|
+
duo_agent_platform: true, // will be overridden
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const mergedModel = gitlab2.agenticChat('duo-chat', {
|
|
113
|
+
featureFlags: {
|
|
114
|
+
duo_agent_platform: false, // overrides provider-level
|
|
115
|
+
duo_agent_platform_agentic_chat: true, // adds new flag
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## 🔑 Authentication
|
|
121
|
+
|
|
122
|
+
### Personal Access Token
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
const gitlab = createGitLab({
|
|
126
|
+
apiKey: 'glpat-xxxxxxxxxxxxxxxxxxxx',
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Environment Variable
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
export GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
const gitlab = createGitLab(); // Automatically uses GITLAB_TOKEN
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### OAuth (OpenCode Auth)
|
|
141
|
+
|
|
142
|
+
The provider automatically detects and uses OpenCode authentication if available:
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
const gitlab = createGitLab({
|
|
146
|
+
instanceUrl: 'https://gitlab.com',
|
|
147
|
+
// OAuth tokens are loaded from ~/.opencode/auth.json
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Custom Headers
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
const gitlab = createGitLab({
|
|
155
|
+
apiKey: 'your-token',
|
|
156
|
+
headers: {
|
|
157
|
+
'X-Custom-Header': 'value',
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## 🏗️ Architecture
|
|
163
|
+
|
|
164
|
+
### Core Components
|
|
165
|
+
|
|
166
|
+
#### 1. **GitLabProvider**
|
|
167
|
+
|
|
168
|
+
Main provider factory that creates language models with different capabilities.
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
interface GitLabProvider {
|
|
172
|
+
(modelId: string): LanguageModelV2;
|
|
173
|
+
languageModel(modelId: string): LanguageModelV2;
|
|
174
|
+
agenticChat(modelId: string, options?: GitLabAgenticOptions): GitLabAgenticLanguageModel;
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
#### 2. **GitLabAgenticLanguageModel**
|
|
179
|
+
|
|
180
|
+
Provides native tool calling through GitLab's Anthropic proxy.
|
|
181
|
+
|
|
182
|
+
- Uses Claude models via `https://cloud.gitlab.com/ai/v1/proxy/anthropic/`
|
|
183
|
+
- Automatic token refresh and retry logic
|
|
184
|
+
- Direct access token management
|
|
185
|
+
- Supports all Anthropic tool calling features
|
|
186
|
+
|
|
187
|
+
### Tool Executors
|
|
188
|
+
|
|
189
|
+
#### AnthropicToolExecutor
|
|
190
|
+
|
|
191
|
+
Executes local file system and command tools:
|
|
192
|
+
|
|
193
|
+
- `list_dir` - List directory contents
|
|
194
|
+
- `read_file` - Read file contents
|
|
195
|
+
- `write_file` - Write to files
|
|
196
|
+
- `edit_file` - Edit file with find/replace
|
|
197
|
+
- `find_files` - Find files by pattern
|
|
198
|
+
- `mkdir` - Create directories
|
|
199
|
+
- `grep` - Search file contents
|
|
200
|
+
- `run_command` - Execute shell commands
|
|
201
|
+
- `run_git_command` - Execute git commands
|
|
202
|
+
|
|
203
|
+
#### GitLabApiToolExecutor
|
|
204
|
+
|
|
205
|
+
Executes GitLab API operations:
|
|
206
|
+
|
|
207
|
+
- Merge Requests: get, list, changes, discussions, notes
|
|
208
|
+
- Issues: get, list, notes
|
|
209
|
+
- Pipelines: list, get, jobs, logs
|
|
210
|
+
- Repository: files, commits, branches
|
|
211
|
+
- Search: global and project search
|
|
212
|
+
- Projects: get, members
|
|
213
|
+
|
|
214
|
+
### Supporting Utilities
|
|
215
|
+
|
|
216
|
+
#### GitLabProjectDetector
|
|
217
|
+
|
|
218
|
+
Automatically detects GitLab projects from git remotes.
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
const detector = new GitLabProjectDetector({
|
|
222
|
+
instanceUrl: 'https://gitlab.com',
|
|
223
|
+
getHeaders: () => ({ Authorization: `Bearer ${token}` }),
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
const project = await detector.detectProject(process.cwd());
|
|
227
|
+
// Returns: { id: 12345, path: 'group/project', namespaceId: 67890 }
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
#### GitLabProjectCache
|
|
231
|
+
|
|
232
|
+
Caches project information with TTL.
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
const cache = new GitLabProjectCache(5 * 60 * 1000); // 5 minutes
|
|
236
|
+
cache.set('key', project);
|
|
237
|
+
const cached = cache.get('key');
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
#### GitLabOAuthManager
|
|
241
|
+
|
|
242
|
+
Manages OAuth token lifecycle.
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
const oauthManager = new GitLabOAuthManager();
|
|
246
|
+
|
|
247
|
+
// Exchange authorization code
|
|
248
|
+
const tokens = await oauthManager.exchangeAuthorizationCode({
|
|
249
|
+
instanceUrl: 'https://gitlab.com',
|
|
250
|
+
code: 'auth-code',
|
|
251
|
+
codeVerifier: 'verifier',
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
// Refresh tokens
|
|
255
|
+
const refreshed = await oauthManager.refreshIfNeeded(tokens);
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
#### GitLabDirectAccessClient
|
|
259
|
+
|
|
260
|
+
Manages direct access tokens for Anthropic proxy.
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
const client = new GitLabDirectAccessClient({
|
|
264
|
+
instanceUrl: 'https://gitlab.com',
|
|
265
|
+
getHeaders: () => ({ Authorization: `Bearer ${token}` }),
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
const directToken = await client.getDirectAccessToken();
|
|
269
|
+
// Returns: { token: 'xxx', headers: {...}, expiresAt: 123456 }
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## 📚 API Reference
|
|
273
|
+
|
|
274
|
+
### Provider Configuration
|
|
275
|
+
|
|
276
|
+
```typescript
|
|
277
|
+
interface GitLabProviderSettings {
|
|
278
|
+
instanceUrl?: string; // Default: 'https://gitlab.com'
|
|
279
|
+
apiKey?: string; // PAT or OAuth access token
|
|
280
|
+
refreshToken?: string; // OAuth refresh token
|
|
281
|
+
name?: string; // Provider name prefix
|
|
282
|
+
headers?: Record<string, string>; // Custom headers
|
|
283
|
+
fetch?: typeof fetch; // Custom fetch implementation
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Agentic Chat Options
|
|
288
|
+
|
|
289
|
+
```typescript
|
|
290
|
+
interface GitLabAgenticOptions {
|
|
291
|
+
anthropicModel?: string; // Default: 'claude-sonnet-4-20250514'
|
|
292
|
+
maxTokens?: number; // Default: 8192
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Error Handling
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
import { GitLabError } from '@gitlab/gitlab-ai-provider';
|
|
300
|
+
|
|
301
|
+
try {
|
|
302
|
+
const result = await generateText({ model, prompt });
|
|
303
|
+
} catch (error) {
|
|
304
|
+
if (error instanceof GitLabError) {
|
|
305
|
+
if (error.isAuthError()) {
|
|
306
|
+
console.error('Authentication failed');
|
|
307
|
+
} else if (error.isRateLimitError()) {
|
|
308
|
+
console.error('Rate limit exceeded');
|
|
309
|
+
} else if (error.isServerError()) {
|
|
310
|
+
console.error('Server error:', error.statusCode);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## 🔧 Development
|
|
317
|
+
|
|
318
|
+
### Build
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
npm run build # Build once
|
|
322
|
+
npm run build:watch # Build in watch mode
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Testing
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
npm test # Run all tests
|
|
329
|
+
npm run test:watch # Run tests in watch mode
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Code Quality
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
npm run lint # Lint code
|
|
336
|
+
npm run lint:fix # Lint and auto-fix
|
|
337
|
+
npm run format # Format code
|
|
338
|
+
npm run format:check # Check formatting
|
|
339
|
+
npm run type-check # TypeScript type checking
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Project Structure
|
|
343
|
+
|
|
344
|
+
```
|
|
345
|
+
gitlab-ai-provider/
|
|
346
|
+
├── src/
|
|
347
|
+
│ ├── index.ts # Main exports
|
|
348
|
+
│ ├── gitlab-provider.ts # Provider factory
|
|
349
|
+
│ ├── gitlab-agentic-language-model.ts # Agentic chat model
|
|
350
|
+
│ ├── gitlab-direct-access.ts # Direct access tokens
|
|
351
|
+
│ ├── gitlab-oauth-manager.ts # OAuth management
|
|
352
|
+
│ ├── gitlab-oauth-types.ts # OAuth types
|
|
353
|
+
│ ├── gitlab-project-detector.ts # Project detection
|
|
354
|
+
│ ├── gitlab-project-cache.ts # Project caching
|
|
355
|
+
│ ├── gitlab-anthropic-tools.ts # Anthropic tool executor
|
|
356
|
+
│ ├── gitlab-api-tools.ts # GitLab API tool executor
|
|
357
|
+
│ ├── gitlab-api-types.ts # API types
|
|
358
|
+
│ ├── gitlab-error.ts # Error handling
|
|
359
|
+
│ └── gitlab-workflow-debug.ts # Debug logging
|
|
360
|
+
├── tests/ # Test files
|
|
361
|
+
├── dist/ # Build output
|
|
362
|
+
├── package.json
|
|
363
|
+
├── tsconfig.json
|
|
364
|
+
├── tsup.config.ts
|
|
365
|
+
└── vitest.config.ts
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
## 📝 Code Style
|
|
369
|
+
|
|
370
|
+
- **Imports**: Named imports, organized by external → internal → types
|
|
371
|
+
- **Formatting**: Single quotes, semicolons, 100 char line width, 2 space indent
|
|
372
|
+
- **Types**: Interfaces for public APIs, Zod schemas for runtime validation
|
|
373
|
+
- **Naming**: camelCase (variables/functions), PascalCase (classes/types), kebab-case (files)
|
|
374
|
+
- **Exports**: Named exports only (no default exports)
|
|
375
|
+
- **Comments**: JSDoc for public APIs with @param/@returns
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
## Assistant
|
|
380
|
+
|
|
381
|
+
## 🤝 Contributing
|
|
382
|
+
|
|
383
|
+
Contributions are welcome! Please see our [Contributing Guide](./CONTRIBUTING.md) for detailed guidelines on:
|
|
384
|
+
|
|
385
|
+
- Code style and conventions
|
|
386
|
+
- Development workflow
|
|
387
|
+
- Testing requirements
|
|
388
|
+
- Submitting merge requests
|
|
389
|
+
- Developer Certificate of Origin and License
|
|
390
|
+
|
|
391
|
+
**Quick Start for Contributors**:
|
|
392
|
+
|
|
393
|
+
1. **Commit Messages**: Use conventional commits format
|
|
394
|
+
|
|
395
|
+
```
|
|
396
|
+
feat(scope): add new feature
|
|
397
|
+
fix(scope): fix bug
|
|
398
|
+
docs(scope): update documentation
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
2. **Code Quality**: Ensure all checks pass
|
|
402
|
+
|
|
403
|
+
```bash
|
|
404
|
+
npm run lint
|
|
405
|
+
npm run type-check
|
|
406
|
+
npm test
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
3. **Testing**: Add tests for new features
|
|
410
|
+
|
|
411
|
+
## 🔗 Links
|
|
412
|
+
|
|
413
|
+
- [GitLab Repository](https://gitlab.com/gitlab-org/editor-extensions/gitlab-ai-provider)
|
|
414
|
+
- [npm Package](https://www.npmjs.com/package/@gitlab/gitlab-ai-provider)
|
|
415
|
+
- [Issue Tracker](https://gitlab.com/gitlab-org/editor-extensions/gitlab-ai-provider/-/issues)
|
|
416
|
+
- [Contributing Guide](./CONTRIBUTING.md)
|
|
417
|
+
- [Changelog](./CHANGELOG.md)
|
|
418
|
+
- [Agent Guidelines](./AGENTS.md)
|
|
419
|
+
|
|
420
|
+
## 🙏 Acknowledgments
|
|
421
|
+
|
|
422
|
+
This project is built on top of:
|
|
423
|
+
|
|
424
|
+
- [Vercel AI SDK](https://sdk.vercel.ai/)
|
|
425
|
+
- [Anthropic SDK](https://github.com/anthropics/anthropic-sdk-typescript)
|
|
426
|
+
- [GitLab Duo](https://about.gitlab.com/gitlab-duo/)
|
|
427
|
+
|
|
428
|
+
---
|
|
429
|
+
|
|
430
|
+
**Made with ❤️ for the OpenCode community**
|
|
431
|
+
|
|
432
|
+
---
|