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