gitlab-ai-provider 6.0.0 → 6.1.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 +15 -0
- package/dist/gitlab-ai-provider-6.1.1.tgz +0 -0
- package/dist/index.d.mts +64 -1
- package/dist/index.d.ts +64 -1
- package/dist/index.js +127 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +127 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/gitlab-ai-provider-6.0.0.tgz +0 -0
package/dist/index.mjs
CHANGED
|
@@ -1582,7 +1582,7 @@ var GitLabOpenAILanguageModel = class {
|
|
|
1582
1582
|
import WebSocket from "isomorphic-ws";
|
|
1583
1583
|
|
|
1584
1584
|
// src/version.ts
|
|
1585
|
-
var VERSION = true ? "
|
|
1585
|
+
var VERSION = true ? "6.1.0" : "0.0.0-dev";
|
|
1586
1586
|
|
|
1587
1587
|
// src/gitlab-workflow-types.ts
|
|
1588
1588
|
var WorkflowType = /* @__PURE__ */ ((WorkflowType2) => {
|
|
@@ -1808,7 +1808,9 @@ var GitLabWorkflowClient = class {
|
|
|
1808
1808
|
});
|
|
1809
1809
|
} else if (checkpoint.status === "STOPPED" || checkpoint.status === "CANCELLED") {
|
|
1810
1810
|
this.emit({ type: "completed" });
|
|
1811
|
-
} else if (checkpoint.status === "TOOL_CALL_APPROVAL_REQUIRED"
|
|
1811
|
+
} else if (checkpoint.status === "TOOL_CALL_APPROVAL_REQUIRED") {
|
|
1812
|
+
this.emit({ type: "approval-required", tools: this.extractApprovalTools(checkpoint) });
|
|
1813
|
+
} else if (checkpoint.status === "PLAN_APPROVAL_REQUIRED") {
|
|
1812
1814
|
this.emit({ type: "completed" });
|
|
1813
1815
|
}
|
|
1814
1816
|
return;
|
|
@@ -1847,6 +1849,18 @@ var GitLabWorkflowClient = class {
|
|
|
1847
1849
|
}
|
|
1848
1850
|
}
|
|
1849
1851
|
}
|
|
1852
|
+
extractApprovalTools(checkpoint) {
|
|
1853
|
+
if (!checkpoint.checkpoint) return [];
|
|
1854
|
+
let parsed;
|
|
1855
|
+
try {
|
|
1856
|
+
parsed = JSON.parse(checkpoint.checkpoint);
|
|
1857
|
+
} catch {
|
|
1858
|
+
return [];
|
|
1859
|
+
}
|
|
1860
|
+
return (parsed.channel_values?.ui_chat_log ?? []).filter(
|
|
1861
|
+
(e) => e.message_type === "request" && e.tool_info !== null
|
|
1862
|
+
).map((e) => ({ name: e.tool_info.name, args: JSON.stringify(e.tool_info.args) }));
|
|
1863
|
+
}
|
|
1850
1864
|
send(event) {
|
|
1851
1865
|
if (this.socket?.readyState === WebSocket.OPEN) {
|
|
1852
1866
|
const json = JSON.stringify(event);
|
|
@@ -3018,6 +3032,23 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3018
3032
|
* the AI SDK only surfaces usage via finish-step at stream end.
|
|
3019
3033
|
*/
|
|
3020
3034
|
onUsageUpdate = null;
|
|
3035
|
+
/**
|
|
3036
|
+
* Tool names pre-approved for the current session.
|
|
3037
|
+
* Set by the host (e.g., opencode) and merged into preapproved_tools on each StartRequest.
|
|
3038
|
+
* Updated when the user chooses "always" in the approval prompt.
|
|
3039
|
+
*/
|
|
3040
|
+
sessionPreapprovedTools = [];
|
|
3041
|
+
/**
|
|
3042
|
+
* Set the approval handler callback.
|
|
3043
|
+
* Called when DWS requires tool call approval. Host (e.g., opencode) wires this
|
|
3044
|
+
* to its permission system each stream call, similar to toolExecutor.
|
|
3045
|
+
*/
|
|
3046
|
+
set approvalHandler(handler) {
|
|
3047
|
+
this.workflowOptions.approvalHandler = handler ?? void 0;
|
|
3048
|
+
}
|
|
3049
|
+
get approvalHandler() {
|
|
3050
|
+
return this.workflowOptions.approvalHandler ?? null;
|
|
3051
|
+
}
|
|
3021
3052
|
/**
|
|
3022
3053
|
* Optional callback invoked when multiple workflow models are available
|
|
3023
3054
|
* and the user should pick one. Set per-stream by the host (e.g., OpenCode)
|
|
@@ -3319,7 +3350,10 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3319
3350
|
const goal = this.extractGoalFromPrompt(options.prompt);
|
|
3320
3351
|
const modelRef = await this.resolveModelRef();
|
|
3321
3352
|
const mcpTools = this.extractMcpTools(options);
|
|
3322
|
-
const preapprovedTools =
|
|
3353
|
+
const preapprovedTools = [
|
|
3354
|
+
...this.workflowOptions.preapprovedTools ?? mcpTools.map((t) => t.name),
|
|
3355
|
+
...this.sessionPreapprovedTools
|
|
3356
|
+
];
|
|
3323
3357
|
const additionalContext = this.buildAdditionalContext(options.prompt);
|
|
3324
3358
|
const toolExecutor = this.toolExecutor ?? null;
|
|
3325
3359
|
const availableToolNames = new Set(options.tools?.map((t) => t.name) ?? []);
|
|
@@ -3335,7 +3369,8 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3335
3369
|
workflowId = await this.tokenClient.createWorkflow(goal, {
|
|
3336
3370
|
projectId,
|
|
3337
3371
|
namespaceId: this.workflowOptions.namespaceId,
|
|
3338
|
-
workflowDefinition: this.workflowOptions.workflowDefinition
|
|
3372
|
+
workflowDefinition: this.workflowOptions.workflowDefinition,
|
|
3373
|
+
agentPrivileges: this.workflowOptions.agentPrivileges
|
|
3339
3374
|
});
|
|
3340
3375
|
this.currentWorkflowId = workflowId;
|
|
3341
3376
|
}
|
|
@@ -3347,11 +3382,13 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3347
3382
|
streamedInputChars: 0,
|
|
3348
3383
|
streamedOutputChars: 0,
|
|
3349
3384
|
pendingToolCount: 0,
|
|
3385
|
+
approvalPending: false,
|
|
3350
3386
|
deferredClose: null,
|
|
3351
3387
|
activeTextBlockId: null,
|
|
3352
3388
|
agentMessageEmitted: new Map(this.persistedAgentEmitted),
|
|
3353
3389
|
currentAgentMessageId: "",
|
|
3354
|
-
activeClient: wsClient
|
|
3390
|
+
activeClient: wsClient,
|
|
3391
|
+
processedRequestIDs: /* @__PURE__ */ new Set()
|
|
3355
3392
|
};
|
|
3356
3393
|
for (const msg of options.prompt) {
|
|
3357
3394
|
if (msg.role === "system") {
|
|
@@ -3364,6 +3401,7 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3364
3401
|
}
|
|
3365
3402
|
}
|
|
3366
3403
|
}
|
|
3404
|
+
let startReq;
|
|
3367
3405
|
const stream = new ReadableStream({
|
|
3368
3406
|
start: async (controller) => {
|
|
3369
3407
|
try {
|
|
@@ -3384,7 +3422,8 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3384
3422
|
wsClient,
|
|
3385
3423
|
toolExecutor,
|
|
3386
3424
|
() => `text-${textBlockCounter++}`,
|
|
3387
|
-
availableToolNames
|
|
3425
|
+
availableToolNames,
|
|
3426
|
+
startReq
|
|
3388
3427
|
);
|
|
3389
3428
|
}
|
|
3390
3429
|
);
|
|
@@ -3406,7 +3445,7 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3406
3445
|
const trimmedPreapproved = preapprovedTools.filter(
|
|
3407
3446
|
(name) => trimmed.mcpTools.some((t) => t.name === name)
|
|
3408
3447
|
);
|
|
3409
|
-
|
|
3448
|
+
startReq = {
|
|
3410
3449
|
workflowID: workflowId,
|
|
3411
3450
|
clientVersion: CLIENT_VERSION,
|
|
3412
3451
|
workflowDefinition: workflowDef,
|
|
@@ -3471,7 +3510,7 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3471
3510
|
// ---------------------------------------------------------------------------
|
|
3472
3511
|
// Event handling
|
|
3473
3512
|
// ---------------------------------------------------------------------------
|
|
3474
|
-
handleWorkflowEvent(ss, event, controller, wsClient, toolExecutor, nextTextId, availableToolNames) {
|
|
3513
|
+
handleWorkflowEvent(ss, event, controller, wsClient, toolExecutor, nextTextId, availableToolNames, startReq) {
|
|
3475
3514
|
if (ss.streamClosed) {
|
|
3476
3515
|
return;
|
|
3477
3516
|
}
|
|
@@ -3482,6 +3521,8 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3482
3521
|
}
|
|
3483
3522
|
case "tool-request": {
|
|
3484
3523
|
const { requestID, data } = event;
|
|
3524
|
+
if (ss.processedRequestIDs.has(requestID)) break;
|
|
3525
|
+
ss.processedRequestIDs.add(requestID);
|
|
3485
3526
|
let parsedArgs;
|
|
3486
3527
|
try {
|
|
3487
3528
|
JSON.parse(data.args);
|
|
@@ -3528,6 +3569,8 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3528
3569
|
break;
|
|
3529
3570
|
}
|
|
3530
3571
|
case "builtin-tool-request": {
|
|
3572
|
+
if (ss.processedRequestIDs.has(event.requestID)) break;
|
|
3573
|
+
ss.processedRequestIDs.add(event.requestID);
|
|
3531
3574
|
const mapped = mapBuiltinTool(event.toolName, event.data, availableToolNames);
|
|
3532
3575
|
const mappedArgs = JSON.stringify(mapped.args);
|
|
3533
3576
|
if (ss.activeTextBlockId) {
|
|
@@ -3568,6 +3611,26 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3568
3611
|
});
|
|
3569
3612
|
break;
|
|
3570
3613
|
}
|
|
3614
|
+
case "approval-required": {
|
|
3615
|
+
ss.approvalPending = true;
|
|
3616
|
+
this.approveAndResume(
|
|
3617
|
+
ss,
|
|
3618
|
+
event.tools,
|
|
3619
|
+
startReq,
|
|
3620
|
+
controller,
|
|
3621
|
+
toolExecutor,
|
|
3622
|
+
nextTextId,
|
|
3623
|
+
availableToolNames
|
|
3624
|
+
).catch(() => {
|
|
3625
|
+
ss.approvalPending = false;
|
|
3626
|
+
if (ss.deferredClose) {
|
|
3627
|
+
const close = ss.deferredClose;
|
|
3628
|
+
ss.deferredClose = null;
|
|
3629
|
+
close();
|
|
3630
|
+
}
|
|
3631
|
+
});
|
|
3632
|
+
break;
|
|
3633
|
+
}
|
|
3571
3634
|
case "completed": {
|
|
3572
3635
|
if (ss.activeTextBlockId) {
|
|
3573
3636
|
controller.enqueue({ type: "text-end", id: ss.activeTextBlockId });
|
|
@@ -3586,7 +3649,7 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3586
3649
|
controller.close();
|
|
3587
3650
|
this.cleanupClient(ss);
|
|
3588
3651
|
};
|
|
3589
|
-
if (ss.pendingToolCount > 0) {
|
|
3652
|
+
if (ss.pendingToolCount > 0 || ss.approvalPending) {
|
|
3590
3653
|
ss.deferredClose = doCompleteClose;
|
|
3591
3654
|
} else {
|
|
3592
3655
|
ss.deferredClose = null;
|
|
@@ -3645,7 +3708,7 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3645
3708
|
this.cleanupClient(ss);
|
|
3646
3709
|
}
|
|
3647
3710
|
};
|
|
3648
|
-
if (ss.pendingToolCount > 0) {
|
|
3711
|
+
if (ss.pendingToolCount > 0 || ss.approvalPending) {
|
|
3649
3712
|
ss.deferredClose = doClose;
|
|
3650
3713
|
} else {
|
|
3651
3714
|
ss.deferredClose = null;
|
|
@@ -3821,6 +3884,60 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3821
3884
|
this.persistedAgentEmitted.clear();
|
|
3822
3885
|
}
|
|
3823
3886
|
}
|
|
3887
|
+
async approveAndResume(ss, tools, startReq, controller, toolExecutor, nextTextId, availableToolNames) {
|
|
3888
|
+
const handler = this.workflowOptions.approvalHandler;
|
|
3889
|
+
if (!handler || !startReq) {
|
|
3890
|
+
ss.approvalPending = false;
|
|
3891
|
+
if (ss.deferredClose) {
|
|
3892
|
+
const close = ss.deferredClose;
|
|
3893
|
+
ss.deferredClose = null;
|
|
3894
|
+
close();
|
|
3895
|
+
}
|
|
3896
|
+
return;
|
|
3897
|
+
}
|
|
3898
|
+
let decision;
|
|
3899
|
+
try {
|
|
3900
|
+
decision = await handler(tools);
|
|
3901
|
+
} catch (err) {
|
|
3902
|
+
ss.approvalPending = false;
|
|
3903
|
+
if (!ss.streamClosed) controller.error(err);
|
|
3904
|
+
return;
|
|
3905
|
+
}
|
|
3906
|
+
ss.approvalPending = false;
|
|
3907
|
+
this.cleanupClient(ss, false);
|
|
3908
|
+
const approval = decision.approved ? { approval: { tool_name: tools[0]?.name, tool_args_json: tools[0]?.args } } : { rejection: { message: decision.message ?? "User rejected" } };
|
|
3909
|
+
const newStartReq = { ...startReq, approval };
|
|
3910
|
+
const newClient = new GitLabWorkflowClient();
|
|
3911
|
+
this.activeClients.add(newClient);
|
|
3912
|
+
ss.activeClient = newClient;
|
|
3913
|
+
const modelRef = await this.resolveModelRef();
|
|
3914
|
+
try {
|
|
3915
|
+
await newClient.connect(
|
|
3916
|
+
{
|
|
3917
|
+
instanceUrl: this.config.instanceUrl,
|
|
3918
|
+
modelRef,
|
|
3919
|
+
headers: this.config.getHeaders(),
|
|
3920
|
+
projectId: this.workflowOptions.projectId,
|
|
3921
|
+
namespaceId: this.workflowOptions.namespaceId,
|
|
3922
|
+
rootNamespaceId: this.workflowOptions.rootNamespaceId
|
|
3923
|
+
},
|
|
3924
|
+
(event) => this.handleWorkflowEvent(
|
|
3925
|
+
ss,
|
|
3926
|
+
event,
|
|
3927
|
+
controller,
|
|
3928
|
+
newClient,
|
|
3929
|
+
toolExecutor,
|
|
3930
|
+
nextTextId,
|
|
3931
|
+
availableToolNames,
|
|
3932
|
+
newStartReq
|
|
3933
|
+
)
|
|
3934
|
+
);
|
|
3935
|
+
newClient.sendStartRequest(newStartReq);
|
|
3936
|
+
} catch (err) {
|
|
3937
|
+
this.cleanupClient(ss, true);
|
|
3938
|
+
if (!ss.streamClosed) controller.error(err);
|
|
3939
|
+
}
|
|
3940
|
+
}
|
|
3824
3941
|
// ---------------------------------------------------------------------------
|
|
3825
3942
|
// Workflow metadata
|
|
3826
3943
|
// ---------------------------------------------------------------------------
|