@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/dist/index.mjs CHANGED
@@ -38,6 +38,17 @@ var GitLabError = class _GitLabError extends Error {
38
38
  isServerError() {
39
39
  return this.statusCode !== void 0 && this.statusCode >= 500;
40
40
  }
41
+ /**
42
+ * Check if this error is a context overflow error (prompt too long).
43
+ * These errors occur when the conversation exceeds the model's token limit.
44
+ */
45
+ isContextOverflowError() {
46
+ if (this.statusCode !== 400) {
47
+ return false;
48
+ }
49
+ const message = this.message?.toLowerCase() || "";
50
+ return message.includes("context overflow") || message.includes("prompt is too long") || message.includes("prompt too long") || message.includes("tokens") && message.includes("maximum");
51
+ }
41
52
  };
42
53
 
43
54
  // src/gitlab-direct-access.ts
@@ -181,11 +192,15 @@ var GitLabAnthropicLanguageModel = class {
181
192
  async getAnthropicClient(forceRefresh = false) {
182
193
  const tokenData = await this.directAccessClient.getDirectAccessToken(forceRefresh);
183
194
  const { "x-api-key": _removed, ...filteredHeaders } = tokenData.headers;
195
+ const mergedHeaders = {
196
+ ...filteredHeaders,
197
+ ...this.config.aiGatewayHeaders
198
+ };
184
199
  this.anthropicClient = new Anthropic({
185
200
  apiKey: null,
186
201
  authToken: tokenData.token,
187
202
  baseURL: this.directAccessClient.getAnthropicProxyUrl(),
188
- defaultHeaders: filteredHeaders
203
+ defaultHeaders: mergedHeaders
189
204
  });
190
205
  return this.anthropicClient;
191
206
  }
@@ -204,6 +219,21 @@ var GitLabAnthropicLanguageModel = class {
204
219
  }
205
220
  return false;
206
221
  }
222
+ /**
223
+ * Check if an error is a context overflow error (prompt too long)
224
+ * These should NOT trigger token refresh and should be reported to the user.
225
+ */
226
+ isContextOverflowError(error) {
227
+ if (error instanceof Anthropic.APIError) {
228
+ if (error.status === 400) {
229
+ const message = error.message?.toLowerCase() || "";
230
+ if (message.includes("prompt is too long") || message.includes("prompt too long") || message.includes("tokens") && message.includes("maximum")) {
231
+ return true;
232
+ }
233
+ }
234
+ }
235
+ return false;
236
+ }
207
237
  /**
208
238
  * Convert AI SDK tools to Anthropic tool format
209
239
  */
@@ -381,6 +411,14 @@ var GitLabAnthropicLanguageModel = class {
381
411
  warnings: []
382
412
  };
383
413
  } catch (error) {
414
+ if (this.isContextOverflowError(error)) {
415
+ const apiError = error;
416
+ throw new GitLabError({
417
+ message: `Context overflow: ${apiError.message}. Please start a new session or use /compact to reduce context.`,
418
+ statusCode: 400,
419
+ cause: error
420
+ });
421
+ }
384
422
  if (!isRetry && this.isTokenError(error)) {
385
423
  this.directAccessClient.invalidateToken();
386
424
  return this.doGenerateWithRetry(options, true);
@@ -388,6 +426,7 @@ var GitLabAnthropicLanguageModel = class {
388
426
  if (error instanceof Anthropic.APIError) {
389
427
  throw new GitLabError({
390
428
  message: `Anthropic API error: ${error.message}`,
429
+ statusCode: error.status,
391
430
  cause: error
392
431
  });
393
432
  }
@@ -568,6 +607,19 @@ var GitLabAnthropicLanguageModel = class {
568
607
  });
569
608
  }
570
609
  }
