mobbdev 1.0.211 → 1.0.213
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/dist/args/commands/upload_ai_blame.mjs +1 -1
- package/dist/index.mjs +180 -184
- package/package.json +1 -1
|
@@ -42,7 +42,7 @@ var init_configs = __esm({
|
|
|
42
42
|
MCP_TOOLS_BROWSER_COOLDOWN_MS = 24 * 60 * 60 * 1e3;
|
|
43
43
|
isAutoScan = process.env["AUTO_SCAN"] !== "false";
|
|
44
44
|
MVS_AUTO_FIX_OVERRIDE = process.env["MVS_AUTO_FIX"];
|
|
45
|
-
MCP_PERIODIC_TRACK_INTERVAL = 60 * 60 * 1e3;
|
|
45
|
+
MCP_PERIODIC_TRACK_INTERVAL = 24 * 60 * 60 * 1e3;
|
|
46
46
|
MCP_SYSTEM_FIND_TIMEOUT_MS = 15 * 60 * 1e3;
|
|
47
47
|
}
|
|
48
48
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -51,7 +51,7 @@ var init_configs = __esm({
|
|
|
51
51
|
isAutoScan = process.env["AUTO_SCAN"] !== "false";
|
|
52
52
|
MVS_AUTO_FIX_OVERRIDE = process.env["MVS_AUTO_FIX"];
|
|
53
53
|
MCP_AUTO_FIX_DEBUG_MODE = true;
|
|
54
|
-
MCP_PERIODIC_TRACK_INTERVAL = 60 * 60 * 1e3;
|
|
54
|
+
MCP_PERIODIC_TRACK_INTERVAL = 24 * 60 * 60 * 1e3;
|
|
55
55
|
MCP_DEFAULT_REST_API_URL = "https://api.mobb.ai/api/rest/mcp/track";
|
|
56
56
|
MCP_SYSTEM_FIND_TIMEOUT_MS = 15 * 60 * 1e3;
|
|
57
57
|
}
|
|
@@ -6224,7 +6224,7 @@ async function getAdoSdk(params) {
|
|
|
6224
6224
|
const url = new URL(repoUrl);
|
|
6225
6225
|
const origin2 = url.origin.toLowerCase().endsWith(".visualstudio.com") ? DEFUALT_ADO_ORIGIN : url.origin.toLowerCase();
|
|
6226
6226
|
const params2 = `path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=commit&versionDescriptor[version]=${branch}&resolveLfs=true&$format=zip&api-version=5.0&download=true`;
|
|
6227
|
-
const
|
|
6227
|
+
const path18 = [
|
|
6228
6228
|
prefixPath,
|
|
6229
6229
|
owner,
|
|
6230
6230
|
projectName,
|
|
@@ -6235,7 +6235,7 @@ async function getAdoSdk(params) {
|
|
|
6235
6235
|
"items",
|
|
6236
6236
|
"items"
|
|
6237
6237
|
].filter(Boolean).join("/");
|
|
6238
|
-
return new URL(`${
|
|
6238
|
+
return new URL(`${path18}?${params2}`, origin2).toString();
|
|
6239
6239
|
},
|
|
6240
6240
|
async getAdoBranchList({ repoUrl }) {
|
|
6241
6241
|
try {
|
|
@@ -7782,14 +7782,14 @@ function getGithubSdk(params = {}) {
|
|
|
7782
7782
|
};
|
|
7783
7783
|
},
|
|
7784
7784
|
async getGithubBlameRanges(params2) {
|
|
7785
|
-
const { ref, gitHubUrl, path:
|
|
7785
|
+
const { ref, gitHubUrl, path: path18 } = params2;
|
|
7786
7786
|
const { owner, repo } = parseGithubOwnerAndRepo(gitHubUrl);
|
|
7787
7787
|
const res = await octokit.graphql(
|
|
7788
7788
|
GET_BLAME_DOCUMENT,
|
|
7789
7789
|
{
|
|
7790
7790
|
owner,
|
|
7791
7791
|
repo,
|
|
7792
|
-
path:
|
|
7792
|
+
path: path18,
|
|
7793
7793
|
ref
|
|
7794
7794
|
}
|
|
7795
7795
|
);
|
|
@@ -8131,11 +8131,11 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
8131
8131
|
markdownComment: comment
|
|
8132
8132
|
});
|
|
8133
8133
|
}
|
|
8134
|
-
async getRepoBlameRanges(ref,
|
|
8134
|
+
async getRepoBlameRanges(ref, path18) {
|
|
8135
8135
|
this._validateUrl();
|
|
8136
8136
|
return await this.githubSdk.getGithubBlameRanges({
|
|
8137
8137
|
ref,
|
|
8138
|
-
path:
|
|
8138
|
+
path: path18,
|
|
8139
8139
|
gitHubUrl: this.url
|
|
8140
8140
|
});
|
|
8141
8141
|
}
|
|
@@ -8815,13 +8815,13 @@ function parseGitlabOwnerAndRepo(gitlabUrl) {
|
|
|
8815
8815
|
const { organization, repoName, projectPath } = parsingResult;
|
|
8816
8816
|
return { owner: organization, repo: repoName, projectPath };
|
|
8817
8817
|
}
|
|
8818
|
-
async function getGitlabBlameRanges({ ref, gitlabUrl, path:
|
|
8818
|
+
async function getGitlabBlameRanges({ ref, gitlabUrl, path: path18 }, options) {
|
|
8819
8819
|
const { projectPath } = parseGitlabOwnerAndRepo(gitlabUrl);
|
|
8820
8820
|
const api2 = getGitBeaker({
|
|
8821
8821
|
url: gitlabUrl,
|
|
8822
8822
|
gitlabAuthToken: options?.gitlabAuthToken
|
|
8823
8823
|
});
|
|
8824
|
-
const resp = await api2.RepositoryFiles.allFileBlames(projectPath,
|
|
8824
|
+
const resp = await api2.RepositoryFiles.allFileBlames(projectPath, path18, ref);
|
|
8825
8825
|
let lineNumber = 1;
|
|
8826
8826
|
return resp.filter((range) => range.lines).map((range) => {
|
|
8827
8827
|
const oldLineNumber = lineNumber;
|
|
@@ -8998,10 +8998,10 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
8998
8998
|
markdownComment: comment
|
|
8999
8999
|
});
|
|
9000
9000
|
}
|
|
9001
|
-
async getRepoBlameRanges(ref,
|
|
9001
|
+
async getRepoBlameRanges(ref, path18) {
|
|
9002
9002
|
this._validateUrl();
|
|
9003
9003
|
return await getGitlabBlameRanges(
|
|
9004
|
-
{ ref, path:
|
|
9004
|
+
{ ref, path: path18, gitlabUrl: this.url },
|
|
9005
9005
|
{
|
|
9006
9006
|
url: this.url,
|
|
9007
9007
|
gitlabAuthToken: this.accessToken
|
|
@@ -11033,7 +11033,7 @@ async function postIssueComment(params) {
|
|
|
11033
11033
|
fpDescription
|
|
11034
11034
|
} = params;
|
|
11035
11035
|
const {
|
|
11036
|
-
path:
|
|
11036
|
+
path: path18,
|
|
11037
11037
|
startLine,
|
|
11038
11038
|
vulnerabilityReportIssue: {
|
|
11039
11039
|
vulnerabilityReportIssueTags,
|
|
@@ -11048,7 +11048,7 @@ async function postIssueComment(params) {
|
|
|
11048
11048
|
Refresh the page in order to see the changes.`,
|
|
11049
11049
|
pull_number: pullRequest,
|
|
11050
11050
|
commit_id: commitSha,
|
|
11051
|
-
path:
|
|
11051
|
+
path: path18,
|
|
11052
11052
|
line: startLine
|
|
11053
11053
|
});
|
|
11054
11054
|
const commentId = commentRes.data.id;
|
|
@@ -11082,7 +11082,7 @@ async function postFixComment(params) {
|
|
|
11082
11082
|
scanner
|
|
11083
11083
|
} = params;
|
|
11084
11084
|
const {
|
|
11085
|
-
path:
|
|
11085
|
+
path: path18,
|
|
11086
11086
|
startLine,
|
|
11087
11087
|
vulnerabilityReportIssue: { fixId, vulnerabilityReportIssueTags, category },
|
|
11088
11088
|
vulnerabilityReportIssueId
|
|
@@ -11100,7 +11100,7 @@ async function postFixComment(params) {
|
|
|
11100
11100
|
Refresh the page in order to see the changes.`,
|
|
11101
11101
|
pull_number: pullRequest,
|
|
11102
11102
|
commit_id: commitSha,
|
|
11103
|
-
path:
|
|
11103
|
+
path: path18,
|
|
11104
11104
|
line: startLine
|
|
11105
11105
|
});
|
|
11106
11106
|
const commentId = commentRes.data.id;
|
|
@@ -12858,8 +12858,8 @@ var WorkspaceService = class {
|
|
|
12858
12858
|
* Sets a known workspace path that was discovered through successful validation
|
|
12859
12859
|
* @param path The validated workspace path to store
|
|
12860
12860
|
*/
|
|
12861
|
-
static setKnownWorkspacePath(
|
|
12862
|
-
this.knownWorkspacePath =
|
|
12861
|
+
static setKnownWorkspacePath(path18) {
|
|
12862
|
+
this.knownWorkspacePath = path18;
|
|
12863
12863
|
}
|
|
12864
12864
|
/**
|
|
12865
12865
|
* Gets the known workspace path that was previously validated
|
|
@@ -14107,10 +14107,10 @@ var getHostInfo = (additionalMcpList) => {
|
|
|
14107
14107
|
const ideConfigPaths = /* @__PURE__ */ new Set();
|
|
14108
14108
|
for (const ide of IDEs) {
|
|
14109
14109
|
const configPaths = getMCPConfigPaths(ide);
|
|
14110
|
-
configPaths.forEach((
|
|
14110
|
+
configPaths.forEach((path18) => ideConfigPaths.add(path18));
|
|
14111
14111
|
}
|
|
14112
14112
|
const uniqueAdditionalPaths = additionalMcpList.filter(
|
|
14113
|
-
(
|
|
14113
|
+
(path18) => !ideConfigPaths.has(path18)
|
|
14114
14114
|
);
|
|
14115
14115
|
for (const ide of IDEs) {
|
|
14116
14116
|
const cfg = readMCPConfig(ide);
|
|
@@ -14230,78 +14230,68 @@ init_configs();
|
|
|
14230
14230
|
|
|
14231
14231
|
// src/mcp/services/McpUsageService/system.ts
|
|
14232
14232
|
init_configs();
|
|
14233
|
-
import
|
|
14233
|
+
import fs12 from "fs";
|
|
14234
14234
|
import os4 from "os";
|
|
14235
|
+
import path12 from "path";
|
|
14236
|
+
var MAX_DEPTH = 2;
|
|
14237
|
+
var patterns = ["mcp", "claude"];
|
|
14238
|
+
var isFileMatch = (fileName) => {
|
|
14239
|
+
const lowerName = fileName.toLowerCase();
|
|
14240
|
+
return lowerName.endsWith(".json") && patterns.some((p) => lowerName.includes(p.toLowerCase()));
|
|
14241
|
+
};
|
|
14242
|
+
var safeAccess = async (filePath) => {
|
|
14243
|
+
try {
|
|
14244
|
+
await fs12.promises.access(filePath, fs12.constants.R_OK);
|
|
14245
|
+
return true;
|
|
14246
|
+
} catch {
|
|
14247
|
+
return false;
|
|
14248
|
+
}
|
|
14249
|
+
};
|
|
14250
|
+
var searchDir = async (dir, depth = 0) => {
|
|
14251
|
+
const results = [];
|
|
14252
|
+
if (depth > MAX_DEPTH) return results;
|
|
14253
|
+
const entries = await fs12.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
14254
|
+
for (const entry of entries) {
|
|
14255
|
+
const fullPath = path12.join(dir, entry.name);
|
|
14256
|
+
if (entry.isFile() && isFileMatch(entry.name)) {
|
|
14257
|
+
results.push(fullPath);
|
|
14258
|
+
} else if (entry.isDirectory()) {
|
|
14259
|
+
if (await safeAccess(fullPath)) {
|
|
14260
|
+
const subResults = await searchDir(fullPath, depth + 1);
|
|
14261
|
+
results.push(...subResults);
|
|
14262
|
+
}
|
|
14263
|
+
}
|
|
14264
|
+
}
|
|
14265
|
+
return results;
|
|
14266
|
+
};
|
|
14235
14267
|
var findSystemMCPConfigs = async () => {
|
|
14236
14268
|
try {
|
|
14269
|
+
const home = os4.homedir();
|
|
14237
14270
|
const platform = os4.platform();
|
|
14238
|
-
|
|
14239
|
-
|
|
14240
|
-
|
|
14241
|
-
|
|
14242
|
-
|
|
14243
|
-
|
|
14244
|
-
|
|
14245
|
-
|
|
14246
|
-
|
|
14247
|
-
|
|
14248
|
-
|
|
14249
|
-
|
|
14250
|
-
args = [
|
|
14251
|
-
home,
|
|
14252
|
-
"-type",
|
|
14253
|
-
"f",
|
|
14254
|
-
"(",
|
|
14255
|
-
"-iname",
|
|
14256
|
-
"*mcp*.json",
|
|
14257
|
-
"-o",
|
|
14258
|
-
"-iname",
|
|
14259
|
-
"*claude*.json",
|
|
14260
|
-
")"
|
|
14261
|
-
];
|
|
14262
|
-
}
|
|
14263
|
-
return await new Promise((resolve) => {
|
|
14264
|
-
const child = spawn(command, args, {
|
|
14265
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
14266
|
-
shell: platform === "win32"
|
|
14267
|
-
// needed for PowerShell
|
|
14268
|
-
});
|
|
14269
|
-
let output = "";
|
|
14270
|
-
let errorOutput = "";
|
|
14271
|
-
const timer = setTimeout(() => {
|
|
14272
|
-
child.kill("SIGTERM");
|
|
14271
|
+
const knownDirs = platform === "win32" ? [
|
|
14272
|
+
path12.join(home, ".cursor"),
|
|
14273
|
+
path12.join(home, "Documents"),
|
|
14274
|
+
path12.join(home, "Downloads")
|
|
14275
|
+
] : [
|
|
14276
|
+
path12.join(home, ".cursor"),
|
|
14277
|
+
process.env["XDG_CONFIG_HOME"] || path12.join(home, ".config"),
|
|
14278
|
+
path12.join(home, "Documents"),
|
|
14279
|
+
path12.join(home, "Downloads")
|
|
14280
|
+
];
|
|
14281
|
+
const timeoutPromise = new Promise(
|
|
14282
|
+
(resolve) => setTimeout(() => {
|
|
14273
14283
|
logWarn(
|
|
14274
14284
|
`MCP config search timed out after ${MCP_SYSTEM_FIND_TIMEOUT_MS / 1e3}s`
|
|
14275
14285
|
);
|
|
14276
14286
|
resolve([]);
|
|
14277
|
-
}, MCP_SYSTEM_FIND_TIMEOUT_MS)
|
|
14278
|
-
|
|
14279
|
-
|
|
14280
|
-
|
|
14281
|
-
|
|
14282
|
-
|
|
14283
|
-
|
|
14284
|
-
|
|
14285
|
-
}
|
|
14286
|
-
});
|
|
14287
|
-
child.on("error", (err) => {
|
|
14288
|
-
clearTimeout(timer);
|
|
14289
|
-
logWarn("MCP config search failed to start", { err });
|
|
14290
|
-
resolve([]);
|
|
14291
|
-
});
|
|
14292
|
-
child.on("close", (code) => {
|
|
14293
|
-
clearTimeout(timer);
|
|
14294
|
-
if (code === 0 || output.trim().length > 0) {
|
|
14295
|
-
const files = output.split(/\r?\n/).map((f) => f.trim()).filter(Boolean);
|
|
14296
|
-
resolve(files);
|
|
14297
|
-
} else {
|
|
14298
|
-
if (errorOutput.trim().length > 0) {
|
|
14299
|
-
logWarn("MCP config search finished with warnings", { errorOutput });
|
|
14300
|
-
}
|
|
14301
|
-
resolve([]);
|
|
14302
|
-
}
|
|
14303
|
-
});
|
|
14304
|
-
});
|
|
14287
|
+
}, MCP_SYSTEM_FIND_TIMEOUT_MS)
|
|
14288
|
+
);
|
|
14289
|
+
const searchPromise = Promise.all(
|
|
14290
|
+
knownDirs.map(
|
|
14291
|
+
(dir) => fs12.existsSync(dir) ? searchDir(dir) : Promise.resolve([])
|
|
14292
|
+
)
|
|
14293
|
+
).then((results) => results.flat());
|
|
14294
|
+
return await Promise.race([timeoutPromise, searchPromise]);
|
|
14305
14295
|
} catch (err) {
|
|
14306
14296
|
logWarn("MCP config search unexpected error", { err });
|
|
14307
14297
|
return [];
|
|
@@ -14897,6 +14887,12 @@ var McpServer = class {
|
|
|
14897
14887
|
}
|
|
14898
14888
|
}
|
|
14899
14889
|
async handleListPromptsRequest(request) {
|
|
14890
|
+
const mcpCheckerTool = this.toolRegistry.getToolDefinition(MCP_TOOL_CHECKER);
|
|
14891
|
+
if (mcpCheckerTool) {
|
|
14892
|
+
return {
|
|
14893
|
+
prompts: []
|
|
14894
|
+
};
|
|
14895
|
+
}
|
|
14900
14896
|
logInfo("Received list_prompts request");
|
|
14901
14897
|
logDebug("list_prompts request", {
|
|
14902
14898
|
request: JSON.parse(JSON.stringify(request))
|
|
@@ -16699,8 +16695,8 @@ For a complete security audit workflow, use the \`full-security-audit\` prompt.
|
|
|
16699
16695
|
import { z as z40 } from "zod";
|
|
16700
16696
|
|
|
16701
16697
|
// src/mcp/services/PathValidation.ts
|
|
16702
|
-
import
|
|
16703
|
-
import
|
|
16698
|
+
import fs13 from "fs";
|
|
16699
|
+
import path13 from "path";
|
|
16704
16700
|
async function validatePath(inputPath) {
|
|
16705
16701
|
logDebug("Validating MCP path", { inputPath });
|
|
16706
16702
|
if (/^\/[a-zA-Z]:\//.test(inputPath)) {
|
|
@@ -16732,7 +16728,7 @@ async function validatePath(inputPath) {
|
|
|
16732
16728
|
logError(error);
|
|
16733
16729
|
return { isValid: false, error, path: inputPath };
|
|
16734
16730
|
}
|
|
16735
|
-
const normalizedPath =
|
|
16731
|
+
const normalizedPath = path13.normalize(inputPath);
|
|
16736
16732
|
if (normalizedPath.includes("..")) {
|
|
16737
16733
|
const error = `Normalized path contains path traversal patterns: ${inputPath}`;
|
|
16738
16734
|
logError(error);
|
|
@@ -16759,7 +16755,7 @@ async function validatePath(inputPath) {
|
|
|
16759
16755
|
logDebug("Path validation successful", { inputPath });
|
|
16760
16756
|
logDebug("Checking path existence", { inputPath });
|
|
16761
16757
|
try {
|
|
16762
|
-
await
|
|
16758
|
+
await fs13.promises.access(inputPath);
|
|
16763
16759
|
logDebug("Path exists and is accessible", { inputPath });
|
|
16764
16760
|
WorkspaceService.setKnownWorkspacePath(inputPath);
|
|
16765
16761
|
logDebug("Stored validated path in WorkspaceService", { inputPath });
|
|
@@ -17383,10 +17379,10 @@ If you wish to scan files that were recently changed in your git history call th
|
|
|
17383
17379
|
init_FileUtils();
|
|
17384
17380
|
init_GitService();
|
|
17385
17381
|
init_configs();
|
|
17386
|
-
import
|
|
17382
|
+
import fs14 from "fs/promises";
|
|
17387
17383
|
import nodePath from "path";
|
|
17388
17384
|
var getLocalFiles = async ({
|
|
17389
|
-
path:
|
|
17385
|
+
path: path18,
|
|
17390
17386
|
maxFileSize = MCP_MAX_FILE_SIZE,
|
|
17391
17387
|
maxFiles,
|
|
17392
17388
|
isAllFilesScan,
|
|
@@ -17394,17 +17390,17 @@ var getLocalFiles = async ({
|
|
|
17394
17390
|
scanRecentlyChangedFiles
|
|
17395
17391
|
}) => {
|
|
17396
17392
|
logDebug(`[${scanContext}] Starting getLocalFiles`, {
|
|
17397
|
-
path:
|
|
17393
|
+
path: path18,
|
|
17398
17394
|
maxFileSize,
|
|
17399
17395
|
maxFiles,
|
|
17400
17396
|
isAllFilesScan,
|
|
17401
17397
|
scanRecentlyChangedFiles
|
|
17402
17398
|
});
|
|
17403
17399
|
try {
|
|
17404
|
-
const resolvedRepoPath = await
|
|
17400
|
+
const resolvedRepoPath = await fs14.realpath(path18);
|
|
17405
17401
|
logDebug(`[${scanContext}] Resolved repository path`, {
|
|
17406
17402
|
resolvedRepoPath,
|
|
17407
|
-
originalPath:
|
|
17403
|
+
originalPath: path18
|
|
17408
17404
|
});
|
|
17409
17405
|
const gitService = new GitService(resolvedRepoPath, log);
|
|
17410
17406
|
const gitValidation = await gitService.validateRepository();
|
|
@@ -17417,7 +17413,7 @@ var getLocalFiles = async ({
|
|
|
17417
17413
|
if (!gitValidation.isValid || isAllFilesScan) {
|
|
17418
17414
|
try {
|
|
17419
17415
|
files = await FileUtils.getLastChangedFiles({
|
|
17420
|
-
dir:
|
|
17416
|
+
dir: path18,
|
|
17421
17417
|
maxFileSize,
|
|
17422
17418
|
maxFiles,
|
|
17423
17419
|
isAllFilesScan
|
|
@@ -17481,7 +17477,7 @@ var getLocalFiles = async ({
|
|
|
17481
17477
|
absoluteFilePath
|
|
17482
17478
|
);
|
|
17483
17479
|
try {
|
|
17484
|
-
const fileStat = await
|
|
17480
|
+
const fileStat = await fs14.stat(absoluteFilePath);
|
|
17485
17481
|
return {
|
|
17486
17482
|
filename: nodePath.basename(absoluteFilePath),
|
|
17487
17483
|
relativePath,
|
|
@@ -17509,15 +17505,15 @@ var getLocalFiles = async ({
|
|
|
17509
17505
|
logError(`${scanContext}Unexpected error in getLocalFiles`, {
|
|
17510
17506
|
error: error instanceof Error ? error.message : String(error),
|
|
17511
17507
|
stack: error instanceof Error ? error.stack : void 0,
|
|
17512
|
-
path:
|
|
17508
|
+
path: path18
|
|
17513
17509
|
});
|
|
17514
17510
|
throw error;
|
|
17515
17511
|
}
|
|
17516
17512
|
};
|
|
17517
17513
|
|
|
17518
17514
|
// src/mcp/services/LocalMobbFolderService.ts
|
|
17519
|
-
import
|
|
17520
|
-
import
|
|
17515
|
+
import fs15 from "fs";
|
|
17516
|
+
import path14 from "path";
|
|
17521
17517
|
import { z as z39 } from "zod";
|
|
17522
17518
|
init_GitService();
|
|
17523
17519
|
function extractPathFromPatch(patch) {
|
|
@@ -17604,19 +17600,19 @@ var LocalMobbFolderService = class {
|
|
|
17604
17600
|
"[LocalMobbFolderService] Non-git repository detected, skipping .gitignore operations"
|
|
17605
17601
|
);
|
|
17606
17602
|
}
|
|
17607
|
-
const mobbFolderPath =
|
|
17603
|
+
const mobbFolderPath = path14.join(
|
|
17608
17604
|
this.repoPath,
|
|
17609
17605
|
this.defaultMobbFolderName
|
|
17610
17606
|
);
|
|
17611
|
-
if (!
|
|
17607
|
+
if (!fs15.existsSync(mobbFolderPath)) {
|
|
17612
17608
|
logInfo("[LocalMobbFolderService] Creating .mobb folder", {
|
|
17613
17609
|
mobbFolderPath
|
|
17614
17610
|
});
|
|
17615
|
-
|
|
17611
|
+
fs15.mkdirSync(mobbFolderPath, { recursive: true });
|
|
17616
17612
|
} else {
|
|
17617
17613
|
logDebug("[LocalMobbFolderService] .mobb folder already exists");
|
|
17618
17614
|
}
|
|
17619
|
-
const stats =
|
|
17615
|
+
const stats = fs15.statSync(mobbFolderPath);
|
|
17620
17616
|
if (!stats.isDirectory()) {
|
|
17621
17617
|
throw new Error(`Path exists but is not a directory: ${mobbFolderPath}`);
|
|
17622
17618
|
}
|
|
@@ -17657,13 +17653,13 @@ var LocalMobbFolderService = class {
|
|
|
17657
17653
|
logDebug("[LocalMobbFolderService] Git repository validated successfully");
|
|
17658
17654
|
} else {
|
|
17659
17655
|
try {
|
|
17660
|
-
const stats =
|
|
17656
|
+
const stats = fs15.statSync(this.repoPath);
|
|
17661
17657
|
if (!stats.isDirectory()) {
|
|
17662
17658
|
throw new Error(
|
|
17663
17659
|
`Path exists but is not a directory: ${this.repoPath}`
|
|
17664
17660
|
);
|
|
17665
17661
|
}
|
|
17666
|
-
|
|
17662
|
+
fs15.accessSync(this.repoPath, fs15.constants.R_OK | fs15.constants.W_OK);
|
|
17667
17663
|
logDebug(
|
|
17668
17664
|
"[LocalMobbFolderService] Non-git directory validated successfully"
|
|
17669
17665
|
);
|
|
@@ -17776,8 +17772,8 @@ var LocalMobbFolderService = class {
|
|
|
17776
17772
|
mobbFolderPath,
|
|
17777
17773
|
baseFileName
|
|
17778
17774
|
);
|
|
17779
|
-
const filePath =
|
|
17780
|
-
await
|
|
17775
|
+
const filePath = path14.join(mobbFolderPath, uniqueFileName);
|
|
17776
|
+
await fs15.promises.writeFile(filePath, patch, "utf8");
|
|
17781
17777
|
logInfo("[LocalMobbFolderService] Patch saved successfully", {
|
|
17782
17778
|
filePath,
|
|
17783
17779
|
fileName: uniqueFileName,
|
|
@@ -17834,11 +17830,11 @@ var LocalMobbFolderService = class {
|
|
|
17834
17830
|
* @returns Unique filename that doesn't conflict with existing files
|
|
17835
17831
|
*/
|
|
17836
17832
|
getUniqueFileName(folderPath, baseFileName) {
|
|
17837
|
-
const baseName =
|
|
17838
|
-
const extension =
|
|
17833
|
+
const baseName = path14.parse(baseFileName).name;
|
|
17834
|
+
const extension = path14.parse(baseFileName).ext;
|
|
17839
17835
|
let uniqueFileName = baseFileName;
|
|
17840
17836
|
let index = 1;
|
|
17841
|
-
while (
|
|
17837
|
+
while (fs15.existsSync(path14.join(folderPath, uniqueFileName))) {
|
|
17842
17838
|
uniqueFileName = `${baseName}-${index}${extension}`;
|
|
17843
17839
|
index++;
|
|
17844
17840
|
if (index > 1e3) {
|
|
@@ -17869,18 +17865,18 @@ var LocalMobbFolderService = class {
|
|
|
17869
17865
|
logDebug("[LocalMobbFolderService] Logging patch info", { fixId: fix.id });
|
|
17870
17866
|
try {
|
|
17871
17867
|
const mobbFolderPath = await this.getFolder();
|
|
17872
|
-
const patchInfoPath =
|
|
17868
|
+
const patchInfoPath = path14.join(mobbFolderPath, "patchInfo.md");
|
|
17873
17869
|
const markdownContent = this.generateFixMarkdown(fix, savedPatchFileName);
|
|
17874
17870
|
let existingContent = "";
|
|
17875
|
-
if (
|
|
17876
|
-
existingContent = await
|
|
17871
|
+
if (fs15.existsSync(patchInfoPath)) {
|
|
17872
|
+
existingContent = await fs15.promises.readFile(patchInfoPath, "utf8");
|
|
17877
17873
|
logDebug("[LocalMobbFolderService] Existing patchInfo.md found");
|
|
17878
17874
|
} else {
|
|
17879
17875
|
logDebug("[LocalMobbFolderService] Creating new patchInfo.md file");
|
|
17880
17876
|
}
|
|
17881
17877
|
const separator = existingContent ? "\n\n================================================================================\n\n" : "";
|
|
17882
17878
|
const updatedContent = `${markdownContent}${separator}${existingContent}`;
|
|
17883
|
-
await
|
|
17879
|
+
await fs15.promises.writeFile(patchInfoPath, updatedContent, "utf8");
|
|
17884
17880
|
logInfo("[LocalMobbFolderService] Patch info logged successfully", {
|
|
17885
17881
|
patchInfoPath,
|
|
17886
17882
|
fixId: fix.id,
|
|
@@ -17911,7 +17907,7 @@ var LocalMobbFolderService = class {
|
|
|
17911
17907
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
17912
17908
|
const patch = this.extractPatchFromFix(fix);
|
|
17913
17909
|
const relativePatchedFilePath = patch ? extractPathFromPatch(patch) : null;
|
|
17914
|
-
const patchedFilePath = relativePatchedFilePath ?
|
|
17910
|
+
const patchedFilePath = relativePatchedFilePath ? path14.resolve(this.repoPath, relativePatchedFilePath) : null;
|
|
17915
17911
|
const fixIdentifier = savedPatchFileName ? savedPatchFileName.replace(".patch", "") : fix.id;
|
|
17916
17912
|
let markdown = `# Fix ${fixIdentifier}
|
|
17917
17913
|
|
|
@@ -18253,16 +18249,16 @@ import {
|
|
|
18253
18249
|
unlinkSync,
|
|
18254
18250
|
writeFileSync
|
|
18255
18251
|
} from "fs";
|
|
18256
|
-
import
|
|
18252
|
+
import fs16 from "fs/promises";
|
|
18257
18253
|
import parseDiff2 from "parse-diff";
|
|
18258
|
-
import
|
|
18254
|
+
import path15 from "path";
|
|
18259
18255
|
var PatchApplicationService = class {
|
|
18260
18256
|
/**
|
|
18261
18257
|
* Gets the appropriate comment syntax for a file based on its extension
|
|
18262
18258
|
*/
|
|
18263
18259
|
static getCommentSyntax(filePath) {
|
|
18264
|
-
const ext =
|
|
18265
|
-
const basename2 =
|
|
18260
|
+
const ext = path15.extname(filePath).toLowerCase();
|
|
18261
|
+
const basename2 = path15.basename(filePath);
|
|
18266
18262
|
const commentMap = {
|
|
18267
18263
|
// C-style languages (single line comments)
|
|
18268
18264
|
".js": "//",
|
|
@@ -18465,7 +18461,7 @@ var PatchApplicationService = class {
|
|
|
18465
18461
|
}
|
|
18466
18462
|
);
|
|
18467
18463
|
}
|
|
18468
|
-
const dirPath =
|
|
18464
|
+
const dirPath = path15.dirname(filePath);
|
|
18469
18465
|
mkdirSync(dirPath, { recursive: true });
|
|
18470
18466
|
writeFileSync(filePath, finalContent, "utf8");
|
|
18471
18467
|
return filePath;
|
|
@@ -18749,9 +18745,9 @@ var PatchApplicationService = class {
|
|
|
18749
18745
|
continue;
|
|
18750
18746
|
}
|
|
18751
18747
|
try {
|
|
18752
|
-
const absolutePath =
|
|
18748
|
+
const absolutePath = path15.resolve(repositoryPath, targetFile);
|
|
18753
18749
|
if (existsSync2(absolutePath)) {
|
|
18754
|
-
const stats = await
|
|
18750
|
+
const stats = await fs16.stat(absolutePath);
|
|
18755
18751
|
const fileModTime = stats.mtime.getTime();
|
|
18756
18752
|
if (fileModTime > scanStartTime) {
|
|
18757
18753
|
logError(
|
|
@@ -18792,7 +18788,7 @@ var PatchApplicationService = class {
|
|
|
18792
18788
|
const appliedFixes = [];
|
|
18793
18789
|
const failedFixes = [];
|
|
18794
18790
|
const skippedFixes = [];
|
|
18795
|
-
const resolvedRepoPath = await
|
|
18791
|
+
const resolvedRepoPath = await fs16.realpath(repositoryPath);
|
|
18796
18792
|
logInfo(
|
|
18797
18793
|
`[${scanContext}] Starting patch application for ${fixes.length} fixes`,
|
|
18798
18794
|
{
|
|
@@ -18940,11 +18936,11 @@ var PatchApplicationService = class {
|
|
|
18940
18936
|
}) {
|
|
18941
18937
|
const sanitizedRepoPath = String(repositoryPath || "").replace("\0", "").replace(/^(\.\.(\/|\\))+/, "");
|
|
18942
18938
|
const sanitizedTargetFile = String(targetFile || "").replace("\0", "").replace(/^(\.\.(\/|\\))+/, "");
|
|
18943
|
-
const absoluteFilePath =
|
|
18939
|
+
const absoluteFilePath = path15.resolve(
|
|
18944
18940
|
sanitizedRepoPath,
|
|
18945
18941
|
sanitizedTargetFile
|
|
18946
18942
|
);
|
|
18947
|
-
const relativePath =
|
|
18943
|
+
const relativePath = path15.relative(sanitizedRepoPath, absoluteFilePath);
|
|
18948
18944
|
if (relativePath.startsWith("..")) {
|
|
18949
18945
|
throw new Error(
|
|
18950
18946
|
`Security violation: target file ${targetFile} resolves outside repository`
|
|
@@ -18978,7 +18974,7 @@ var PatchApplicationService = class {
|
|
|
18978
18974
|
fix,
|
|
18979
18975
|
scanContext
|
|
18980
18976
|
});
|
|
18981
|
-
appliedFiles.push(
|
|
18977
|
+
appliedFiles.push(path15.relative(repositoryPath, actualPath));
|
|
18982
18978
|
logDebug(`[${scanContext}] Created new file: ${relativePath}`);
|
|
18983
18979
|
}
|
|
18984
18980
|
/**
|
|
@@ -19026,7 +19022,7 @@ var PatchApplicationService = class {
|
|
|
19026
19022
|
fix,
|
|
19027
19023
|
scanContext
|
|
19028
19024
|
});
|
|
19029
|
-
appliedFiles.push(
|
|
19025
|
+
appliedFiles.push(path15.relative(repositoryPath, actualPath));
|
|
19030
19026
|
logDebug(`[${scanContext}] Modified file: ${relativePath}`);
|
|
19031
19027
|
}
|
|
19032
19028
|
}
|
|
@@ -19221,8 +19217,8 @@ init_configs();
|
|
|
19221
19217
|
|
|
19222
19218
|
// src/mcp/services/FileOperations.ts
|
|
19223
19219
|
init_FileUtils();
|
|
19224
|
-
import
|
|
19225
|
-
import
|
|
19220
|
+
import fs17 from "fs";
|
|
19221
|
+
import path16 from "path";
|
|
19226
19222
|
import AdmZip2 from "adm-zip";
|
|
19227
19223
|
var FileOperations = class {
|
|
19228
19224
|
/**
|
|
@@ -19242,10 +19238,10 @@ var FileOperations = class {
|
|
|
19242
19238
|
let packedFilesCount = 0;
|
|
19243
19239
|
const packedFiles = [];
|
|
19244
19240
|
const excludedFiles = [];
|
|
19245
|
-
const resolvedRepoPath =
|
|
19241
|
+
const resolvedRepoPath = path16.resolve(repositoryPath);
|
|
19246
19242
|
for (const filepath of fileList) {
|
|
19247
|
-
const absoluteFilepath =
|
|
19248
|
-
const resolvedFilePath =
|
|
19243
|
+
const absoluteFilepath = path16.join(repositoryPath, filepath);
|
|
19244
|
+
const resolvedFilePath = path16.resolve(absoluteFilepath);
|
|
19249
19245
|
if (!resolvedFilePath.startsWith(resolvedRepoPath)) {
|
|
19250
19246
|
const reason = "potential path traversal security risk";
|
|
19251
19247
|
logDebug(`[FileOperations] Skipping ${filepath} due to ${reason}`);
|
|
@@ -19292,11 +19288,11 @@ var FileOperations = class {
|
|
|
19292
19288
|
fileList,
|
|
19293
19289
|
repositoryPath
|
|
19294
19290
|
}) {
|
|
19295
|
-
const resolvedRepoPath =
|
|
19291
|
+
const resolvedRepoPath = path16.resolve(repositoryPath);
|
|
19296
19292
|
const validatedPaths = [];
|
|
19297
19293
|
for (const filepath of fileList) {
|
|
19298
|
-
const absoluteFilepath =
|
|
19299
|
-
const resolvedFilePath =
|
|
19294
|
+
const absoluteFilepath = path16.join(repositoryPath, filepath);
|
|
19295
|
+
const resolvedFilePath = path16.resolve(absoluteFilepath);
|
|
19300
19296
|
if (!resolvedFilePath.startsWith(resolvedRepoPath)) {
|
|
19301
19297
|
logDebug(
|
|
19302
19298
|
`[FileOperations] Rejecting ${filepath} - path traversal attempt detected`
|
|
@@ -19304,7 +19300,7 @@ var FileOperations = class {
|
|
|
19304
19300
|
continue;
|
|
19305
19301
|
}
|
|
19306
19302
|
try {
|
|
19307
|
-
await
|
|
19303
|
+
await fs17.promises.access(absoluteFilepath, fs17.constants.R_OK);
|
|
19308
19304
|
validatedPaths.push(filepath);
|
|
19309
19305
|
} catch (error) {
|
|
19310
19306
|
logDebug(
|
|
@@ -19323,8 +19319,8 @@ var FileOperations = class {
|
|
|
19323
19319
|
const fileDataArray = [];
|
|
19324
19320
|
for (const absolutePath of filePaths) {
|
|
19325
19321
|
try {
|
|
19326
|
-
const content = await
|
|
19327
|
-
const relativePath =
|
|
19322
|
+
const content = await fs17.promises.readFile(absolutePath);
|
|
19323
|
+
const relativePath = path16.basename(absolutePath);
|
|
19328
19324
|
fileDataArray.push({
|
|
19329
19325
|
relativePath,
|
|
19330
19326
|
absolutePath,
|
|
@@ -19349,7 +19345,7 @@ var FileOperations = class {
|
|
|
19349
19345
|
relativeFilepath
|
|
19350
19346
|
}) {
|
|
19351
19347
|
try {
|
|
19352
|
-
return await
|
|
19348
|
+
return await fs17.promises.readFile(absoluteFilepath);
|
|
19353
19349
|
} catch (fsError) {
|
|
19354
19350
|
logError(
|
|
19355
19351
|
`[FileOperations] Failed to read ${relativeFilepath} from filesystem: ${fsError}`
|
|
@@ -19636,14 +19632,14 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
19636
19632
|
* since the last scan.
|
|
19637
19633
|
*/
|
|
19638
19634
|
async scanForSecurityVulnerabilities({
|
|
19639
|
-
path:
|
|
19635
|
+
path: path18,
|
|
19640
19636
|
isAllDetectionRulesScan,
|
|
19641
19637
|
isAllFilesScan,
|
|
19642
19638
|
scanContext
|
|
19643
19639
|
}) {
|
|
19644
19640
|
this.hasAuthenticationFailed = false;
|
|
19645
19641
|
logDebug(`[${scanContext}] Scanning for new security vulnerabilities`, {
|
|
19646
|
-
path:
|
|
19642
|
+
path: path18
|
|
19647
19643
|
});
|
|
19648
19644
|
if (!this.gqlClient) {
|
|
19649
19645
|
logInfo(`[${scanContext}] No GQL client found, skipping scan`);
|
|
@@ -19659,11 +19655,11 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
19659
19655
|
}
|
|
19660
19656
|
logDebug(
|
|
19661
19657
|
`[${scanContext}] Connected to the API, assembling list of files to scan`,
|
|
19662
|
-
{ path:
|
|
19658
|
+
{ path: path18 }
|
|
19663
19659
|
);
|
|
19664
19660
|
const isBackgroundScan = scanContext === ScanContext.BACKGROUND_INITIAL || scanContext === ScanContext.BACKGROUND_PERIODIC;
|
|
19665
19661
|
const files = await getLocalFiles({
|
|
19666
|
-
path:
|
|
19662
|
+
path: path18,
|
|
19667
19663
|
isAllFilesScan,
|
|
19668
19664
|
scanContext,
|
|
19669
19665
|
scanRecentlyChangedFiles: !isBackgroundScan
|
|
@@ -19689,13 +19685,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
19689
19685
|
});
|
|
19690
19686
|
const { fixReportId, projectId } = await scanFiles({
|
|
19691
19687
|
fileList: filesToScan.map((file) => file.relativePath),
|
|
19692
|
-
repositoryPath:
|
|
19688
|
+
repositoryPath: path18,
|
|
19693
19689
|
gqlClient: this.gqlClient,
|
|
19694
19690
|
isAllDetectionRulesScan,
|
|
19695
19691
|
scanContext
|
|
19696
19692
|
});
|
|
19697
19693
|
logInfo(
|
|
19698
|
-
`[${scanContext}] Security scan completed for ${
|
|
19694
|
+
`[${scanContext}] Security scan completed for ${path18} reportId: ${fixReportId} projectId: ${projectId}`
|
|
19699
19695
|
);
|
|
19700
19696
|
if (isAllFilesScan) {
|
|
19701
19697
|
return;
|
|
@@ -19989,13 +19985,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
19989
19985
|
});
|
|
19990
19986
|
return scannedFiles.some((file) => file.relativePath === fixFile);
|
|
19991
19987
|
}
|
|
19992
|
-
async getFreshFixes({ path:
|
|
19988
|
+
async getFreshFixes({ path: path18 }) {
|
|
19993
19989
|
const scanContext = ScanContext.USER_REQUEST;
|
|
19994
|
-
logDebug(`[${scanContext}] Getting fresh fixes`, { path:
|
|
19995
|
-
if (this.path !==
|
|
19996
|
-
this.path =
|
|
19990
|
+
logDebug(`[${scanContext}] Getting fresh fixes`, { path: path18 });
|
|
19991
|
+
if (this.path !== path18) {
|
|
19992
|
+
this.path = path18;
|
|
19997
19993
|
this.reset();
|
|
19998
|
-
logInfo(`[${scanContext}] Reset service state for new path`, { path:
|
|
19994
|
+
logInfo(`[${scanContext}] Reset service state for new path`, { path: path18 });
|
|
19999
19995
|
}
|
|
20000
19996
|
try {
|
|
20001
19997
|
this.gqlClient = await createAuthenticatedMcpGQLClient();
|
|
@@ -20013,7 +20009,7 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
20013
20009
|
}
|
|
20014
20010
|
throw error;
|
|
20015
20011
|
}
|
|
20016
|
-
this.triggerScan({ path:
|
|
20012
|
+
this.triggerScan({ path: path18, gqlClient: this.gqlClient });
|
|
20017
20013
|
let isMvsAutoFixEnabled = null;
|
|
20018
20014
|
try {
|
|
20019
20015
|
isMvsAutoFixEnabled = await this.gqlClient.getMvsAutoFixSettings();
|
|
@@ -20047,33 +20043,33 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
20047
20043
|
return noFreshFixesPrompt;
|
|
20048
20044
|
}
|
|
20049
20045
|
triggerScan({
|
|
20050
|
-
path:
|
|
20046
|
+
path: path18,
|
|
20051
20047
|
gqlClient
|
|
20052
20048
|
}) {
|
|
20053
|
-
if (this.path !==
|
|
20054
|
-
this.path =
|
|
20049
|
+
if (this.path !== path18) {
|
|
20050
|
+
this.path = path18;
|
|
20055
20051
|
this.reset();
|
|
20056
|
-
logInfo(`Reset service state for new path in triggerScan`, { path:
|
|
20052
|
+
logInfo(`Reset service state for new path in triggerScan`, { path: path18 });
|
|
20057
20053
|
}
|
|
20058
20054
|
this.gqlClient = gqlClient;
|
|
20059
20055
|
if (!this.intervalId) {
|
|
20060
|
-
this.startPeriodicScanning(
|
|
20061
|
-
this.executeInitialScan(
|
|
20062
|
-
void this.executeInitialFullScan(
|
|
20056
|
+
this.startPeriodicScanning(path18);
|
|
20057
|
+
this.executeInitialScan(path18);
|
|
20058
|
+
void this.executeInitialFullScan(path18);
|
|
20063
20059
|
}
|
|
20064
20060
|
}
|
|
20065
|
-
startPeriodicScanning(
|
|
20061
|
+
startPeriodicScanning(path18) {
|
|
20066
20062
|
const scanContext = ScanContext.BACKGROUND_PERIODIC;
|
|
20067
20063
|
logDebug(
|
|
20068
20064
|
`[${scanContext}] Starting periodic scan for new security vulnerabilities`,
|
|
20069
20065
|
{
|
|
20070
|
-
path:
|
|
20066
|
+
path: path18
|
|
20071
20067
|
}
|
|
20072
20068
|
);
|
|
20073
20069
|
this.intervalId = setInterval(() => {
|
|
20074
|
-
logDebug(`[${scanContext}] Triggering periodic security scan`, { path:
|
|
20070
|
+
logDebug(`[${scanContext}] Triggering periodic security scan`, { path: path18 });
|
|
20075
20071
|
this.scanForSecurityVulnerabilities({
|
|
20076
|
-
path:
|
|
20072
|
+
path: path18,
|
|
20077
20073
|
scanContext
|
|
20078
20074
|
}).catch((error) => {
|
|
20079
20075
|
logError(`[${scanContext}] Error during periodic security scan`, {
|
|
@@ -20082,45 +20078,45 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
20082
20078
|
});
|
|
20083
20079
|
}, MCP_PERIODIC_CHECK_INTERVAL);
|
|
20084
20080
|
}
|
|
20085
|
-
async executeInitialFullScan(
|
|
20081
|
+
async executeInitialFullScan(path18) {
|
|
20086
20082
|
const scanContext = ScanContext.FULL_SCAN;
|
|
20087
|
-
logDebug(`[${scanContext}] Triggering initial full security scan`, { path:
|
|
20083
|
+
logDebug(`[${scanContext}] Triggering initial full security scan`, { path: path18 });
|
|
20088
20084
|
logDebug(`[${scanContext}] Full scan paths scanned`, {
|
|
20089
20085
|
fullScanPathsScanned: this.fullScanPathsScanned
|
|
20090
20086
|
});
|
|
20091
|
-
if (this.fullScanPathsScanned.includes(
|
|
20087
|
+
if (this.fullScanPathsScanned.includes(path18)) {
|
|
20092
20088
|
logDebug(`[${scanContext}] Full scan already executed for this path`, {
|
|
20093
|
-
path:
|
|
20089
|
+
path: path18
|
|
20094
20090
|
});
|
|
20095
20091
|
return;
|
|
20096
20092
|
}
|
|
20097
20093
|
configStore.set("fullScanPathsScanned", [
|
|
20098
20094
|
...this.fullScanPathsScanned,
|
|
20099
|
-
|
|
20095
|
+
path18
|
|
20100
20096
|
]);
|
|
20101
20097
|
try {
|
|
20102
20098
|
await this.scanForSecurityVulnerabilities({
|
|
20103
|
-
path:
|
|
20099
|
+
path: path18,
|
|
20104
20100
|
isAllFilesScan: true,
|
|
20105
20101
|
isAllDetectionRulesScan: true,
|
|
20106
20102
|
scanContext: ScanContext.FULL_SCAN
|
|
20107
20103
|
});
|
|
20108
|
-
if (!this.fullScanPathsScanned.includes(
|
|
20109
|
-
this.fullScanPathsScanned.push(
|
|
20104
|
+
if (!this.fullScanPathsScanned.includes(path18)) {
|
|
20105
|
+
this.fullScanPathsScanned.push(path18);
|
|
20110
20106
|
configStore.set("fullScanPathsScanned", this.fullScanPathsScanned);
|
|
20111
20107
|
}
|
|
20112
|
-
logInfo(`[${scanContext}] Full scan completed`, { path:
|
|
20108
|
+
logInfo(`[${scanContext}] Full scan completed`, { path: path18 });
|
|
20113
20109
|
} catch (error) {
|
|
20114
20110
|
logError(`[${scanContext}] Error during initial full security scan`, {
|
|
20115
20111
|
error
|
|
20116
20112
|
});
|
|
20117
20113
|
}
|
|
20118
20114
|
}
|
|
20119
|
-
executeInitialScan(
|
|
20115
|
+
executeInitialScan(path18) {
|
|
20120
20116
|
const scanContext = ScanContext.BACKGROUND_INITIAL;
|
|
20121
|
-
logDebug(`[${scanContext}] Triggering initial security scan`, { path:
|
|
20117
|
+
logDebug(`[${scanContext}] Triggering initial security scan`, { path: path18 });
|
|
20122
20118
|
this.scanForSecurityVulnerabilities({
|
|
20123
|
-
path:
|
|
20119
|
+
path: path18,
|
|
20124
20120
|
scanContext: ScanContext.BACKGROUND_INITIAL
|
|
20125
20121
|
}).catch((error) => {
|
|
20126
20122
|
logError(`[${scanContext}] Error during initial security scan`, { error });
|
|
@@ -20217,9 +20213,9 @@ Example payload:
|
|
|
20217
20213
|
`Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
|
|
20218
20214
|
);
|
|
20219
20215
|
}
|
|
20220
|
-
const
|
|
20216
|
+
const path18 = pathValidationResult.path;
|
|
20221
20217
|
const resultText = await this.newFixesService.getFreshFixes({
|
|
20222
|
-
path:
|
|
20218
|
+
path: path18
|
|
20223
20219
|
});
|
|
20224
20220
|
logInfo("CheckForNewAvailableFixesTool execution completed", {
|
|
20225
20221
|
resultText
|
|
@@ -20396,8 +20392,8 @@ Call this tool instead of ${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES} when you only
|
|
|
20396
20392
|
`Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
|
|
20397
20393
|
);
|
|
20398
20394
|
}
|
|
20399
|
-
const
|
|
20400
|
-
const gitService = new GitService(
|
|
20395
|
+
const path18 = pathValidationResult.path;
|
|
20396
|
+
const gitService = new GitService(path18, log);
|
|
20401
20397
|
const gitValidation = await gitService.validateRepository();
|
|
20402
20398
|
if (!gitValidation.isValid) {
|
|
20403
20399
|
throw new Error(`Invalid git repository: ${gitValidation.error}`);
|
|
@@ -20785,9 +20781,9 @@ Example payload:
|
|
|
20785
20781
|
`Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
|
|
20786
20782
|
);
|
|
20787
20783
|
}
|
|
20788
|
-
const
|
|
20784
|
+
const path18 = pathValidationResult.path;
|
|
20789
20785
|
const files = await getLocalFiles({
|
|
20790
|
-
path:
|
|
20786
|
+
path: path18,
|
|
20791
20787
|
maxFileSize: MCP_MAX_FILE_SIZE,
|
|
20792
20788
|
maxFiles: args.maxFiles,
|
|
20793
20789
|
scanContext: ScanContext.USER_REQUEST,
|
|
@@ -20807,7 +20803,7 @@ Example payload:
|
|
|
20807
20803
|
try {
|
|
20808
20804
|
const fixResult = await this.vulnerabilityFixService.processVulnerabilities({
|
|
20809
20805
|
fileList: files.map((file) => file.relativePath),
|
|
20810
|
-
repositoryPath:
|
|
20806
|
+
repositoryPath: path18,
|
|
20811
20807
|
offset: args.offset,
|
|
20812
20808
|
limit: args.limit,
|
|
20813
20809
|
isRescan: args.rescan || !!args.maxFiles
|
|
@@ -20911,7 +20907,7 @@ var mcpHandler = async (_args) => {
|
|
|
20911
20907
|
};
|
|
20912
20908
|
|
|
20913
20909
|
// src/args/commands/review.ts
|
|
20914
|
-
import
|
|
20910
|
+
import fs18 from "fs";
|
|
20915
20911
|
import chalk9 from "chalk";
|
|
20916
20912
|
function reviewBuilder(yargs2) {
|
|
20917
20913
|
return yargs2.option("f", {
|
|
@@ -20948,7 +20944,7 @@ function reviewBuilder(yargs2) {
|
|
|
20948
20944
|
).help();
|
|
20949
20945
|
}
|
|
20950
20946
|
function validateReviewOptions(argv) {
|
|
20951
|
-
if (!
|
|
20947
|
+
if (!fs18.existsSync(argv.f)) {
|
|
20952
20948
|
throw new CliError(`
|
|
20953
20949
|
Can't access ${chalk9.bold(argv.f)}`);
|
|
20954
20950
|
}
|
|
@@ -21022,7 +21018,7 @@ async function addScmTokenHandler(args) {
|
|
|
21022
21018
|
|
|
21023
21019
|
// src/args/commands/upload_ai_blame.ts
|
|
21024
21020
|
import fsPromises3 from "fs/promises";
|
|
21025
|
-
import
|
|
21021
|
+
import path17 from "path";
|
|
21026
21022
|
import chalk10 from "chalk";
|
|
21027
21023
|
import Configstore6 from "configstore";
|
|
21028
21024
|
import { withFile } from "tmp-promise";
|
|
@@ -21124,8 +21120,8 @@ async function uploadAiBlameHandler(args, exitOnError = true) {
|
|
|
21124
21120
|
throw new Error(errorMsg);
|
|
21125
21121
|
}
|
|
21126
21122
|
sessions.push({
|
|
21127
|
-
promptFileName:
|
|
21128
|
-
inferenceFileName:
|
|
21123
|
+
promptFileName: path17.basename(promptPath),
|
|
21124
|
+
inferenceFileName: path17.basename(inferencePath),
|
|
21129
21125
|
aiResponseAt: responseTimes[i] || nowIso,
|
|
21130
21126
|
model: models[i],
|
|
21131
21127
|
toolName: tools[i]
|