@gitlab/gitlab-ai-provider 3.3.1 → 3.4.1

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 CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
4
4
 
5
+ ## <small>3.4.1 (2026-02-06)</small>
6
+
7
+ - Merge branch 'vg/token_refresh_fix' into 'main' ([8c1f2c4](https://gitlab.com/gitlab-org/editor-extensions/gitlab-ai-provider/commit/8c1f2c4))
8
+ - fix: detect context overflow errors before token refresh ([ce272cd](https://gitlab.com/gitlab-org/editor-extensions/gitlab-ai-provider/commit/ce272cd))
9
+
10
+ ## 3.4.0 (2026-02-02)
11
+
12
+ - Merge branch 'feat/ai-gateway-headers' into 'main' ([f2d4c79](https://gitlab.com/gitlab-org/editor-extensions/gitlab-ai-provider/commit/f2d4c79))
13
+ - feat: add custom AI Gateway headers support ([2ef662d](https://gitlab.com/gitlab-org/editor-extensions/gitlab-ai-provider/commit/2ef662d))
14
+ - chore: added models testing script ([85dd9ba](https://gitlab.com/gitlab-org/editor-extensions/gitlab-ai-provider/commit/85dd9ba))
15
+ - chore: bump version to 3.3.1 to fix package-lock.json sync ([6e6e9e2](https://gitlab.com/gitlab-org/editor-extensions/gitlab-ai-provider/commit/6e6e9e2))
16
+
5
17
  ## 3.3.0 (2026-01-23)
6
18
 
7
19
  - feat: add GPT-5.2 model support (duo-chat-gpt-5-2) ([fba8c4c](https://gitlab.com/gitlab-org/editor-extensions/gitlab-ai-provider/commit/fba8c4c))
package/README.md CHANGED
@@ -272,6 +272,33 @@ const gitlab = createGitLab({
272
272
  });
273
273
  ```
274
274
 
275
+ ### AI Gateway Headers
276
+
277
+ Custom headers can be sent to GitLab's AI Gateway (Anthropic/OpenAI proxy) for traffic identification and routing. By default, the provider sends `User-Agent: gitlab-ai-provider/{version}`.
278
+
279
+ ```typescript
280
+ // Provider-level headers (apply to all agentic models)
281
+ const gitlab = createGitLab({
282
+ apiKey: process.env.GITLAB_TOKEN,
283
+ aiGatewayHeaders: {
284
+ 'X-Custom-Routing': 'premium-tier',
285
+ },
286
+ });
287
+
288
+ // Model-level headers (override provider-level)
289
+ const model = gitlab.agenticChat('duo-chat-opus-4-5', {
290
+ aiGatewayHeaders: {
291
+ 'X-Request-Priority': 'high',
292
+ },
293
+ });
294
+ ```
295
+
296
+ **Header Precedence (lowest to highest):**
297
+
298
+ 1. Default headers (`User-Agent: gitlab-ai-provider/{version}`)
299
+ 2. Provider-level `aiGatewayHeaders`
300
+ 3. Model-level `aiGatewayHeaders`
301
+
275
302
  ## 🏗️ Architecture
276
303
 
277
304
  ### Core Components
@@ -374,7 +401,8 @@ interface GitLabProviderSettings {
374
401
  apiKey?: string; // PAT or OAuth access token
375
402
  refreshToken?: string; // OAuth refresh token
376
403
  name?: string; // Provider name prefix
377
- headers?: Record<string, string>; // Custom headers
404
+ headers?: Record<string, string>; // Custom headers for GitLab API
405
+ aiGatewayHeaders?: Record<string, string>; // Custom headers for AI Gateway proxy
378
406
  fetch?: typeof fetch; // Custom fetch implementation
379
407
  aiGatewayUrl?: string; // AI Gateway URL (default: 'https://cloud.gitlab.com')
380
408
  }
@@ -394,6 +422,7 @@ interface GitLabAgenticOptions {
394
422
  providerModel?: string; // Override the backend model (e.g., 'claude-sonnet-4-5-20250929' or 'gpt-5.1-2025-11-13')
395
423
  maxTokens?: number; // Default: 8192
396
424
  featureFlags?: Record<string, boolean>; // GitLab feature flags
425
+ aiGatewayHeaders?: Record<string, string>; // Custom headers for AI Gateway proxy (per-model)
397
426
  }
398
427
  ```
399
428
 
package/dist/index.d.mts CHANGED
@@ -34,6 +34,11 @@ interface GitLabAnthropicConfig {
34
34
  * @default 'https://cloud.gitlab.com'
35
35
  */
36
36
  aiGatewayUrl?: string;
37
+ /**
38
+ * Custom headers for AI Gateway Anthropic proxy requests.
39
+ * Merged with headers from direct_access token response.
40
+ */
41
+ aiGatewayHeaders?: Record<string, string>;
37
42
  }
38
43
  /**
39
44
  * GitLab Anthropic Language Model
@@ -60,6 +65,11 @@ declare class GitLabAnthropicLanguageModel implements LanguageModelV2 {
60
65
  * Check if an error is a token-related authentication error that can be retried
61
66
  */
62
67
  private isTokenError;
68
+ /**
69
+ * Check if an error is a context overflow error (prompt too long)
70
+ * These should NOT trigger token refresh and should be reported to the user.
71
+ */
72
+ private isContextOverflowError;
63
73
  /**
64
74
  * Convert AI SDK tools to Anthropic tool format
65
75
  */
@@ -154,6 +164,12 @@ interface GitLabAgenticOptions {
154
164
  * Feature flags to pass to the GitLab API
155
165
  */
156
166
  featureFlags?: Record<string, boolean>;
167
+ /**
168
+ * Custom headers for AI Gateway requests (per-model override).
169
+ * These headers are sent to the Anthropic/OpenAI proxy endpoints.
170
+ * Merged with provider-level aiGatewayHeaders (model-level takes precedence).
171
+ */
172
+ aiGatewayHeaders?: Record<string, string>;
157
173
  }
158
174
  interface GitLabProviderSettings {
159
175
  /**
@@ -200,6 +216,12 @@ interface GitLabProviderSettings {
200
216
  * @default 'https://cloud.gitlab.com'
201
217
  */
202
218
  aiGatewayUrl?: string;
219
+ /**
220
+ * Custom headers to include in AI Gateway requests (Anthropic/OpenAI proxy).
221
+ * These headers are merged with the default headers from direct_access response.
222
+ * Default User-Agent: gitlab-ai-provider/{version}
223
+ */
224
+ aiGatewayHeaders?: Record<string, string>;
203
225
  }
204
226
  declare function createGitLab(options?: GitLabProviderSettings): GitLabProvider;
205
227
  /**
@@ -214,6 +236,8 @@ declare function createGitLab(options?: GitLabProviderSettings): GitLabProvider;
214
236
  */
215
237
  declare const gitlab: GitLabProvider;
216
238
 
239
+ declare const VERSION: string;
240
+
217
241
  interface GitLabOpenAIConfig {
218
242
  provider: string;
219
243
  instanceUrl: string;
@@ -228,6 +252,11 @@ interface GitLabOpenAIConfig {
228
252
  aiGatewayUrl?: string;
229
253
  /** Whether to use the Responses API instead of Chat Completions API */
230
254
  useResponsesApi?: boolean;
255
+ /**
256
+ * Custom headers for AI Gateway OpenAI proxy requests.
257
+ * Merged with headers from direct_access token response.
258
+ */
259
+ aiGatewayHeaders?: Record<string, string>;
231
260
  }
232
261
  declare class GitLabOpenAILanguageModel implements LanguageModelV2 {
233
262
  readonly specificationVersion: "v2";
@@ -241,6 +270,11 @@ declare class GitLabOpenAILanguageModel implements LanguageModelV2 {
241
270
  get provider(): string;
242
271
  private getOpenAIClient;
243
272
  private isTokenError;
273
+ /**
274
+ * Check if an error is a context overflow error (prompt too long)
275
+ * These should NOT trigger token refresh and should be reported to the user.
276
+ */
277
+ private isContextOverflowError;
244
278
  private convertTools;
245
279
  private convertToolChoice;
246
280
  private convertPrompt;
@@ -318,6 +352,11 @@ declare class GitLabError extends Error {
318
352
  isRateLimitError(): boolean;
319
353
  isForbiddenError(): boolean;
320
354
  isServerError(): boolean;
355
+ /**
356
+ * Check if this error is a context overflow error (prompt too long).
357
+ * These errors occur when the conversation exceeds the model's token limit.
358
+ */
359
+ isContextOverflowError(): boolean;
321
360
  }
322
361
 
323
362
  declare const gitlabOAuthTokenResponseSchema: z.ZodObject<{
@@ -641,4 +680,4 @@ declare class GitLabDirectAccessClient {
641
680
  invalidateToken(): void;
642
681
  }
643
682
 
644
- export { BUNDLED_CLIENT_ID, DEFAULT_AI_GATEWAY_URL, type DirectAccessToken, GITLAB_COM_URL, type GitLabAgenticOptions, type GitLabAnthropicConfig, GitLabAnthropicLanguageModel, GitLabDirectAccessClient, type GitLabDirectAccessConfig, GitLabError, type GitLabErrorOptions, GitLabOAuthManager, type GitLabOAuthTokenResponse, type GitLabOAuthTokens, type GitLabOpenAIConfig, GitLabOpenAILanguageModel, type GitLabProject, GitLabProjectCache, GitLabProjectDetector, type GitLabProjectDetectorConfig, type GitLabProvider, type GitLabProviderSettings, MODEL_ID_TO_ANTHROPIC_MODEL, MODEL_MAPPINGS, type ModelMapping, type ModelProvider, OAUTH_SCOPES, type OpenAIApiType, type OpenCodeAuth, type OpenCodeAuthApi, type OpenCodeAuthOAuth, TOKEN_EXPIRY_SKEW_MS, createGitLab, getAnthropicModelForModelId, getModelMapping, getOpenAIApiType, getOpenAIModelForModelId, getProviderForModelId, getValidModelsForProvider, gitlab, isResponsesApiModel };
683
+ export { BUNDLED_CLIENT_ID, DEFAULT_AI_GATEWAY_URL, type DirectAccessToken, GITLAB_COM_URL, type GitLabAgenticOptions, type GitLabAnthropicConfig, GitLabAnthropicLanguageModel, GitLabDirectAccessClient, type GitLabDirectAccessConfig, GitLabError, type GitLabErrorOptions, GitLabOAuthManager, type GitLabOAuthTokenResponse, type GitLabOAuthTokens, type GitLabOpenAIConfig, GitLabOpenAILanguageModel, type GitLabProject, GitLabProjectCache, GitLabProjectDetector, type GitLabProjectDetectorConfig, type GitLabProvider, type GitLabProviderSettings, MODEL_ID_TO_ANTHROPIC_MODEL, MODEL_MAPPINGS, type ModelMapping, type ModelProvider, OAUTH_SCOPES, type OpenAIApiType, type OpenCodeAuth, type OpenCodeAuthApi, type OpenCodeAuthOAuth, TOKEN_EXPIRY_SKEW_MS, VERSION, createGitLab, getAnthropicModelForModelId, getModelMapping, getOpenAIApiType, getOpenAIModelForModelId, getProviderForModelId, getValidModelsForProvider, gitlab, isResponsesApiModel };
package/dist/index.d.ts CHANGED
@@ -34,6 +34,11 @@ interface GitLabAnthropicConfig {
34
34
  * @default 'https://cloud.gitlab.com'
35
35
  */
36
36
  aiGatewayUrl?: string;
37
+ /**
38
+ * Custom headers for AI Gateway Anthropic proxy requests.
39
+ * Merged with headers from direct_access token response.
40
+ */
41
+ aiGatewayHeaders?: Record<string, string>;
37
42
  }
38
43
  /**
39
44
  * GitLab Anthropic Language Model
@@ -60,6 +65,11 @@ declare class GitLabAnthropicLanguageModel implements LanguageModelV2 {
60
65
  * Check if an error is a token-related authentication error that can be retried
61
66
  */
62
67
  private isTokenError;
68
+ /**
69
+ * Check if an error is a context overflow error (prompt too long)
70
+ * These should NOT trigger token refresh and should be reported to the user.
71
+ */
72
+ private isContextOverflowError;
63
73
  /**
64
74
  * Convert AI SDK tools to Anthropic tool format
65
75
  */
@@ -154,6 +164,12 @@ interface GitLabAgenticOptions {
154
164
  * Feature flags to pass to the GitLab API
155
165
  */
156
166
  featureFlags?: Record<string, boolean>;
167
+ /**
168
+ * Custom headers for AI Gateway requests (per-model override).
169
+ * These headers are sent to the Anthropic/OpenAI proxy endpoints.
170
+ * Merged with provider-level aiGatewayHeaders (model-level takes precedence).
171
+ */
172
+ aiGatewayHeaders?: Record<string, string>;
157
173
  }
158
174
  interface GitLabProviderSettings {
159
175
  /**
@@ -200,6 +216,12 @@ interface GitLabProviderSettings {
200
216
  * @default 'https://cloud.gitlab.com'
201
217
  */
202
218
  aiGatewayUrl?: string;
219
+ /**
220
+ * Custom headers to include in AI Gateway requests (Anthropic/OpenAI proxy).
221
+ * These headers are merged with the default headers from direct_access response.
222
+ * Default User-Agent: gitlab-ai-provider/{version}
223
+ */
224
+ aiGatewayHeaders?: Record<string, string>;
203
225
  }
204
226
  declare function createGitLab(options?: GitLabProviderSettings): GitLabProvider;
205
227
  /**
@@ -214,6 +236,8 @@ declare function createGitLab(options?: GitLabProviderSettings): GitLabProvider;
214
236
  */
215
237
  declare const gitlab: GitLabProvider;
216
238
 
239
+ declare const VERSION: string;
240
+
217
241
  interface GitLabOpenAIConfig {
218
242
  provider: string;
219
243
  instanceUrl: string;
@@ -228,6 +252,11 @@ interface GitLabOpenAIConfig {
228
252
  aiGatewayUrl?: string;
229
253
  /** Whether to use the Responses API instead of Chat Completions API */
230
254
  useResponsesApi?: boolean;
255
+ /**
256
+ * Custom headers for AI Gateway OpenAI proxy requests.
257
+ * Merged with headers from direct_access token response.
258
+ */
259
+ aiGatewayHeaders?: Record<string, string>;
231
260
  }
232
261
  declare class GitLabOpenAILanguageModel implements LanguageModelV2 {
233
262
  readonly specificationVersion: "v2";
@@ -241,6 +270,11 @@ declare class GitLabOpenAILanguageModel implements LanguageModelV2 {
241
270
  get provider(): string;
242
271
  private getOpenAIClient;
243
272
  private isTokenError;
273
+ /**
274
+ * Check if an error is a context overflow error (prompt too long)
275
+ * These should NOT trigger token refresh and should be reported to the user.
276
+ */
277
+ private isContextOverflowError;
244
278
  private convertTools;
245
279
  private convertToolChoice;
246
280
  private convertPrompt;
@@ -318,6 +352,11 @@ declare class GitLabError extends Error {
318
352
  isRateLimitError(): boolean;
319
353
  isForbiddenError(): boolean;
320
354
  isServerError(): boolean;
355
+ /**
356
+ * Check if this error is a context overflow error (prompt too long).
357
+ * These errors occur when the conversation exceeds the model's token limit.
358
+ */
359
+ isContextOverflowError(): boolean;
321
360
  }
322
361
 
323
362
  declare const gitlabOAuthTokenResponseSchema: z.ZodObject<{
@@ -641,4 +680,4 @@ declare class GitLabDirectAccessClient {
641
680
  invalidateToken(): void;
642
681
  }
643
682
 
644
- export { BUNDLED_CLIENT_ID, DEFAULT_AI_GATEWAY_URL, type DirectAccessToken, GITLAB_COM_URL, type GitLabAgenticOptions, type GitLabAnthropicConfig, GitLabAnthropicLanguageModel, GitLabDirectAccessClient, type GitLabDirectAccessConfig, GitLabError, type GitLabErrorOptions, GitLabOAuthManager, type GitLabOAuthTokenResponse, type GitLabOAuthTokens, type GitLabOpenAIConfig, GitLabOpenAILanguageModel, type GitLabProject, GitLabProjectCache, GitLabProjectDetector, type GitLabProjectDetectorConfig, type GitLabProvider, type GitLabProviderSettings, MODEL_ID_TO_ANTHROPIC_MODEL, MODEL_MAPPINGS, type ModelMapping, type ModelProvider, OAUTH_SCOPES, type OpenAIApiType, type OpenCodeAuth, type OpenCodeAuthApi, type OpenCodeAuthOAuth, TOKEN_EXPIRY_SKEW_MS, createGitLab, getAnthropicModelForModelId, getModelMapping, getOpenAIApiType, getOpenAIModelForModelId, getProviderForModelId, getValidModelsForProvider, gitlab, isResponsesApiModel };
683
+ export { BUNDLED_CLIENT_ID, DEFAULT_AI_GATEWAY_URL, type DirectAccessToken, GITLAB_COM_URL, type GitLabAgenticOptions, type GitLabAnthropicConfig, GitLabAnthropicLanguageModel, GitLabDirectAccessClient, type GitLabDirectAccessConfig, GitLabError, type GitLabErrorOptions, GitLabOAuthManager, type GitLabOAuthTokenResponse, type GitLabOAuthTokens, type GitLabOpenAIConfig, GitLabOpenAILanguageModel, type GitLabProject, GitLabProjectCache, GitLabProjectDetector, type GitLabProjectDetectorConfig, type GitLabProvider, type GitLabProviderSettings, MODEL_ID_TO_ANTHROPIC_MODEL, MODEL_MAPPINGS, type ModelMapping, type ModelProvider, OAUTH_SCOPES, type OpenAIApiType, type OpenCodeAuth, type OpenCodeAuthApi, type OpenCodeAuthOAuth, TOKEN_EXPIRY_SKEW_MS, VERSION, createGitLab, getAnthropicModelForModelId, getModelMapping, getOpenAIApiType, getOpenAIModelForModelId, getProviderForModelId, getValidModelsForProvider, gitlab, isResponsesApiModel };
package/dist/index.js CHANGED
@@ -43,6 +43,7 @@ __export(index_exports, {
43
43
  MODEL_MAPPINGS: () => MODEL_MAPPINGS,
44
44
  OAUTH_SCOPES: () => OAUTH_SCOPES,
45
45
  TOKEN_EXPIRY_SKEW_MS: () => TOKEN_EXPIRY_SKEW_MS,
46
+ VERSION: () => VERSION,
46
47
  createGitLab: () => createGitLab,
47
48
  getAnthropicModelForModelId: () => getAnthropicModelForModelId,
48
49
  getModelMapping: () => getModelMapping,
@@ -95,6 +96,17 @@ var GitLabError = class _GitLabError extends Error {
95
96
  isServerError() {
96
97
  return this.statusCode !== void 0 && this.statusCode >= 500;
97
98
  }
99
+ /**
100
+ * Check if this error is a context overflow error (prompt too long).
101
+ * These errors occur when the conversation exceeds the model's token limit.
102
+ */
103
+ isContextOverflowError() {
104
+ if (this.statusCode !== 400) {
105
+ return false;
106
+ }
107
+ const message = this.message?.toLowerCase() || "";
108
+ return message.includes("context overflow") || message.includes("prompt is too long") || message.includes("prompt too long") || message.includes("tokens") && message.includes("maximum");
109
+ }
98
110
  };
99
111
 
100
112
  // src/gitlab-direct-access.ts
@@ -238,11 +250,15 @@ var GitLabAnthropicLanguageModel = class {
238
250
  async getAnthropicClient(forceRefresh = false) {
239
251
  const tokenData = await this.directAccessClient.getDirectAccessToken(forceRefresh);
240
252
  const { "x-api-key": _removed, ...filteredHeaders } = tokenData.headers;
253
+ const mergedHeaders = {
254
+ ...filteredHeaders,
255
+ ...this.config.aiGatewayHeaders
256
+ };
241
257
  this.anthropicClient = new import_sdk.default({
242
258
  apiKey: null,
243
259
  authToken: tokenData.token,
244
260
  baseURL: this.directAccessClient.getAnthropicProxyUrl(),
245
- defaultHeaders: filteredHeaders
261
+ defaultHeaders: mergedHeaders
246
262
  });
247
263
  return this.anthropicClient;
248
264
  }
@@ -261,6 +277,21 @@ var GitLabAnthropicLanguageModel = class {
261
277
  }
262
278
  return false;
263
279
  }
280
+ /**
281
+ * Check if an error is a context overflow error (prompt too long)
282
+ * These should NOT trigger token refresh and should be reported to the user.
283
+ */
284
+ isContextOverflowError(error) {
285
+ if (error instanceof import_sdk.default.APIError) {
286
+ if (error.status === 400) {
287
+ const message = error.message?.toLowerCase() || "";
288
+ if (message.includes("prompt is too long") || message.includes("prompt too long") || message.includes("tokens") && message.includes("maximum")) {
289
+ return true;
290
+ }
291
+ }
292
+ }
293
+ return false;
294
+ }
264
295
  /**
265
296
  * Convert AI SDK tools to Anthropic tool format
266
297
  */
@@ -438,6 +469,14 @@ var GitLabAnthropicLanguageModel = class {
438
469
  warnings: []
439
470
  };
440
471
  } catch (error) {
472
+ if (this.isContextOverflowError(error)) {
473
+ const apiError = error;
474
+ throw new GitLabError({
475
+ message: `Context overflow: ${apiError.message}. Please start a new session or use /compact to reduce context.`,
476
+ statusCode: 400,
477
+ cause: error
478
+ });
479
+ }
441
480
  if (!isRetry && this.isTokenError(error)) {
442
481
  this.directAccessClient.invalidateToken();
443
482
  return this.doGenerateWithRetry(options, true);
@@ -445,6 +484,7 @@ var GitLabAnthropicLanguageModel = class {
445
484
  if (error instanceof import_sdk.default.APIError) {
446
485
  throw new GitLabError({
447
486
  message: `Anthropic API error: ${error.message}`,
487
+ statusCode: error.status,
448
488
  cause: error
449
489
  });
450
490
  }
@@ -625,6 +665,19 @@ var GitLabAnthropicLanguageModel = class {
625
665
  });
626
666
  }
627
667
  }
668
+ if (self.isContextOverflowError(error)) {
669
+ const apiError = error;
670
+ controller.enqueue({
671
+ type: "error",
672
+ error: new GitLabError({
673
+ message: `Context overflow: ${apiError.message}. Please start a new session or use /compact to reduce context.`,
674
+ statusCode: 400,
675
+ cause: error
676
+ })
677
+ });
678
+ controller.close();
679
+ return;
680
+ }
628
681
  if (!isRetry && self.isTokenError(error)) {
629
682
  self.directAccessClient.invalidateToken();
630
683
  controller.enqueue({
@@ -642,6 +695,7 @@ var GitLabAnthropicLanguageModel = class {
642
695
  type: "error",
643
696
  error: new GitLabError({
644
697
  message: `Anthropic API error: ${error.message}`,
698
+ statusCode: error.status,
645
699
  cause: error
646
700
  })
647
701
  });
@@ -743,10 +797,14 @@ var GitLabOpenAILanguageModel = class {
743
797
  async getOpenAIClient(forceRefresh = false) {
744
798
  const tokenData = await this.directAccessClient.getDirectAccessToken(forceRefresh);
745
799
  const { "x-api-key": _removed, ...filteredHeaders } = tokenData.headers;
800
+ const mergedHeaders = {
801
+ ...filteredHeaders,
802
+ ...this.config.aiGatewayHeaders
803
+ };
746
804
  this.openaiClient = new import_openai.default({
747
805
  apiKey: tokenData.token,
748
806
  baseURL: this.directAccessClient.getOpenAIProxyUrl(),
749
- defaultHeaders: filteredHeaders
807
+ defaultHeaders: mergedHeaders
750
808
  });
751
809
  return this.openaiClient;
752
810
  }
@@ -762,6 +820,21 @@ var GitLabOpenAILanguageModel = class {
762
820
  }
763
821
  return false;
764
822
  }
823
+ /**
824
+ * Check if an error is a context overflow error (prompt too long)
825
+ * These should NOT trigger token refresh and should be reported to the user.
826
+ */
827
+ isContextOverflowError(error) {
828
+ if (error instanceof import_openai.default.APIError) {
829
+ if (error.status === 400) {
830
+ const message = error.message?.toLowerCase() || "";
831
+ if (message.includes("prompt is too long") || message.includes("prompt too long") || message.includes("tokens") && message.includes("maximum")) {
832
+ return true;
833
+ }
834
+ }
835
+ }
836
+ return false;
837
+ }
765
838
  convertTools(tools) {
766
839
  if (!tools || tools.length === 0) {
767
840
  return void 0;
@@ -1042,6 +1115,14 @@ var GitLabOpenAILanguageModel = class {
1042
1115
  warnings: []
1043
1116
  };
1044
1117
  } catch (error) {
1118
+ if (this.isContextOverflowError(error)) {
1119
+ const apiError = error;
1120
+ throw new GitLabError({
1121
+ message: `Context overflow: ${apiError.message}. Please start a new session or use /compact to reduce context.`,
1122
+ statusCode: 400,
1123
+ cause: error
1124
+ });
1125
+ }
1045
1126
  if (!isRetry && this.isTokenError(error)) {
1046
1127
  this.directAccessClient.invalidateToken();
1047
1128
  return this.doGenerateWithChatApi(options, true);
@@ -1049,6 +1130,7 @@ var GitLabOpenAILanguageModel = class {
1049
1130
  if (error instanceof import_openai.default.APIError) {
1050
1131
  throw new GitLabError({
1051
1132
  message: `OpenAI API error: ${error.message}`,
1133
+ statusCode: error.status,
1052
1134
  cause: error
1053
1135
  });
1054
1136
  }
@@ -1104,6 +1186,14 @@ var GitLabOpenAILanguageModel = class {
1104
1186
  warnings: []
1105
1187
  };
1106
1188
  } catch (error) {
1189
+ if (this.isContextOverflowError(error)) {
1190
+ const apiError = error;
1191
+ throw new GitLabError({
1192
+ message: `Context overflow: ${apiError.message}. Please start a new session or use /compact to reduce context.`,
1193
+ statusCode: 400,
1194
+ cause: error
1195
+ });
1196
+ }
1107
1197
  if (!isRetry && this.isTokenError(error)) {
1108
1198
  this.directAccessClient.invalidateToken();
1109
1199
  return this.doGenerateWithResponsesApi(options, true);
@@ -1111,6 +1201,7 @@ var GitLabOpenAILanguageModel = class {
1111
1201
  if (error instanceof import_openai.default.APIError) {
1112
1202
  throw new GitLabError({
1113
1203
  message: `OpenAI API error: ${error.message}`,
1204
+ statusCode: error.status,
1114
1205
  cause: error
1115
1206
  });
1116
1207
  }
@@ -1229,6 +1320,19 @@ var GitLabOpenAILanguageModel = class {
1229
1320
  controller.enqueue({ type: "finish", finishReason, usage });
1230
1321
  controller.close();
1231
1322
  } catch (error) {
1323
+ if (self.isContextOverflowError(error)) {
1324
+ const apiError = error;
1325
+ controller.enqueue({
1326
+ type: "error",
1327
+ error: new GitLabError({
1328
+ message: `Context overflow: ${apiError.message}. Please start a new session or use /compact to reduce context.`,
1329
+ statusCode: 400,
1330
+ cause: error
1331
+ })
1332
+ });
1333
+ controller.close();
1334
+ return;
1335
+ }
1232
1336
  if (!isRetry && self.isTokenError(error)) {
1233
1337
  self.directAccessClient.invalidateToken();
1234
1338
  controller.enqueue({
@@ -1243,6 +1347,7 @@ var GitLabOpenAILanguageModel = class {
1243
1347
  type: "error",
1244
1348
  error: new GitLabError({
1245
1349
  message: `OpenAI API error: ${error.message}`,
1350
+ statusCode: error.status,
1246
1351
  cause: error
1247
1352
  })
1248
1353
  });
@@ -1369,6 +1474,19 @@ var GitLabOpenAILanguageModel = class {
1369
1474
  controller.enqueue({ type: "finish", finishReason, usage });
1370
1475
  controller.close();
1371
1476
  } catch (error) {
1477
+ if (self.isContextOverflowError(error)) {
1478
+ const apiError = error;
1479
+ controller.enqueue({
1480
+ type: "error",
1481
+ error: new GitLabError({
1482
+ message: `Context overflow: ${apiError.message}. Please start a new session or use /compact to reduce context.`,
1483
+ statusCode: 400,
1484
+ cause: error
1485
+ })
1486
+ });
1487
+ controller.close();
1488
+ return;
1489
+ }
1372
1490
  if (!isRetry && self.isTokenError(error)) {
1373
1491
  self.directAccessClient.invalidateToken();
1374
1492
  controller.enqueue({
@@ -1383,6 +1501,7 @@ var GitLabOpenAILanguageModel = class {
1383
1501
  type: "error",
1384
1502
  error: new GitLabError({
1385
1503
  message: `OpenAI API error: ${error.message}`,
1504
+ statusCode: error.status,
1386
1505
  cause: error
1387
1506
  })
1388
1507
  });
@@ -1559,11 +1678,13 @@ var GitLabOAuthManager = class {
1559
1678
  }
1560
1679
  };
1561
1680
 
1681
+ // src/version.ts
1682
+ var VERSION = true ? "3.4.0" : "0.0.0-dev";
1683
+
1562
1684
  // src/gitlab-provider.ts
1563
1685
  var fs = __toESM(require("fs"));
1564
1686
  var path = __toESM(require("path"));
1565
1687
  var os = __toESM(require("os"));
1566
- var VERSION = "0.0.1";
1567
1688
  function getOpenCodeAuthPath() {
1568
1689
  const homeDir = os.homedir();
1569
1690
  const xdgDataHome = process.env.XDG_DATA_HOME;
@@ -1713,6 +1834,14 @@ function createGitLab(options = {}) {
1713
1834
  ...options.featureFlags,
1714
1835
  ...agenticOptions?.featureFlags
1715
1836
  };
1837
+ const defaultAiGatewayHeaders = {
1838
+ "User-Agent": `gitlab-ai-provider/${VERSION}`
1839
+ };
1840
+ const aiGatewayHeaders = {
1841
+ ...defaultAiGatewayHeaders,
1842
+ ...options.aiGatewayHeaders,
1843
+ ...agenticOptions?.aiGatewayHeaders
1844
+ };
1716
1845
  const baseConfig = {
1717
1846
  provider: `${providerName}.agentic`,
1718
1847
  instanceUrl,
@@ -1721,7 +1850,8 @@ function createGitLab(options = {}) {
1721
1850
  fetch: options.fetch,
1722
1851
  maxTokens: agenticOptions?.maxTokens,
1723
1852
  featureFlags,
1724
- aiGatewayUrl: options.aiGatewayUrl
1853
+ aiGatewayUrl: options.aiGatewayUrl,
1854
+ aiGatewayHeaders
1725
1855
  };
1726
1856
  if (mapping.provider === "openai") {
1727
1857
  return new GitLabOpenAILanguageModel(modelId, {
@@ -2042,6 +2172,7 @@ var GitLabProjectDetector = class {
2042
2172
  MODEL_MAPPINGS,
2043
2173
  OAUTH_SCOPES,
2044
2174
  TOKEN_EXPIRY_SKEW_MS,
2175
+ VERSION,
2045
2176
  createGitLab,
2046
2177
  getAnthropicModelForModelId,
2047
2178
  getModelMapping,