610
+ if (self.isContextOverflowError(error)) {
611
+ const apiError = error;
612
+ controller.enqueue({
613
+ type: "error",
614
+ error: new GitLabError({
615
+ message: `Context overflow: ${apiError.message}. Please start a new session or use /compact to reduce context.`,
616
+ statusCode: 400,
617
+ cause: error
618
+ })
619
+ });
620
+ controller.close();
621
+ return;
622
+ }
571
623
  if (!isRetry && self.isTokenError(error)) {
572
624
  self.directAccessClient.invalidateToken();
573
625
  controller.enqueue({
@@ -585,6 +637,7 @@ var GitLabAnthropicLanguageModel = class {
585
637
  type: "error",
586
638
  error: new GitLabError({
587
639
  message: `Anthropic API error: ${error.message}`,
640
+ statusCode: error.status,
588
641
  cause: error
589
642
  })
590
643
  });
@@ -686,10 +739,14 @@ var GitLabOpenAILanguageModel = class {
686
739
  async getOpenAIClient(forceRefresh = false) {
687
740
  const tokenData = await this.directAccessClient.getDirectAccessToken(forceRefresh);
688
741
  const { "x-api-key": _removed, ...filteredHeaders } = tokenData.headers;
742
+ const mergedHeaders = {
743
+ ...filteredHeaders,
744
+ ...this.config.aiGatewayHeaders
745
+ };
689
746
  this.openaiClient = new OpenAI({
690
747
  apiKey: tokenData.token,
691
748
  baseURL: this.directAccessClient.getOpenAIProxyUrl(),
692
- defaultHeaders: filteredHeaders
749
+ defaultHeaders: mergedHeaders
693
750
  });
694
751
  return this.openaiClient;
695
752
  }
@@ -705,6 +762,21 @@ var GitLabOpenAILanguageModel = class {
705
762
  }
706
763
  return false;
707
764
  }
765
+ /**
766
+ * Check if an error is a context overflow error (prompt too long)
767
+ * These should NOT trigger token refresh and should be reported to the user.
768
+ */
769
+ isContextOverflowError(error) {
770
+ if (error instanceof OpenAI.APIError) {
771
+ if (error.status === 400) {
772
+ const message = error.message?.toLowerCase() || "";
773
+ if (message.includes("prompt is too long") || message.includes("prompt too long") || message.includes("tokens") && message.includes("maximum")) {
774
+ return true;
775
+ }
776
+ }
777
+ }
778
+ return false;
779
+ }
708
780
  convertTools(tools) {
709
781
  if (!tools || tools.length === 0) {
710
782
  return void 0;
@@ -985,6 +1057,14 @@ var GitLabOpenAILanguageModel = class {
985
1057
  warnings: []
986
1058
  };
987
1059
  } catch (error) {
1060
+ if (this.isContextOverflowError(error)) {
1061
+ const apiError = error;
1062
+ throw new GitLabError({
1063
+ message: `Context overflow: ${apiError.message}. Please start a new session or use /compact to reduce context.`,
1064
+ statusCode: 400,
1065
+ cause: error
1066
+ });
1067
+ }
988
1068
  if (!isRetry && this.isTokenError(error)) {
989
1069
  this.directAccessClient.invalidateToken();
990
1070
  return this.doGenerateWithChatApi(options, true);
@@ -992,6 +1072,7 @@ var GitLabOpenAILanguageModel = class {
992
1072
  if (error instanceof OpenAI.APIError) {
993
1073
  throw new GitLabError({
994
1074
  message: `OpenAI API error: ${error.message}`,
1075
+ statusCode: error.status,
995
1076
  cause: error
996
1077
  });
997
1078
  }
@@ -1047,6 +1128,14 @@ var GitLabOpenAILanguageModel = class {
1047
1128
  warnings: []
1048
1129
  };
1049
1130
  } catch (error) {
1131
+ if (this.isContextOverflowError(error)) {
1132
+ const apiError = error;
1133
+ throw new GitLabError({
1134
+ message: `Context overflow: ${apiError.message}. Please start a new session or use /compact to reduce context.`,
1135
+ statusCode: 400,
1136
+ cause: error
1137
+ });
1138
+ }
1050
1139
  if (!isRetry && this.isTokenError(error)) {
1051
1140
  this.directAccessClient.invalidateToken();
1052
1141
  return this.doGenerateWithResponsesApi(options, true);
@@ -1054,6 +1143,7 @@ var GitLabOpenAILanguageModel = class {
1054
1143
  if (error instanceof OpenAI.APIError) {
1055
1144
  throw new GitLabError({
1056
1145
  message: `OpenAI API error: ${error.message}`,
1146
+ statusCode: error.status,
1057
1147
  cause: error
1058
1148
  });
1059
1149
  }
@@ -1172,6 +1262,19 @@ var GitLabOpenAILanguageModel = class {
1172
1262
  controller.enqueue({ type: "finish", finishReason, usage });
1173
1263
  controller.close();
1174
1264
  } catch (error) {
1265
+ if (self.isContextOverflowError(error)) {
1266
+ const apiError = error;
1267
+ controller.enqueue({
1268
+ type: "error",
1269
+ error: new GitLabError({
1270
+ message: `Context overflow: ${apiError.message}. Please start a new session or use /compact to reduce context.`,
1271
+ statusCode: 400,
1272
+ cause: error
1273
+ })
1274
+ });
1275
+ controller.close();
1276
+ return;
1277
+ }
1175
1278
  if (!isRetry && self.isTokenError(error)) {
1176
1279
  self.directAccessClient.invalidateToken();
1177
1280
  controller.enqueue({
@@ -1186,6 +1289,7 @@ var GitLabOpenAILanguageModel = class {
1186
1289
  type: "error",
1187
1290
  error: new GitLabError({
1188
1291
  message: `OpenAI API error: ${error.message}`,
1292
+ statusCode: error.status,
1189
1293
  cause: error
1190
1294
  })
1191
1295
  });
@@ -1312,6 +1416,19 @@ var GitLabOpenAILanguageModel = class {
1312
1416
  controller.enqueue({ type: "finish", finishReason, usage });
1313
1417
  controller.close();
1314
1418
  } catch (error) {
1419
+ if (self.isContextOverflowError(error)) {
1420
+ const apiError = error;
1421
+ controller.enqueue({
1422
+ type: "error",
1423
+ error: new GitLabError({
1424
+ message: `Context overflow: ${apiError.message}. Please start a new session or use /compact to reduce context.`,
1425
+ statusCode: 400,
1426
+ cause: error
1427
+ })
1428
+ });
1429
+ controller.close();
1430
+ return;
1431
+ }
1315
1432
  if (!isRetry && self.isTokenError(error)) {
1316
1433
  self.directAccessClient.invalidateToken();
1317
1434
  controller.enqueue({
@@ -1326,6 +1443,7 @@ var GitLabOpenAILanguageModel = class {
1326
1443
  type: "error",
1327
1444
  error: new GitLabError({
1328
1445
  message: `OpenAI API error: ${error.message}`,
1446
+ statusCode: error.status,
1329
1447
  cause: error
1330
1448
  })
1331
1449
  });
@@ -1502,11 +1620,13 @@ var GitLabOAuthManager = class {
1502
1620
  }
1503
1621
  };
1504
1622
 
1623
+ // src/version.ts
1624
+ var VERSION = true ? "3.4.0" : "0.0.0-dev";
1625
+
1505
1626
  // src/gitlab-provider.ts
1506
1627
  import * as fs from "fs";
1507
1628
  import * as path from "path";
1508
1629
  import * as os from "os";
1509
- var VERSION = "0.0.1";
1510
1630
  function getOpenCodeAuthPath() {
1511
1631
  const homeDir = os.homedir();
1512
1632
  const xdgDataHome = process.env.XDG_DATA_HOME;
@@ -1656,6 +1776,14 @@ function createGitLab(options = {}) {
1656
1776
  ...options.featureFlags,
1657
1777
  ...agenticOptions?.featureFlags
1658
1778
  };
1779
+ const defaultAiGatewayHeaders = {
1780
+ "User-Agent": `gitlab-ai-provider/${VERSION}`
1781
+ };
1782
+ const aiGatewayHeaders = {
1783
+ ...defaultAiGatewayHeaders,
1784
+ ...options.aiGatewayHeaders,
1785
+ ...agenticOptions?.aiGatewayHeaders
1786
+ };
1659
1787
  const baseConfig = {
1660
1788
  provider: `${providerName}.agentic`,
1661
1789
  instanceUrl,
@@ -1664,7 +1792,8 @@ function createGitLab(options = {}) {
1664
1792
  fetch: options.fetch,
1665
1793
  maxTokens: agenticOptions?.maxTokens,
1666
1794
  featureFlags,
1667
- aiGatewayUrl: options.aiGatewayUrl
1795
+ aiGatewayUrl: options.aiGatewayUrl,
1796
+ aiGatewayHeaders
1668
1797
  };
1669
1798
  if (mapping.provider === "openai") {
1670
1799
  return new GitLabOpenAILanguageModel(modelId, {
@@ -1984,6 +2113,7 @@ export {
1984
2113
  MODEL_MAPPINGS,
1985
2114
  OAUTH_SCOPES,
1986
2115
  TOKEN_EXPIRY_SKEW_MS,
2116
+ VERSION,
1987
2117
  createGitLab,
1988
2118
  getAnthropicModelForModelId,
1989
2119
  getModelMapping,