@gitlab/gitlab-ai-provider 3.4.1 → 3.5.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,16 @@
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.5.1 (2026-02-16)</small>
6
+
7
+ - Merge branch 'vg/token-refresh' into 'main' ([38295cf](https://gitlab.com/gitlab-org/editor-extensions/gitlab-ai-provider/commit/38295cf))
8
+ - fix: resolve mid-session OAuth token refresh failures ([b495153](https://gitlab.com/gitlab-org/editor-extensions/gitlab-ai-provider/commit/b495153))
9
+
10
+ ## 3.5.0 (2026-02-06)
11
+
12
+ - Merge branch 'feat/add-opus-4-6' into 'main' ([b776bd7](https://gitlab.com/gitlab-org/editor-extensions/gitlab-ai-provider/commit/b776bd7))
13
+ - feat(models): add Claude Opus 4.6 model support ([e221e45](https://gitlab.com/gitlab-org/editor-extensions/gitlab-ai-provider/commit/e221e45))
14
+
5
15
  ## <small>3.4.1 (2026-02-06)</small>
6
16
 
7
17
  - Merge branch 'vg/token_refresh_fix' into 'main' ([8c1f2c4](https://gitlab.com/gitlab-org/editor-extensions/gitlab-ai-provider/commit/8c1f2c4))
package/dist/index.d.mts CHANGED
@@ -392,7 +392,10 @@ interface OpenCodeAuthOAuth {
392
392
  refresh: string;
393
393
  access: string;
394
394
  expires: number;
395
+ /** @deprecated Use enterpriseUrl instead. Kept for backwards compatibility with older auth.json files. */
395
396
  instanceUrl?: string;
397
+ /** Instance URL as written by opencode-gitlab-auth plugin (e.g. 'https://gitlab.com') */
398
+ enterpriseUrl?: string;
396
399
  }
397
400
  interface OpenCodeAuthApi {
398
401
  type: 'api';
@@ -400,8 +403,16 @@ interface OpenCodeAuthApi {
400
403
  }
401
404
  type OpenCodeAuth = OpenCodeAuthOAuth | OpenCodeAuthApi;
402
405
  /**
403
- * Bundled OAuth client ID for GitLab.com
404
- * Same as used in gitlab-vscode-extension
406
+ * Default OAuth client ID for GitLab.com
407
+ * This is the same client ID used by opencode-gitlab-auth plugin.
408
+ * The GITLAB_OAUTH_CLIENT_ID env var takes precedence if set.
409
+ * Note: VS Code extension uses a different client ID ('36f2a70c...') but we use the opencode plugin's ID
410
+ * to ensure token refresh works correctly with tokens created by the auth plugin.
411
+ */
412
+ declare const OPENCODE_GITLAB_AUTH_CLIENT_ID = "1d89f9fdb23ee96d4e603201f6861dab6e143c5c3c00469a018a2d94bdc03d4e";
413
+ /**
414
+ * @deprecated Use OPENCODE_GITLAB_AUTH_CLIENT_ID instead. This is the VS Code extension's client ID
415
+ * and will cause refresh failures if used with tokens created by opencode-gitlab-auth.
405
416
  */
406
417
  declare const BUNDLED_CLIENT_ID = "36f2a70cddeb5a0889d4fd8295c241b7e9848e89cf9e599d0eed2d8e5350fbf5";
407
418
  /**
@@ -463,7 +474,10 @@ declare class GitLabOAuthManager {
463
474
  */
464
475
  exchangeRefreshToken(params: RefreshTokenParams): Promise<GitLabOAuthTokens>;
465
476
  /**
466
- * Get the OAuth client ID for an instance
477
+ * Get the OAuth client ID for an instance.
478
+ * Priority: env var > opencode-gitlab-auth default (for GitLab.com).
479
+ * Note: callers (e.g. exchangeRefreshToken) may pass an explicit clientId
480
+ * that bypasses this method entirely.
467
481
  */
468
482
  private getClientId;
469
483
  /**
@@ -680,4 +694,4 @@ declare class GitLabDirectAccessClient {
680
694
  invalidateToken(): void;
681
695
  }
682
696
 
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 };
697
+ 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, OPENCODE_GITLAB_AUTH_CLIENT_ID, 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
@@ -392,7 +392,10 @@ interface OpenCodeAuthOAuth {
392
392
  refresh: string;
393
393
  access: string;
394
394
  expires: number;
395
+ /** @deprecated Use enterpriseUrl instead. Kept for backwards compatibility with older auth.json files. */
395
396
  instanceUrl?: string;
397
+ /** Instance URL as written by opencode-gitlab-auth plugin (e.g. 'https://gitlab.com') */
398
+ enterpriseUrl?: string;
396
399
  }
397
400
  interface OpenCodeAuthApi {
398
401
  type: 'api';
@@ -400,8 +403,16 @@ interface OpenCodeAuthApi {
400
403
  }
401
404
  type OpenCodeAuth = OpenCodeAuthOAuth | OpenCodeAuthApi;
402
405
  /**
403
- * Bundled OAuth client ID for GitLab.com
404
- * Same as used in gitlab-vscode-extension
406
+ * Default OAuth client ID for GitLab.com
407
+ * This is the same client ID used by opencode-gitlab-auth plugin.
408
+ * The GITLAB_OAUTH_CLIENT_ID env var takes precedence if set.
409
+ * Note: VS Code extension uses a different client ID ('36f2a70c...') but we use the opencode plugin's ID
410
+ * to ensure token refresh works correctly with tokens created by the auth plugin.
411
+ */
412
+ declare const OPENCODE_GITLAB_AUTH_CLIENT_ID = "1d89f9fdb23ee96d4e603201f6861dab6e143c5c3c00469a018a2d94bdc03d4e";
413
+ /**
414
+ * @deprecated Use OPENCODE_GITLAB_AUTH_CLIENT_ID instead. This is the VS Code extension's client ID
415
+ * and will cause refresh failures if used with tokens created by opencode-gitlab-auth.
405
416
  */
406
417
  declare const BUNDLED_CLIENT_ID = "36f2a70cddeb5a0889d4fd8295c241b7e9848e89cf9e599d0eed2d8e5350fbf5";
407
418
  /**
@@ -463,7 +474,10 @@ declare class GitLabOAuthManager {
463
474
  */
464
475
  exchangeRefreshToken(params: RefreshTokenParams): Promise<GitLabOAuthTokens>;
465
476
  /**
466
- * Get the OAuth client ID for an instance
477
+ * Get the OAuth client ID for an instance.
478
+ * Priority: env var > opencode-gitlab-auth default (for GitLab.com).
479
+ * Note: callers (e.g. exchangeRefreshToken) may pass an explicit clientId
480
+ * that bypasses this method entirely.
467
481
  */
468
482
  private getClientId;
469
483
  /**
@@ -680,4 +694,4 @@ declare class GitLabDirectAccessClient {
680
694
  invalidateToken(): void;
681
695
  }
682
696
 
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 };
697
+ 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, OPENCODE_GITLAB_AUTH_CLIENT_ID, 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
@@ -42,6 +42,7 @@ __export(index_exports, {
42
42
  MODEL_ID_TO_ANTHROPIC_MODEL: () => MODEL_ID_TO_ANTHROPIC_MODEL,
43
43
  MODEL_MAPPINGS: () => MODEL_MAPPINGS,
44
44
  OAUTH_SCOPES: () => OAUTH_SCOPES,
45
+ OPENCODE_GITLAB_AUTH_CLIENT_ID: () => OPENCODE_GITLAB_AUTH_CLIENT_ID,
45
46
  TOKEN_EXPIRY_SKEW_MS: () => TOKEN_EXPIRY_SKEW_MS,
46
47
  VERSION: () => VERSION,
47
48
  createGitLab: () => createGitLab,
@@ -722,6 +723,7 @@ var import_openai = __toESM(require("openai"));
722
723
  // src/model-mappings.ts
723
724
  var MODEL_MAPPINGS = {
724
725
  // Anthropic models
726
+ "duo-chat-opus-4-6": { provider: "anthropic", model: "claude-opus-4-6" },
725
727
  "duo-chat-opus-4-5": { provider: "anthropic", model: "claude-opus-4-5-20251101" },
726
728
  "duo-chat-sonnet-4-5": { provider: "anthropic", model: "claude-sonnet-4-5-20250929" },
727
729
  "duo-chat-haiku-4-5": { provider: "anthropic", model: "claude-haiku-4-5-20251001" },
@@ -1517,6 +1519,7 @@ var GitLabOpenAILanguageModel = class {
1517
1519
  };
1518
1520
 
1519
1521
  // src/gitlab-oauth-types.ts
1522
+ var OPENCODE_GITLAB_AUTH_CLIENT_ID = "1d89f9fdb23ee96d4e603201f6861dab6e143c5c3c00469a018a2d94bdc03d4e";
1520
1523
  var BUNDLED_CLIENT_ID = "36f2a70cddeb5a0889d4fd8295c241b7e9848e89cf9e599d0eed2d8e5350fbf5";
1521
1524
  var GITLAB_COM_URL = "https://gitlab.com";
1522
1525
  var TOKEN_EXPIRY_SKEW_MS = 5 * 60 * 1e3;
@@ -1590,14 +1593,21 @@ var GitLabOAuthManager = class {
1590
1593
  return this.createTokensFromResponse(tokenResponse, instanceUrl);
1591
1594
  }
1592
1595
  /**
1593
- * Get the OAuth client ID for an instance
1596
+ * Get the OAuth client ID for an instance.
1597
+ * Priority: env var > opencode-gitlab-auth default (for GitLab.com).
1598
+ * Note: callers (e.g. exchangeRefreshToken) may pass an explicit clientId
1599
+ * that bypasses this method entirely.
1594
1600
  */
1595
1601
  getClientId(instanceUrl) {
1602
+ const envClientId = process.env["GITLAB_OAUTH_CLIENT_ID"];
1603
+ if (envClientId) {
1604
+ return envClientId;
1605
+ }
1596
1606
  if (instanceUrl === GITLAB_COM_URL) {
1597
- return BUNDLED_CLIENT_ID;
1607
+ return OPENCODE_GITLAB_AUTH_CLIENT_ID;
1598
1608
  }
1599
1609
  throw new GitLabError({
1600
- message: `No OAuth client ID configured for instance ${instanceUrl}. Please provide a clientId parameter.`
1610
+ message: `No OAuth client ID configured for instance ${instanceUrl}. Please provide a clientId parameter or set GITLAB_OAUTH_CLIENT_ID environment variable.`
1601
1611
  });
1602
1612
  }
1603
1613
  /**
@@ -1679,7 +1689,7 @@ var GitLabOAuthManager = class {
1679
1689
  };
1680
1690
 
1681
1691
  // src/version.ts
1682
- var VERSION = true ? "3.4.0" : "0.0.0-dev";
1692
+ var VERSION = true ? "3.5.0" : "0.0.0-dev";
1683
1693
 
1684
1694
  // src/gitlab-provider.ts
1685
1695
  var fs = __toESM(require("fs"));
@@ -1732,20 +1742,26 @@ async function loadApiKey(options, instanceUrl, clientId) {
1732
1742
  });
1733
1743
  const authPath = getOpenCodeAuthPath();
1734
1744
  const authData = JSON.parse(fs.readFileSync(authPath, "utf-8"));
1735
- const normalizedUrl = instanceUrl.replace(/\/$/, "");
1736
- authData[normalizedUrl] = {
1745
+ authData.gitlab = {
1737
1746
  type: "oauth",
1738
1747
  refresh: refreshed.refreshToken,
1739
1748
  access: refreshed.accessToken,
1740
1749
  expires: refreshed.expiresAt,
1741
- instanceUrl
1750
+ enterpriseUrl: instanceUrl
1751
+ // Use enterpriseUrl to match auth plugin format
1742
1752
  };
1743
- fs.writeFileSync(authPath, JSON.stringify(authData, null, 2));
1753
+ fs.writeFileSync(authPath, JSON.stringify(authData, null, 2), { mode: 384 });
1744
1754
  return refreshed.accessToken;
1745
1755
  } catch (error) {
1746
- console.warn(
1747
- `Failed to refresh OAuth token: ${error instanceof Error ? error.message : String(error)}`
1748
- );
1756
+ const refreshErrorMsg = error instanceof Error ? error.message : String(error);
1757
+ console.warn(`Failed to refresh OAuth token: ${refreshErrorMsg}`);
1758
+ const envApiKey = process.env[options.environmentVariableName];
1759
+ if (envApiKey) {
1760
+ return envApiKey;
1761
+ }
1762
+ throw new GitLabError({
1763
+ message: `OAuth token refresh failed and no fallback ${options.environmentVariableName} environment variable is set. Refresh error: ${refreshErrorMsg}. Re-authenticate with 'opencode auth login gitlab' or set ${options.environmentVariableName}.`
1764
+ });
1749
1765
  }
1750
1766
  } else {
1751
1767
  return auth.access;
@@ -1794,7 +1810,16 @@ function createGitLab(options = {}) {
1794
1810
  const refreshApiKey = async () => {
1795
1811
  cachedApiKey = void 0;
1796
1812
  apiKeyPromise = void 0;
1797
- cachedApiKey = await getApiKey();
1813
+ cachedApiKey = await loadApiKey(
1814
+ {
1815
+ apiKey: void 0,
1816
+ // Bypass stale options.apiKey to force auth.json read
1817
+ environmentVariableName: "GITLAB_TOKEN",
1818
+ description: "GitLab"
1819
+ },
1820
+ instanceUrl,
1821
+ options.clientId
1822
+ );
1798
1823
  };
1799
1824
  const getHeaders = () => {
1800
1825
  const apiKey = cachedApiKey || options.apiKey || process.env["GITLAB_TOKEN"] || "";
@@ -2171,6 +2196,7 @@ var GitLabProjectDetector = class {
2171
2196
  MODEL_ID_TO_ANTHROPIC_MODEL,
2172
2197
  MODEL_MAPPINGS,
2173
2198
  OAUTH_SCOPES,
2199
+ OPENCODE_GITLAB_AUTH_CLIENT_ID,
2174
2200
  TOKEN_EXPIRY_SKEW_MS,
2175
2201
  VERSION,
2176
2202
  createGitLab,