gitlab-ai-provider 5.1.0 → 5.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 +7 -0
- package/dist/gitlab-ai-provider-5.1.1.tgz +0 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +147 -63
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +147 -63
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/gitlab-ai-provider-5.1.0.tgz +0 -0
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.
|
|
1509
|
+
var VERSION = true ? "5.1.0" : "0.0.0-dev";
|
|
1510
1510
|
|
|
1511
1511
|
// src/gitlab-workflow-types.ts
|
|
1512
1512
|
var WorkflowType = /* @__PURE__ */ ((WorkflowType2) => {
|
|
@@ -1843,7 +1843,8 @@ function sanitizeErrorMessage(message) {
|
|
|
1843
1843
|
if (!message) return "";
|
|
1844
1844
|
return message.replace(/\bBearer\s+[A-Za-z0-9\-_.~+/]+=*/gi, "Bearer [REDACTED]").replace(/\bgl(?:pat|oat|cbt|dt|oas|rt|soat|ffct|sapat)-[A-Za-z0-9_-]+/g, "[REDACTED]").replace(/([?&](?:private_token|access_token|token)=)[^&\s"']*/gi, "$1[REDACTED]").replace(/:\/\/([^:@/\s]+):([^@/\s]+)@/g, "://$1:[REDACTED]@");
|
|
1845
1845
|
}
|
|
1846
|
-
function mapBuiltinTool(dwsToolName, data) {
|
|
1846
|
+
function mapBuiltinTool(dwsToolName, data, availableTools) {
|
|
1847
|
+
const has = (name) => !availableTools || availableTools.has(name);
|
|
1847
1848
|
switch (dwsToolName) {
|
|
1848
1849
|
case "runReadFile":
|
|
1849
1850
|
return { toolName: "read", args: { filePath: data.filepath } };
|
|
@@ -1857,20 +1858,51 @@ function mapBuiltinTool(dwsToolName, data) {
|
|
|
1857
1858
|
args: { filePaths: paths }
|
|
1858
1859
|
};
|
|
1859
1860
|
}
|
|
1860
|
-
case "runWriteFile":
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
}
|
|
1873
|
-
|
|
1861
|
+
case "runWriteFile": {
|
|
1862
|
+
if (has("write")) {
|
|
1863
|
+
return {
|
|
1864
|
+
toolName: "write",
|
|
1865
|
+
args: { filePath: data.filepath, content: data.contents }
|
|
1866
|
+
};
|
|
1867
|
+
}
|
|
1868
|
+
const filePath = String(data.filepath ?? "");
|
|
1869
|
+
const content = String(data.contents ?? "");
|
|
1870
|
+
const patchLines = [
|
|
1871
|
+
"*** Begin Patch",
|
|
1872
|
+
`*** Add File: ${filePath}`,
|
|
1873
|
+
...content.split("\n").map((l) => `+${l}`),
|
|
1874
|
+
"*** End Patch"
|
|
1875
|
+
].join("\n");
|
|
1876
|
+
return { toolName: "apply_patch", args: { patchText: patchLines } };
|
|
1877
|
+
}
|
|
1878
|
+
case "runEditFile": {
|
|
1879
|
+
const editOldString = String(data.oldString ?? data.old_string ?? "");
|
|
1880
|
+
const editNewString = String(data.newString ?? data.new_string ?? "");
|
|
1881
|
+
if (has("edit")) {
|
|
1882
|
+
return {
|
|
1883
|
+
toolName: "edit",
|
|
1884
|
+
args: {
|
|
1885
|
+
filePath: data.filepath,
|
|
1886
|
+
oldString: editOldString,
|
|
1887
|
+
newString: editNewString
|
|
1888
|
+
}
|
|
1889
|
+
};
|
|
1890
|
+
}
|
|
1891
|
+
const editPath = String(data.filepath ?? "");
|
|
1892
|
+
const oldStr = editOldString;
|
|
1893
|
+
const newStr = editNewString;
|
|
1894
|
+
const oldLines = oldStr.split("\n");
|
|
1895
|
+
const newLines = newStr.split("\n");
|
|
1896
|
+
const patchContent = [
|
|
1897
|
+
"*** Begin Patch",
|
|
1898
|
+
`*** Update File: ${editPath}`,
|
|
1899
|
+
"@@",
|
|
1900
|
+
...oldLines.map((l) => `-${l}`),
|
|
1901
|
+
...newLines.map((l) => `+${l}`),
|
|
1902
|
+
"*** End Patch"
|
|
1903
|
+
].join("\n");
|
|
1904
|
+
return { toolName: "apply_patch", args: { patchText: patchContent } };
|
|
1905
|
+
}
|
|
1874
1906
|
case "runShellCommand": {
|
|
1875
1907
|
const command = data.command;
|
|
1876
1908
|
if (!command || typeof command !== "string") {
|
|
@@ -1993,6 +2025,87 @@ function mapBuiltinTool(dwsToolName, data) {
|
|
|
1993
2025
|
return { toolName: dwsToolName, args: data };
|
|
1994
2026
|
}
|
|
1995
2027
|
}
|
|
2028
|
+
function validateSafePath(filePath) {
|
|
2029
|
+
if (!filePath) {
|
|
2030
|
+
throw new Error("filePath is required");
|
|
2031
|
+
}
|
|
2032
|
+
if (filePath.includes("\0")) {
|
|
2033
|
+
throw new Error("filePath contains null bytes");
|
|
2034
|
+
}
|
|
2035
|
+
const path5 = __require("path");
|
|
2036
|
+
const resolved = path5.resolve(filePath);
|
|
2037
|
+
const cwd = process.cwd();
|
|
2038
|
+
if (!resolved.startsWith(cwd + path5.sep) && resolved !== cwd) {
|
|
2039
|
+
throw new Error(`filePath resolves outside the working directory: ${filePath}`);
|
|
2040
|
+
}
|
|
2041
|
+
return resolved;
|
|
2042
|
+
}
|
|
2043
|
+
function executeBuiltinFallback(toolName, argsJson) {
|
|
2044
|
+
if (toolName !== "edit" && toolName !== "write") {
|
|
2045
|
+
return null;
|
|
2046
|
+
}
|
|
2047
|
+
const fs4 = __require("fs");
|
|
2048
|
+
let args;
|
|
2049
|
+
try {
|
|
2050
|
+
args = JSON.parse(argsJson);
|
|
2051
|
+
} catch {
|
|
2052
|
+
return { result: "", error: `${toolName} fallback: invalid JSON arguments` };
|
|
2053
|
+
}
|
|
2054
|
+
try {
|
|
2055
|
+
if (toolName === "write") {
|
|
2056
|
+
const filePath2 = String(args.filePath ?? "");
|
|
2057
|
+
if (!filePath2) {
|
|
2058
|
+
return { result: "", error: "write fallback: filePath is required" };
|
|
2059
|
+
}
|
|
2060
|
+
const safePath2 = validateSafePath(filePath2);
|
|
2061
|
+
const content2 = String(args.content ?? "");
|
|
2062
|
+
fs4.writeFileSync(safePath2, content2, "utf-8");
|
|
2063
|
+
return {
|
|
2064
|
+
result: "File written successfully.",
|
|
2065
|
+
title: filePath2,
|
|
2066
|
+
metadata: { output: "File written successfully." }
|
|
2067
|
+
};
|
|
2068
|
+
}
|
|
2069
|
+
const filePath = String(args.filePath ?? "");
|
|
2070
|
+
const oldString = String(args.oldString ?? "");
|
|
2071
|
+
const newString = String(args.newString ?? "");
|
|
2072
|
+
if (!filePath) {
|
|
2073
|
+
return { result: "", error: "edit fallback: filePath is required" };
|
|
2074
|
+
}
|
|
2075
|
+
if (!oldString && !newString) {
|
|
2076
|
+
return { result: "", error: "edit fallback: oldString and newString are both empty" };
|
|
2077
|
+
}
|
|
2078
|
+
const safePath = validateSafePath(filePath);
|
|
2079
|
+
let content;
|
|
2080
|
+
try {
|
|
2081
|
+
content = fs4.readFileSync(safePath, "utf-8");
|
|
2082
|
+
} catch {
|
|
2083
|
+
content = "";
|
|
2084
|
+
}
|
|
2085
|
+
if (oldString === "") {
|
|
2086
|
+
fs4.writeFileSync(safePath, newString, "utf-8");
|
|
2087
|
+
return {
|
|
2088
|
+
result: "Edit applied successfully.",
|
|
2089
|
+
title: filePath,
|
|
2090
|
+
metadata: { output: "Edit applied successfully." }
|
|
2091
|
+
};
|
|
2092
|
+
}
|
|
2093
|
+
const idx = content.indexOf(oldString);
|
|
2094
|
+
if (idx === -1) {
|
|
2095
|
+
return { result: "", error: `edit fallback: could not find oldString in ${filePath}` };
|
|
2096
|
+
}
|
|
2097
|
+
const newContent = content.substring(0, idx) + newString + content.substring(idx + oldString.length);
|
|
2098
|
+
fs4.writeFileSync(safePath, newContent, "utf-8");
|
|
2099
|
+
return {
|
|
2100
|
+
result: "Edit applied successfully.",
|
|
2101
|
+
title: filePath,
|
|
2102
|
+
metadata: { output: "Edit applied successfully." }
|
|
2103
|
+
};
|
|
2104
|
+
} catch (e) {
|
|
2105
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
2106
|
+
return { result: "", error: sanitizeErrorMessage(msg) };
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
1996
2109
|
|
|
1997
2110
|
// src/gitlab-workflow-token-client.ts
|
|
1998
2111
|
var TOKEN_CACHE_DURATION_MS = 25 * 60 * 1e3;
|
|
@@ -3083,6 +3196,7 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3083
3196
|
const preapprovedTools = this.workflowOptions.preapprovedTools ?? mcpTools.map((t) => t.name);
|
|
3084
3197
|
const additionalContext = this.buildAdditionalContext(options.prompt);
|
|
3085
3198
|
const toolExecutor = this.toolExecutor ?? null;
|
|
3199
|
+
const availableToolNames = new Set(options.tools?.map((t) => t.name) ?? []);
|
|
3086
3200
|
await this.tokenClient.getToken(
|
|
3087
3201
|
this.workflowOptions.workflowDefinition ?? DEFAULT_WORKFLOW_DEFINITION,
|
|
3088
3202
|
this.workflowOptions.rootNamespaceId
|
|
@@ -3143,7 +3257,8 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3143
3257
|
controller,
|
|
3144
3258
|
wsClient,
|
|
3145
3259
|
toolExecutor,
|
|
3146
|
-
() => `text-${textBlockCounter++}
|
|
3260
|
+
() => `text-${textBlockCounter++}`,
|
|
3261
|
+
availableToolNames
|
|
3147
3262
|
);
|
|
3148
3263
|
}
|
|
3149
3264
|
);
|
|
@@ -3224,7 +3339,7 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3224
3339
|
// ---------------------------------------------------------------------------
|
|
3225
3340
|
// Event handling
|
|
3226
3341
|
// ---------------------------------------------------------------------------
|
|
3227
|
-
handleWorkflowEvent(ss, event, controller, wsClient, toolExecutor, nextTextId) {
|
|
3342
|
+
handleWorkflowEvent(ss, event, controller, wsClient, toolExecutor, nextTextId, availableToolNames) {
|
|
3228
3343
|
if (ss.streamClosed) {
|
|
3229
3344
|
return;
|
|
3230
3345
|
}
|
|
@@ -3281,7 +3396,7 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3281
3396
|
break;
|
|
3282
3397
|
}
|
|
3283
3398
|
case "builtin-tool-request": {
|
|
3284
|
-
const mapped = mapBuiltinTool(event.toolName, event.data);
|
|
3399
|
+
const mapped = mapBuiltinTool(event.toolName, event.data, availableToolNames);
|
|
3285
3400
|
const mappedArgs = JSON.stringify(mapped.args);
|
|
3286
3401
|
if (ss.activeTextBlockId) {
|
|
3287
3402
|
controller.enqueue({ type: "text-end", id: ss.activeTextBlockId });
|
|
@@ -3481,37 +3596,19 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3481
3596
|
};
|
|
3482
3597
|
try {
|
|
3483
3598
|
if (toolExecutor) {
|
|
3484
|
-
|
|
3599
|
+
let result = await toolExecutor(toolName, argsJson, requestID);
|
|
3600
|
+
if (result.error && /^Unknown tool:/.test(result.error)) {
|
|
3601
|
+
const fallback = executeBuiltinFallback(toolName, argsJson);
|
|
3602
|
+
if (fallback) {
|
|
3603
|
+
result = fallback;
|
|
3604
|
+
}
|
|
3605
|
+
}
|
|
3485
3606
|
wsClient.sendActionResponse(requestID, result.result, result.error);
|
|
3486
3607
|
ss.streamedInputChars += argsJson.length;
|
|
3487
3608
|
ss.streamedOutputChars += result.result.length;
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
try {
|
|
3492
|
-
const parsed = JSON.parse(result.result);
|
|
3493
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
3494
|
-
if (typeof parsed.output === "string") {
|
|
3495
|
-
toolOutput = parsed.output;
|
|
3496
|
-
} else if (parsed.output != null) {
|
|
3497
|
-
toolOutput = JSON.stringify(parsed.output);
|
|
3498
|
-
}
|
|
3499
|
-
if (typeof parsed.title === "string") toolTitle = parsed.title;
|
|
3500
|
-
if (parsed.metadata && typeof parsed.metadata === "object") {
|
|
3501
|
-
toolMetadata = {};
|
|
3502
|
-
for (const [k, v] of Object.entries(parsed.metadata)) {
|
|
3503
|
-
toolMetadata[k] = typeof v === "string" ? v : JSON.stringify(v);
|
|
3504
|
-
}
|
|
3505
|
-
if (!("output" in toolMetadata)) {
|
|
3506
|
-
toolMetadata.output = toolOutput;
|
|
3507
|
-
}
|
|
3508
|
-
}
|
|
3509
|
-
} else if (Array.isArray(parsed)) {
|
|
3510
|
-
toolOutput = JSON.stringify(parsed);
|
|
3511
|
-
toolMetadata = { output: toolOutput };
|
|
3512
|
-
}
|
|
3513
|
-
} catch {
|
|
3514
|
-
}
|
|
3609
|
+
const toolOutput = result.result;
|
|
3610
|
+
const toolTitle = result.title ?? `${toolName} result`;
|
|
3611
|
+
const toolMetadata = result.metadata ?? { output: result.result };
|
|
3515
3612
|
if (result.error) {
|
|
3516
3613
|
let errorText;
|
|
3517
3614
|
if (typeof result.error === "string") {
|
|
@@ -3521,16 +3618,11 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3521
3618
|
} else {
|
|
3522
3619
|
errorText = String(result.error);
|
|
3523
3620
|
}
|
|
3524
|
-
const errorOutput = toolOutput || errorText;
|
|
3525
3621
|
safeEnqueue({
|
|
3526
3622
|
type: "tool-result",
|
|
3527
3623
|
toolCallId: requestID,
|
|
3528
3624
|
toolName,
|
|
3529
|
-
result:
|
|
3530
|
-
output: errorOutput,
|
|
3531
|
-
title: toolTitle,
|
|
3532
|
-
metadata: { ...toolMetadata, error: errorText }
|
|
3533
|
-
},
|
|
3625
|
+
result: errorText,
|
|
3534
3626
|
isError: true,
|
|
3535
3627
|
providerExecuted: true
|
|
3536
3628
|
});
|
|
@@ -3555,11 +3647,7 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3555
3647
|
type: "tool-result",
|
|
3556
3648
|
toolCallId: requestID,
|
|
3557
3649
|
toolName,
|
|
3558
|
-
result:
|
|
3559
|
-
output: errorMsg,
|
|
3560
|
-
title: `${toolName} error`,
|
|
3561
|
-
metadata: { output: errorMsg }
|
|
3562
|
-
},
|
|
3650
|
+
result: errorMsg,
|
|
3563
3651
|
isError: true,
|
|
3564
3652
|
providerExecuted: true
|
|
3565
3653
|
});
|
|
@@ -3572,11 +3660,7 @@ var GitLabWorkflowLanguageModel = class _GitLabWorkflowLanguageModel {
|
|
|
3572
3660
|
type: "tool-result",
|
|
3573
3661
|
toolCallId: requestID,
|
|
3574
3662
|
toolName,
|
|
3575
|
-
result:
|
|
3576
|
-
output: errorMsg,
|
|
3577
|
-
title: `${toolName} error`,
|
|
3578
|
-
metadata: { output: errorMsg }
|
|
3579
|
-
},
|
|
3663
|
+
result: errorMsg,
|
|
3580
3664
|
isError: true,
|
|
3581
3665
|
providerExecuted: true
|
|
3582
3666
|
});
|