gitlab-ai-provider 6.4.0 → 6.4.2
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 +8 -0
- package/README.md +33 -0
- package/dist/gitlab-ai-provider-6.4.2.tgz +0 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +54 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +54 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/gitlab-ai-provider-6.4.0.tgz +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
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>6.4.2 (2026-04-09)</small>
|
|
6
|
+
|
|
7
|
+
- fix: prevent auto-generated flowConfig from breaking DWS flow resolution ([e653dfc](https://gitlab.com/vglafirov/gitlab-ai-provider/commit/e653dfc))
|
|
8
|
+
|
|
9
|
+
## <small>6.4.1 (2026-04-06)</small>
|
|
10
|
+
|
|
11
|
+
- fix(workflow): surface server-side MCP tool calls as structured AI SDK events ([fcae357](https://gitlab.com/vglafirov/gitlab-ai-provider/commit/fcae357))
|
|
12
|
+
|
|
5
13
|
## 6.4.0 (2026-04-02)
|
|
6
14
|
|
|
7
15
|
- chore: regenerate dist ([c6833c4](https://gitlab.com/vglafirov/gitlab-ai-provider/commit/c6833c4))
|
package/README.md
CHANGED
|
@@ -334,6 +334,37 @@ The workflow service automatically maps DWS built-in tools to consumer tool name
|
|
|
334
334
|
| `mkdir` | `bash` | Create directory |
|
|
335
335
|
| `runHTTPRequest` | `bash` | Execute HTTP request |
|
|
336
336
|
|
|
337
|
+
**Server-Side Tool Visibility:**
|
|
338
|
+
|
|
339
|
+
When DWS executes tools on the server (e.g., MCP tools like Linear or Context7 that are configured in the agent's catalog), the provider automatically surfaces these as structured AI SDK stream events (`tool-input-start`, `tool-call`, `tool-result`) with `providerExecuted: true` and `dynamic: true`. This allows host applications to display server-side tool calls in their UI alongside locally-executed tools.
|
|
340
|
+
|
|
341
|
+
Server-side tool events are deduplicated across turns — the provider tracks emitted checkpoint tool entries in the persistent session state so that cumulative DWS checkpoints don't re-emit tools from previous turns. Tools that were already handled via `tool-request` (client-executed tools) are also excluded from checkpoint emission to avoid duplicates.
|
|
342
|
+
|
|
343
|
+
Since server-side MCP tools are not registered in the host's tool registry, the `dynamic: true` flag ensures the AI SDK's `parseToolCall` bypasses tool registry validation via the `parseProviderExecutedDynamicToolCall` path.
|
|
344
|
+
|
|
345
|
+
**Tool Call Approval:**
|
|
346
|
+
|
|
347
|
+
The workflow model supports an approval flow for tool execution. When DWS requires approval before executing a tool, it sends a `TOOL_CALL_APPROVAL_REQUIRED` checkpoint. The provider exposes this via the `approvalHandler` callback:
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
const model = gitlab.workflowChat('duo-workflow');
|
|
351
|
+
|
|
352
|
+
// Set approval handler — called when DWS requests tool execution approval
|
|
353
|
+
model.approvalHandler = async (tools) => {
|
|
354
|
+
// tools: Array<{ name: string, args: string }>
|
|
355
|
+
console.log(
|
|
356
|
+
'Approval requested for:',
|
|
357
|
+
tools.map((t) => t.name)
|
|
358
|
+
);
|
|
359
|
+
return { approved: true }; // or { approved: false }
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
// Pre-approve specific tools to skip approval prompts
|
|
363
|
+
model.sessionPreapprovedTools = ['read', 'glob', 'grep'];
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
Approved tools are tracked per-session. When the user approves a tool via "allow always", the provider automatically pre-approves it on subsequent DWS reconnections within the same session.
|
|
367
|
+
|
|
337
368
|
**Workflow Options:**
|
|
338
369
|
|
|
339
370
|
```typescript
|
|
@@ -499,6 +530,8 @@ Provides server-side agentic execution through GitLab Duo Workflow Service.
|
|
|
499
530
|
- Dynamic model discovery via GraphQL (`aiChatAvailableModels`)
|
|
500
531
|
- Automatic model selection (pinned → user-selected → default)
|
|
501
532
|
- Built-in tool mapping and MCP tool support
|
|
533
|
+
- Server-side tool visibility — DWS-executed MCP tools are surfaced as structured AI SDK events
|
|
534
|
+
- Tool call approval flow with per-session pre-approval tracking
|
|
502
535
|
- Per-stream state isolation for concurrent requests
|
|
503
536
|
- Dual heartbeat (WebSocket ping + JSON heartbeat)
|
|
504
537
|
|
|
Binary file
|
package/dist/index.d.mts
CHANGED
|
@@ -649,7 +649,7 @@ declare const DEFAULT_WORKFLOW_DEFINITION = WorkflowType.CHAT;
|
|
|
649
649
|
/** Default client capabilities */
|
|
650
650
|
declare const DEFAULT_CLIENT_CAPABILITIES: string[];
|
|
651
651
|
/** Client version sent in startRequest */
|
|
652
|
-
declare const CLIENT_VERSION = "
|
|
652
|
+
declare const CLIENT_VERSION = "8.51.0";
|
|
653
653
|
/**
|
|
654
654
|
* Agent privileges for workflow creation.
|
|
655
655
|
* Matches gitlab-lsp AGENT_PRIVILEGES enum.
|
package/dist/index.d.ts
CHANGED
|
@@ -649,7 +649,7 @@ declare const DEFAULT_WORKFLOW_DEFINITION = WorkflowType.CHAT;
|
|
|
649
649
|
/** Default client capabilities */
|
|
650
650
|
declare const DEFAULT_CLIENT_CAPABILITIES: string[];
|
|
651
651
|
/** Client version sent in startRequest */
|
|
652
|
-
declare const CLIENT_VERSION = "
|
|
652
|
+
declare const CLIENT_VERSION = "8.51.0";
|
|
653
653
|
/**
|
|
654
654
|
* Agent privileges for workflow creation.
|
|
655
655
|
* Matches gitlab-lsp AGENT_PRIVILEGES enum.
|
package/dist/index.js
CHANGED
|
@@ -1653,7 +1653,7 @@ var GitLabOpenAILanguageModel = class {
|
|
|
1653
1653
|
var import_isomorphic_ws = __toESM(require("isomorphic-ws"));
|
|
1654
1654
|
|
|
1655
1655
|
// src/version.ts
|
|
1656
|
-
var VERSION = true ? "6.
|
|
1656
|
+
var VERSION = true ? "6.4.1" : "0.0.0-dev";
|
|
1657
1657
|
|
|
1658
1658
|
// src/gitlab-workflow-types.ts
|
|
1659
1659
|
var WorkflowType = /* @__PURE__ */ ((WorkflowType2) => {
|
|
@@ -1665,7 +1665,7 @@ var WS_KEEPALIVE_PING_INTERVAL_MS = 45e3;
|
|
|
1665
1665
|
var WS_HEARTBEAT_INTERVAL_MS = 6e4;
|
|
1666
1666
|
var DEFAULT_WORKFLOW_DEFINITION = "chat" /* CHAT */;
|
|
1667
1667
|
var DEFAULT_CLIENT_CAPABILITIES = ["shell_command"];
|
|
1668
|
-
var CLIENT_VERSION = "
|
|
1668
|
+
var CLIENT_VERSION = "8.51.0";
|
|
1669
1669
|
var STOP_REASON_USER = "USER_ACTION_TRIGGERED_STOP";
|
|
1670
1670
|
var AGENT_PRIVILEGES = {
|
|
1671
1671
|
READ_WRITE_FILES: 1,
|
|
@@ -1852,6 +1852,7 @@ var GitLabWorkflowClient = class {
|
|
|
1852
1852
|
}
|
|
1853
1853
|
delete headers["content-type"];
|
|
1854
1854
|
headers["x-gitlab-client-type"] = "node-websocket";
|
|
1855
|
+
headers["x-gitlab-language-server-version"] = CLIENT_VERSION;
|
|
1855
1856
|
const parsedUrl = new URL(options.instanceUrl);
|
|
1856
1857
|
const origin = parsedUrl.origin;
|
|
1857
1858
|
headers["origin"] = origin;
|
|
@@ -3490,7 +3491,8 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3490
3491
|
this.sessionWorkflows.set(sessionKey, {
|
|
3491
3492
|
workflowId,
|
|
3492
3493
|
workflowDefinition: effectiveDefinition,
|
|
3493
|
-
agentEmitted: /* @__PURE__ */ new Map()
|
|
3494
|
+
agentEmitted: /* @__PURE__ */ new Map(),
|
|
3495
|
+
toolEntries: /* @__PURE__ */ new Set()
|
|
3494
3496
|
});
|
|
3495
3497
|
sess = this.sessionWorkflows.get(sessionKey);
|
|
3496
3498
|
}
|
|
@@ -3510,6 +3512,8 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3510
3512
|
currentAgentMessageId: "",
|
|
3511
3513
|
activeClient: wsClient,
|
|
3512
3514
|
processedRequestIDs: /* @__PURE__ */ new Set(),
|
|
3515
|
+
emittedToolEntries: new Set(sess?.toolEntries),
|
|
3516
|
+
emittedToolKeys: /* @__PURE__ */ new Set(),
|
|
3513
3517
|
sessionKey
|
|
3514
3518
|
};
|
|
3515
3519
|
for (const msg of options.prompt) {
|
|
@@ -3588,10 +3592,6 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3588
3592
|
const resolvedFlowConfigSchemaVersion = callFlowConfigSchemaVersion ?? this.workflowOptions.flowConfigSchemaVersion;
|
|
3589
3593
|
if (resolvedFlowConfig) {
|
|
3590
3594
|
startReq.flowConfig = resolvedFlowConfig;
|
|
3591
|
-
} else if (this.workflowOptions.systemPrompt) {
|
|
3592
|
-
startReq.flowConfig = {
|
|
3593
|
-
prompts: [{ prompt_template: { system: this.workflowOptions.systemPrompt } }]
|
|
3594
|
-
};
|
|
3595
3595
|
}
|
|
3596
3596
|
if (resolvedFlowConfigSchemaVersion) {
|
|
3597
3597
|
startReq.flowConfigSchemaVersion = resolvedFlowConfigSchemaVersion;
|
|
@@ -3659,6 +3659,7 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3659
3659
|
const { requestID, data } = event;
|
|
3660
3660
|
if (ss.processedRequestIDs.has(requestID)) break;
|
|
3661
3661
|
ss.processedRequestIDs.add(requestID);
|
|
3662
|
+
ss.emittedToolKeys.add(data.name);
|
|
3662
3663
|
let parsedArgs;
|
|
3663
3664
|
try {
|
|
3664
3665
|
JSON.parse(data.args);
|
|
@@ -3708,6 +3709,7 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3708
3709
|
if (ss.processedRequestIDs.has(event.requestID)) break;
|
|
3709
3710
|
ss.processedRequestIDs.add(event.requestID);
|
|
3710
3711
|
const mapped = mapBuiltinTool(event.toolName, event.data, availableToolNames);
|
|
3712
|
+
ss.emittedToolKeys.add(mapped.toolName);
|
|
3711
3713
|
const mappedArgs = JSON.stringify(mapped.args);
|
|
3712
3714
|
if (ss.activeTextBlockId) {
|
|
3713
3715
|
controller.enqueue({ type: "text-end", id: ss.activeTextBlockId });
|
|
@@ -3889,6 +3891,51 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3889
3891
|
}
|
|
3890
3892
|
for (let i = 0; i < chatLog.length; i++) {
|
|
3891
3893
|
const entry = chatLog[i];
|
|
3894
|
+
if (entry.message_type === "tool" && entry.tool_info) {
|
|
3895
|
+
const toolId = entry.message_id || entry.correlation_id || `tool-${i}`;
|
|
3896
|
+
if (ss.emittedToolEntries.has(toolId)) continue;
|
|
3897
|
+
const name = entry.tool_info.name;
|
|
3898
|
+
const args = JSON.stringify(entry.tool_info.args ?? {});
|
|
3899
|
+
if (ss.emittedToolKeys.has(name)) {
|
|
3900
|
+
ss.emittedToolEntries.add(toolId);
|
|
3901
|
+
const sess2 = this.sessionWorkflows.get(ss.sessionKey);
|
|
3902
|
+
if (sess2) sess2.toolEntries.add(toolId);
|
|
3903
|
+
continue;
|
|
3904
|
+
}
|
|
3905
|
+
if (ss.activeTextBlockId) {
|
|
3906
|
+
controller.enqueue({ type: "text-end", id: ss.activeTextBlockId });
|
|
3907
|
+
ss.activeTextBlockId = null;
|
|
3908
|
+
}
|
|
3909
|
+
controller.enqueue({
|
|
3910
|
+
type: "tool-input-start",
|
|
3911
|
+
id: toolId,
|
|
3912
|
+
toolName: name,
|
|
3913
|
+
providerExecuted: true
|
|
3914
|
+
});
|
|
3915
|
+
controller.enqueue({ type: "tool-input-delta", id: toolId, delta: args });
|
|
3916
|
+
controller.enqueue({ type: "tool-input-end", id: toolId });
|
|
3917
|
+
controller.enqueue({
|
|
3918
|
+
type: "tool-call",
|
|
3919
|
+
toolCallId: toolId,
|
|
3920
|
+
toolName: name,
|
|
3921
|
+
input: args,
|
|
3922
|
+
providerExecuted: true,
|
|
3923
|
+
dynamic: true
|
|
3924
|
+
});
|
|
3925
|
+
const response = entry.tool_info.tool_response;
|
|
3926
|
+
const output = typeof response === "string" ? response : response ? response.content : entry.content || "";
|
|
3927
|
+
controller.enqueue({
|
|
3928
|
+
type: "tool-result",
|
|
3929
|
+
toolCallId: toolId,
|
|
3930
|
+
toolName: name,
|
|
3931
|
+
result: { output, title: name, metadata: {} },
|
|
3932
|
+
isError: false
|
|
3933
|
+
});
|
|
3934
|
+
ss.emittedToolEntries.add(toolId);
|
|
3935
|
+
const sess = this.sessionWorkflows.get(ss.sessionKey);
|
|
3936
|
+
if (sess) sess.toolEntries.add(toolId);
|
|
3937
|
+
continue;
|
|
3938
|
+
}
|
|
3892
3939
|
if (entry.message_type !== "agent") continue;
|
|
3893
3940
|
const content = entry.content || "";
|
|
3894
3941
|
const msgId = entry.message_id || `idx-${i}`;
|