gitlab-ai-provider 6.15.0 → 6.15.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 +5 -0
- package/README.md +13 -3
- package/dist/gitlab-ai-provider-6.15.1.tgz +0 -0
- package/dist/index.d.mts +40 -13
- package/dist/index.d.ts +40 -13
- package/dist/index.js +86 -31
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +86 -31
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/gitlab-ai-provider-6.15.0.tgz +0 -0
package/dist/index.mjs
CHANGED
|
@@ -1583,14 +1583,14 @@ var MODEL_MAPPINGS = {
|
|
|
1583
1583
|
"duo-workflow-default": { provider: "workflow", model: "default" },
|
|
1584
1584
|
"duo-workflow-sonnet-4-5": {
|
|
1585
1585
|
provider: "workflow",
|
|
1586
|
-
model: "
|
|
1586
|
+
model: "claude_sonnet_4_5_20250929"
|
|
1587
1587
|
},
|
|
1588
1588
|
"duo-workflow-sonnet-5": { provider: "workflow", model: "claude_sonnet_5" },
|
|
1589
1589
|
"duo-workflow-opus-5": { provider: "workflow", model: "claude_opus_5" },
|
|
1590
1590
|
"duo-workflow-sonnet-4-6": { provider: "workflow", model: "claude_sonnet_4_6" },
|
|
1591
1591
|
"duo-workflow-opus-4-5": {
|
|
1592
1592
|
provider: "workflow",
|
|
1593
|
-
model: "
|
|
1593
|
+
model: "claude_opus_4_5_20251101"
|
|
1594
1594
|
},
|
|
1595
1595
|
"duo-workflow-haiku-4-5": { provider: "workflow", model: "claude_haiku_4_5_20251001" },
|
|
1596
1596
|
"duo-workflow-opus-4-6": { provider: "workflow", model: "claude_opus_4_6_20260205" }
|
|
@@ -2692,7 +2692,7 @@ import { AsyncResource } from "async_hooks";
|
|
|
2692
2692
|
import WebSocket from "isomorphic-ws";
|
|
2693
2693
|
|
|
2694
2694
|
// src/version.ts
|
|
2695
|
-
var VERSION = true ? "6.
|
|
2695
|
+
var VERSION = true ? "6.15.0" : "0.0.0-dev";
|
|
2696
2696
|
|
|
2697
2697
|
// src/gitlab-workflow-client.ts
|
|
2698
2698
|
var WS_CONNECT_TIMEOUT_MS = 3e4;
|
|
@@ -3412,8 +3412,14 @@ var GitLabProjectDetector = class {
|
|
|
3412
3412
|
};
|
|
3413
3413
|
|
|
3414
3414
|
// src/gitlab-model-discovery.ts
|
|
3415
|
+
function scopeCacheKey(scope) {
|
|
3416
|
+
return "projectId" in scope ? `p:${scope.projectId}` : `n:${scope.rootNamespaceId}`;
|
|
3417
|
+
}
|
|
3418
|
+
function normalizeScope(scope) {
|
|
3419
|
+
return typeof scope === "string" ? { rootNamespaceId: scope } : scope;
|
|
3420
|
+
}
|
|
3415
3421
|
var AI_CHAT_AVAILABLE_MODELS_QUERY = `
|
|
3416
|
-
query aiChatAvailableModels($rootNamespaceId: GroupID
|
|
3422
|
+
query aiChatAvailableModels($projectId: ProjectID, $rootNamespaceId: GroupID) {
|
|
3417
3423
|
metadata {
|
|
3418
3424
|
featureFlags(names: ["ai_user_model_switching"]) {
|
|
3419
3425
|
enabled
|
|
@@ -3422,7 +3428,7 @@ var AI_CHAT_AVAILABLE_MODELS_QUERY = `
|
|
|
3422
3428
|
version
|
|
3423
3429
|
}
|
|
3424
3430
|
|
|
3425
|
-
aiChatAvailableModels(rootNamespaceId: $rootNamespaceId) {
|
|
3431
|
+
aiChatAvailableModels(projectId: $projectId, rootNamespaceId: $rootNamespaceId) {
|
|
3426
3432
|
defaultModel {
|
|
3427
3433
|
name
|
|
3428
3434
|
ref
|
|
@@ -3448,18 +3454,42 @@ var GitLabModelDiscovery = class {
|
|
|
3448
3454
|
this.fetchFn = config.fetch ?? fetch;
|
|
3449
3455
|
}
|
|
3450
3456
|
/**
|
|
3451
|
-
* Discover available models for a given root namespace.
|
|
3457
|
+
* Discover available models for a given project or root namespace.
|
|
3452
3458
|
*
|
|
3453
|
-
* Results are cached per
|
|
3459
|
+
* Results are cached per scope with a 10-minute TTL.
|
|
3454
3460
|
* Use `invalidateCache()` to force an immediate refresh.
|
|
3455
3461
|
*
|
|
3456
|
-
* @param
|
|
3462
|
+
* @param scope - `{ projectId }` (preferred), `{ rootNamespaceId }`, or a
|
|
3463
|
+
* bare string (treated as `rootNamespaceId` for backwards compatibility)
|
|
3457
3464
|
*/
|
|
3458
|
-
async discover(
|
|
3459
|
-
const
|
|
3465
|
+
async discover(scope) {
|
|
3466
|
+
const normalized = normalizeScope(scope);
|
|
3467
|
+
const cacheKey = scopeCacheKey(normalized);
|
|
3468
|
+
const cached = this.cache.get(cacheKey);
|
|
3460
3469
|
if (cached && cached.expiresAt > Date.now()) {
|
|
3461
3470
|
return cached.data;
|
|
3462
3471
|
}
|
|
3472
|
+
try {
|
|
3473
|
+
const result = await this.query(normalized);
|
|
3474
|
+
this.cache.set(cacheKey, {
|
|
3475
|
+
data: result,
|
|
3476
|
+
expiresAt: Date.now() + DISCOVERY_CACHE_TTL_MS
|
|
3477
|
+
});
|
|
3478
|
+
return result;
|
|
3479
|
+
} catch (error) {
|
|
3480
|
+
if ("projectId" in normalized && normalized.rootNamespaceId) {
|
|
3481
|
+
const fallbackScope = { rootNamespaceId: normalized.rootNamespaceId };
|
|
3482
|
+
const result = await this.query(fallbackScope);
|
|
3483
|
+
this.cache.set(scopeCacheKey(fallbackScope), {
|
|
3484
|
+
data: result,
|
|
3485
|
+
expiresAt: Date.now() + DISCOVERY_CACHE_TTL_MS
|
|
3486
|
+
});
|
|
3487
|
+
return result;
|
|
3488
|
+
}
|
|
3489
|
+
throw error;
|
|
3490
|
+
}
|
|
3491
|
+
}
|
|
3492
|
+
async query(scope) {
|
|
3463
3493
|
const url = `${this.config.instanceUrl}/api/graphql`;
|
|
3464
3494
|
try {
|
|
3465
3495
|
const response = await this.fetchFn(url, {
|
|
@@ -3470,7 +3500,7 @@ var GitLabModelDiscovery = class {
|
|
|
3470
3500
|
},
|
|
3471
3501
|
body: JSON.stringify({
|
|
3472
3502
|
query: AI_CHAT_AVAILABLE_MODELS_QUERY,
|
|
3473
|
-
variables: { rootNamespaceId }
|
|
3503
|
+
variables: "projectId" in scope ? { projectId: scope.projectId, rootNamespaceId: void 0 } : { projectId: void 0, rootNamespaceId: scope.rootNamespaceId }
|
|
3474
3504
|
})
|
|
3475
3505
|
});
|
|
3476
3506
|
if (!response.ok) {
|
|
@@ -3489,19 +3519,15 @@ var GitLabModelDiscovery = class {
|
|
|
3489
3519
|
}
|
|
3490
3520
|
const models = json.data?.aiChatAvailableModels;
|
|
3491
3521
|
const metadata = json.data?.metadata;
|
|
3492
|
-
const
|
|
3493
|
-
const
|
|
3522
|
+
const flag = metadata?.featureFlags?.find((f) => f.name === "ai_user_model_switching");
|
|
3523
|
+
const modelSwitchingEnabled = flag ? flag.enabled : true;
|
|
3524
|
+
return {
|
|
3494
3525
|
defaultModel: models?.defaultModel ?? null,
|
|
3495
3526
|
selectableModels: models?.selectableModels ?? [],
|
|
3496
3527
|
pinnedModel: models?.pinnedModel ?? null,
|
|
3497
3528
|
modelSwitchingEnabled,
|
|
3498
3529
|
instanceVersion: metadata?.version ?? null
|
|
3499
3530
|
};
|
|
3500
|
-
this.cache.set(rootNamespaceId, {
|
|
3501
|
-
data: result,
|
|
3502
|
-
expiresAt: Date.now() + DISCOVERY_CACHE_TTL_MS
|
|
3503
|
-
});
|
|
3504
|
-
return result;
|
|
3505
3531
|
} catch (error) {
|
|
3506
3532
|
if (error instanceof GitLabError) throw error;
|
|
3507
3533
|
throw new GitLabError({
|
|
@@ -3515,11 +3541,11 @@ var GitLabModelDiscovery = class {
|
|
|
3515
3541
|
*
|
|
3516
3542
|
* Priority: pinned > user-selected > default.
|
|
3517
3543
|
*
|
|
3518
|
-
* @param
|
|
3544
|
+
* @param scope - Project or root namespace to discover models for
|
|
3519
3545
|
* @param userSelectedRef - Optional user preference
|
|
3520
3546
|
*/
|
|
3521
|
-
async getEffectiveModelRef(
|
|
3522
|
-
const discovered = await this.discover(
|
|
3547
|
+
async getEffectiveModelRef(scope, userSelectedRef) {
|
|
3548
|
+
const discovered = await this.discover(scope);
|
|
3523
3549
|
if (discovered.pinnedModel) {
|
|
3524
3550
|
return discovered.pinnedModel.ref;
|
|
3525
3551
|
}
|
|
@@ -3966,6 +3992,25 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3966
3992
|
this._rootNamespaceId = null;
|
|
3967
3993
|
return null;
|
|
3968
3994
|
}
|
|
3995
|
+
/**
|
|
3996
|
+
* Resolve the model discovery scope to use for `aiChatAvailableModels`.
|
|
3997
|
+
*
|
|
3998
|
+
* `projectId` is preferred — it works for both group- and user-namespace
|
|
3999
|
+
* projects — with `rootNamespaceId` attached as a fallback for GitLab
|
|
4000
|
+
* instances too old to support `projectId`-scoped discovery.
|
|
4001
|
+
*/
|
|
4002
|
+
async resolveDiscoveryScope() {
|
|
4003
|
+
const rootNamespaceId = await this.resolveRootNamespaceId();
|
|
4004
|
+
const workDir = this.workflowOptions.workingDirectory ?? process.cwd();
|
|
4005
|
+
const project = await this.projectDetector.detectProject(workDir);
|
|
4006
|
+
if (project?.id) {
|
|
4007
|
+
return {
|
|
4008
|
+
projectId: `gid://gitlab/Project/${project.id}`,
|
|
4009
|
+
...rootNamespaceId ? { rootNamespaceId } : {}
|
|
4010
|
+
};
|
|
4011
|
+
}
|
|
4012
|
+
return rootNamespaceId ? { rootNamespaceId } : null;
|
|
4013
|
+
}
|
|
3969
4014
|
/**
|
|
3970
4015
|
* Resolve the effective DWS model ref to use for this stream.
|
|
3971
4016
|
* Deduplicates concurrent calls via a shared promise.
|
|
@@ -3996,13 +4041,13 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3996
4041
|
return this._discoveryPromise;
|
|
3997
4042
|
}
|
|
3998
4043
|
async doResolveModelRef() {
|
|
3999
|
-
const
|
|
4000
|
-
if (!
|
|
4044
|
+
const scope = await this.resolveDiscoveryScope();
|
|
4045
|
+
if (!scope) {
|
|
4001
4046
|
this._selectedModelRef = "default";
|
|
4002
4047
|
return "default";
|
|
4003
4048
|
}
|
|
4004
4049
|
try {
|
|
4005
|
-
const discovered = await this.modelDiscovery.discover(
|
|
4050
|
+
const discovered = await this.modelDiscovery.discover(scope);
|
|
4006
4051
|
this.modelCache.saveDiscovery(discovered);
|
|
4007
4052
|
if (discovered.pinnedModel) {
|
|
4008
4053
|
this._selectedModelRef = discovered.pinnedModel.ref;
|
|
@@ -4045,11 +4090,13 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
4045
4090
|
* Call this early (e.g., on IDE startup) to avoid blocking the first stream.
|
|
4046
4091
|
* Results are persisted to the workspace model cache.
|
|
4047
4092
|
*
|
|
4048
|
-
* @param
|
|
4093
|
+
* @param scope - Project or root namespace GID to discover models for.
|
|
4094
|
+
* A bare string is treated as a `rootNamespaceId` (e.g.
|
|
4095
|
+
* 'gid://gitlab/Group/12345') for backwards compatibility.
|
|
4049
4096
|
* @returns Discovered models with default, selectable, and pinned models
|
|
4050
4097
|
*/
|
|
4051
|
-
async discoverModels(
|
|
4052
|
-
const result = await this.modelDiscovery.discover(
|
|
4098
|
+
async discoverModels(scope) {
|
|
4099
|
+
const result = await this.modelDiscovery.discover(scope);
|
|
4053
4100
|
this.modelCache.saveDiscovery(result);
|
|
4054
4101
|
return result;
|
|
4055
4102
|
}
|
|
@@ -5791,7 +5838,7 @@ async function buildModels(discovered, project) {
|
|
|
5791
5838
|
for (const model of all) {
|
|
5792
5839
|
if (!model.ref || seen.has(model.ref)) continue;
|
|
5793
5840
|
seen.add(model.ref);
|
|
5794
|
-
const id = refToID.get(model.ref) ?? `duo-workflow-${model.ref.replace(/[/_]/g, "-")}
|
|
5841
|
+
const id = refToID.get(model.ref) ?? (model.ref.startsWith("__default__") ? "duo-workflow-default" : `duo-workflow-${model.ref.replace(/[/_]/g, "-")}`);
|
|
5795
5842
|
const limits = configs.get(model.ref);
|
|
5796
5843
|
models.push({
|
|
5797
5844
|
id,
|
|
@@ -5823,14 +5870,22 @@ async function discoverWorkflowModels(config, options) {
|
|
|
5823
5870
|
} catch {
|
|
5824
5871
|
return { models: [], project: null };
|
|
5825
5872
|
}
|
|
5826
|
-
|
|
5827
|
-
|
|
5873
|
+
if (!project?.id) return { models: [], project };
|
|
5874
|
+
const scope = {
|
|
5875
|
+
projectId: `gid://gitlab/Project/${project.id}`,
|
|
5876
|
+
...project.namespaceId ? { rootNamespaceId: `gid://gitlab/Group/${project.namespaceId}` } : {}
|
|
5877
|
+
};
|
|
5828
5878
|
const discovery = new GitLabModelDiscovery({
|
|
5829
5879
|
instanceUrl: config.instanceUrl,
|
|
5830
5880
|
getHeaders: config.getHeaders,
|
|
5831
5881
|
fetch: config.fetch
|
|
5832
5882
|
});
|
|
5833
|
-
|
|
5883
|
+
let discovered;
|
|
5884
|
+
try {
|
|
5885
|
+
discovered = await discovery.discover(scope);
|
|
5886
|
+
} catch {
|
|
5887
|
+
return { models: [], project };
|
|
5888
|
+
}
|
|
5834
5889
|
cache.saveDiscovery(discovered, project);
|
|
5835
5890
|
if (!cache.getSelectedModelRef()) {
|
|
5836
5891
|
const pick = discovered.pinnedModel ?? discovered.defaultModel;
|