gitlab-ai-provider 5.1.2 → 5.2.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
@@ -1506,7 +1506,7 @@ var GitLabOpenAILanguageModel = class {
1506
1506
  import WebSocket from "isomorphic-ws";
1507
1507
 
1508
1508
  // src/version.ts
1509
- var VERSION = true ? "5.1.1" : "0.0.0-dev";
1509
+ var VERSION = true ? "5.2.0" : "0.0.0-dev";
1510
1510
 
1511
1511
  // src/gitlab-workflow-types.ts
1512
1512
  var WorkflowType = /* @__PURE__ */ ((WorkflowType2) => {
@@ -2675,6 +2675,7 @@ import * as fs from "fs";
2675
2675
  import * as path2 from "path";
2676
2676
  import * as os from "os";
2677
2677
  import * as crypto from "crypto";
2678
+ var DISCOVERY_TTL_MS = 10 * 60 * 1e3;
2678
2679
  function getCacheFilePath() {
2679
2680
  const cacheHome = process.env.XDG_CACHE_HOME || path2.join(os.homedir(), ".cache");
2680
2681
  return path2.join(cacheHome, "opencode", "gitlab-workflow-model-cache.json");
@@ -2724,13 +2725,23 @@ var GitLabModelCache = class {
2724
2725
  data[this.key] = entry;
2725
2726
  this.writeAll(data);
2726
2727
  }
2728
+ /**
2729
+ * Returns true if the discovery data is missing or older than DISCOVERY_TTL_MS.
2730
+ */
2731
+ isDiscoveryExpired() {
2732
+ const entry = this.load();
2733
+ if (!entry?.discovery || !entry.updatedAt) return true;
2734
+ return Date.now() - new Date(entry.updatedAt).getTime() > DISCOVERY_TTL_MS;
2735
+ }
2727
2736
  /**
2728
2737
  * Update only the discovery portion of the cache, preserving selection.
2738
+ * Optionally persists the associated GitLab project.
2729
2739
  */
2730
- saveDiscovery(discovery) {
2740
+ saveDiscovery(discovery, project) {
2731
2741
  const existing = this.load();
2732
2742
  this.save({
2733
2743
  discovery,
2744
+ project: project !== void 0 ? project : existing?.project ?? null,
2734
2745
  selectedModelRef: existing?.selectedModelRef ?? null,
2735
2746
  selectedModelName: existing?.selectedModelName ?? null,
2736
2747
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -2738,13 +2749,22 @@ var GitLabModelCache = class {
2738
2749
  }
2739
2750
  /**
2740
2751
  * Update only the selected model, preserving the discovery data.
2752
+ * If name is null but ref is provided, attempts to resolve the name
2753
+ * from the cached discovery data.
2741
2754
  */
2742
2755
  saveSelection(ref, name) {
2743
2756
  const existing = this.load();
2757
+ let resolved = name;
2758
+ if (!resolved && ref && existing?.discovery) {
2759
+ const d = existing.discovery;
2760
+ const match = d.pinnedModel?.ref === ref ? d.pinnedModel : d.selectableModels.find((m) => m.ref === ref) ?? (d.defaultModel?.ref === ref ? d.defaultModel : null);
2761
+ resolved = match?.name ?? null;
2762
+ }
2744
2763
  this.save({
2745
2764
  discovery: existing?.discovery ?? null,
2765
+ project: existing?.project ?? null,
2746
2766
  selectedModelRef: ref,
2747
- selectedModelName: name,
2767
+ selectedModelName: resolved,
2748
2768
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
2749
2769
  });
2750
2770
  }
@@ -2886,7 +2906,8 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
2886
2906
  */
2887
2907
  set selectedModelRef(ref) {
2888
2908
  this._selectedModelRef = ref ?? void 0;
2889
- this.modelCache.saveSelection(ref, this._selectedModelName ?? null);
2909
+ this._selectedModelName = void 0;
2910
+ this.modelCache.saveSelection(ref, null);
2890
2911
  }
2891
2912
  /**
2892
2913
  * Get the cached selected model display name.
@@ -4423,6 +4444,67 @@ function parseModelsYml(text) {
4423
4444
  }
4424
4445
  return configs;
4425
4446
  }
4447
+
4448
+ // src/gitlab-workflow-discovery.ts
4449
+ var configRegistry = new GitLabModelConfigRegistry();
4450
+ async function buildModels(discovered, project) {
4451
+ const configs = await configRegistry.getConfigs();
4452
+ const refToID = /* @__PURE__ */ new Map();
4453
+ for (const [id, mapping] of Object.entries(MODEL_MAPPINGS)) {
4454
+ if (mapping.provider === "workflow" && id !== "duo-workflow" && id !== "duo-workflow-default") {
4455
+ refToID.set(mapping.model, id);
4456
+ }
4457
+ }
4458
+ const all = discovered.pinnedModel ? [discovered.pinnedModel] : [
4459
+ ...discovered.selectableModels ?? [],
4460
+ ...discovered.defaultModel ? [discovered.defaultModel] : []
4461
+ ];
4462
+ const seen = /* @__PURE__ */ new Set();
4463
+ const models = [];
4464
+ for (const model of all) {
4465
+ if (!model.ref || seen.has(model.ref)) continue;
4466
+ seen.add(model.ref);
4467
+ const id = refToID.get(model.ref) ?? `duo-workflow-${model.ref.replace(/[/_]/g, "-")}`;
4468
+ const limits = configs.get(model.ref);
4469
+ models.push({
4470
+ id,
4471
+ ref: model.ref,
4472
+ name: model.name,
4473
+ context: limits?.context ?? 2e5,
4474
+ output: limits?.output ?? 64e3,
4475
+ pinned: !!discovered.pinnedModel && discovered.pinnedModel.ref === model.ref
4476
+ });
4477
+ }
4478
+ return { models, project };
4479
+ }
4480
+ async function discoverWorkflowModels(config, options) {
4481
+ const cache = new GitLabModelCache(options.workingDirectory, config.instanceUrl);
4482
+ if (!cache.isDiscoveryExpired()) {
4483
+ const entry = cache.load();
4484
+ return buildModels(entry.discovery, entry.project);
4485
+ }
4486
+ const detector = new GitLabProjectDetector({
4487
+ instanceUrl: config.instanceUrl,
4488
+ getHeaders: config.getHeaders,
4489
+ fetch: config.fetch
4490
+ });
4491
+ let project = null;
4492
+ try {
4493
+ project = await detector.detectProject(options.workingDirectory);
4494
+ } catch {
4495
+ return { models: [], project: null };
4496
+ }
4497
+ const namespaceId = project?.namespaceId;
4498
+ if (!namespaceId) return { models: [], project };
4499
+ const discovery = new GitLabModelDiscovery({
4500
+ instanceUrl: config.instanceUrl,
4501
+ getHeaders: config.getHeaders,
4502
+ fetch: config.fetch
4503
+ });
4504
+ const discovered = await discovery.discover(`gid://gitlab/Group/${namespaceId}`);
4505
+ cache.saveDiscovery(discovered, project);
4506
+ return buildModels(discovered, project);
4507
+ }
4426
4508
  export {
4427
4509
  AGENT_PRIVILEGES,
4428
4510
  BUNDLED_CLIENT_ID,
@@ -4456,6 +4538,7 @@ export {
4456
4538
  WS_KEEPALIVE_PING_INTERVAL_MS,
4457
4539
  WorkflowType,
4458
4540
  createGitLab,
4541
+ discoverWorkflowModels,
4459
4542
  getAnthropicModelForModelId,
4460
4543
  getModelMapping,
4461
4544
  getOpenAIApiType,