mobbdev 1.0.213 → 1.0.216
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.d.mts +62 -28
- package/dist/args/commands/upload_ai_blame.mjs +61 -15
- package/dist/index.mjs +239 -150
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1371,6 +1371,12 @@ import { z as z14 } from "zod";
|
|
|
1371
1371
|
import { z as z2 } from "zod";
|
|
1372
1372
|
|
|
1373
1373
|
// src/features/analysis/scm/generates/client_generates.ts
|
|
1374
|
+
var AiBlameInferenceType = /* @__PURE__ */ ((AiBlameInferenceType2) => {
|
|
1375
|
+
AiBlameInferenceType2["Chat"] = "CHAT";
|
|
1376
|
+
AiBlameInferenceType2["HumanEdit"] = "HUMAN_EDIT";
|
|
1377
|
+
AiBlameInferenceType2["TabAutocomplete"] = "TAB_AUTOCOMPLETE";
|
|
1378
|
+
return AiBlameInferenceType2;
|
|
1379
|
+
})(AiBlameInferenceType || {});
|
|
1374
1380
|
var FixQuestionInputType = /* @__PURE__ */ ((FixQuestionInputType2) => {
|
|
1375
1381
|
FixQuestionInputType2["Number"] = "NUMBER";
|
|
1376
1382
|
FixQuestionInputType2["Select"] = "SELECT";
|
|
@@ -1820,6 +1826,20 @@ var GetLastOrgAndNamedProjectDocument = `
|
|
|
1820
1826
|
}
|
|
1821
1827
|
}
|
|
1822
1828
|
`;
|
|
1829
|
+
var GetLastOrgDocument = `
|
|
1830
|
+
query getLastOrg($email: String!) {
|
|
1831
|
+
user(where: {email: {_eq: $email}}, limit: 1) {
|
|
1832
|
+
id
|
|
1833
|
+
name
|
|
1834
|
+
userOrganizationsAndUserOrganizationRoles(order_by: {createdOn: desc}) {
|
|
1835
|
+
id
|
|
1836
|
+
organization {
|
|
1837
|
+
id
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
`;
|
|
1823
1843
|
var GetEncryptedApiTokenDocument = `
|
|
1824
1844
|
query GetEncryptedApiToken($loginId: uuid!) {
|
|
1825
1845
|
cli_login_by_pk(id: $loginId) {
|
|
@@ -2315,6 +2335,9 @@ function getSdk(client, withWrapper = defaultWrapper) {
|
|
|
2315
2335
|
getLastOrgAndNamedProject(variables, requestHeaders, signal) {
|
|
2316
2336
|
return withWrapper((wrappedRequestHeaders) => client.request({ document: GetLastOrgAndNamedProjectDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "getLastOrgAndNamedProject", "query", variables);
|
|
2317
2337
|
},
|
|
2338
|
+
getLastOrg(variables, requestHeaders, signal) {
|
|
2339
|
+
return withWrapper((wrappedRequestHeaders) => client.request({ document: GetLastOrgDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "getLastOrg", "query", variables);
|
|
2340
|
+
},
|
|
2318
2341
|
GetEncryptedApiToken(variables, requestHeaders, signal) {
|
|
2319
2342
|
return withWrapper((wrappedRequestHeaders) => client.request({ document: GetEncryptedApiTokenDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "GetEncryptedApiToken", "query", variables);
|
|
2320
2343
|
},
|
|
@@ -6224,7 +6247,7 @@ async function getAdoSdk(params) {
|
|
|
6224
6247
|
const url = new URL(repoUrl);
|
|
6225
6248
|
const origin2 = url.origin.toLowerCase().endsWith(".visualstudio.com") ? DEFUALT_ADO_ORIGIN : url.origin.toLowerCase();
|
|
6226
6249
|
const params2 = `path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=commit&versionDescriptor[version]=${branch}&resolveLfs=true&$format=zip&api-version=5.0&download=true`;
|
|
6227
|
-
const
|
|
6250
|
+
const path21 = [
|
|
6228
6251
|
prefixPath,
|
|
6229
6252
|
owner,
|
|
6230
6253
|
projectName,
|
|
@@ -6235,7 +6258,7 @@ async function getAdoSdk(params) {
|
|
|
6235
6258
|
"items",
|
|
6236
6259
|
"items"
|
|
6237
6260
|
].filter(Boolean).join("/");
|
|
6238
|
-
return new URL(`${
|
|
6261
|
+
return new URL(`${path21}?${params2}`, origin2).toString();
|
|
6239
6262
|
},
|
|
6240
6263
|
async getAdoBranchList({ repoUrl }) {
|
|
6241
6264
|
try {
|
|
@@ -7782,14 +7805,14 @@ function getGithubSdk(params = {}) {
|
|
|
7782
7805
|
};
|
|
7783
7806
|
},
|
|
7784
7807
|
async getGithubBlameRanges(params2) {
|
|
7785
|
-
const { ref, gitHubUrl, path:
|
|
7808
|
+
const { ref, gitHubUrl, path: path21 } = params2;
|
|
7786
7809
|
const { owner, repo } = parseGithubOwnerAndRepo(gitHubUrl);
|
|
7787
7810
|
const res = await octokit.graphql(
|
|
7788
7811
|
GET_BLAME_DOCUMENT,
|
|
7789
7812
|
{
|
|
7790
7813
|
owner,
|
|
7791
7814
|
repo,
|
|
7792
|
-
path:
|
|
7815
|
+
path: path21,
|
|
7793
7816
|
ref
|
|
7794
7817
|
}
|
|
7795
7818
|
);
|
|
@@ -7942,6 +7965,23 @@ function getGithubSdk(params = {}) {
|
|
|
7942
7965
|
per_page: 100
|
|
7943
7966
|
});
|
|
7944
7967
|
},
|
|
7968
|
+
async getRecentCommits(params2) {
|
|
7969
|
+
const commits = await octokit.paginate(octokit.rest.repos.listCommits, {
|
|
7970
|
+
owner: params2.owner,
|
|
7971
|
+
repo: params2.repo,
|
|
7972
|
+
since: params2.since,
|
|
7973
|
+
per_page: 100
|
|
7974
|
+
});
|
|
7975
|
+
return { data: commits };
|
|
7976
|
+
},
|
|
7977
|
+
async getRateLimitStatus() {
|
|
7978
|
+
const response = await octokit.rest.rateLimit.get();
|
|
7979
|
+
return {
|
|
7980
|
+
remaining: response.data.rate.remaining,
|
|
7981
|
+
reset: new Date(response.data.rate.reset * 1e3),
|
|
7982
|
+
limit: response.data.rate.limit
|
|
7983
|
+
};
|
|
7984
|
+
},
|
|
7945
7985
|
async getRepoPullRequests(params2) {
|
|
7946
7986
|
return octokit.rest.pulls.list({
|
|
7947
7987
|
owner: params2.owner,
|
|
@@ -8075,6 +8115,14 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
8075
8115
|
const branches = await this.githubSdk.getGithubBranchList(this.url);
|
|
8076
8116
|
return branches.data.map((branch) => branch.name);
|
|
8077
8117
|
}
|
|
8118
|
+
async getRecentCommits(since) {
|
|
8119
|
+
this._validateAccessTokenAndUrl();
|
|
8120
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
8121
|
+
return await this.githubSdk.getRecentCommits({ owner, repo, since });
|
|
8122
|
+
}
|
|
8123
|
+
async getRateLimitStatus() {
|
|
8124
|
+
return await this.githubSdk.getRateLimitStatus();
|
|
8125
|
+
}
|
|
8078
8126
|
get scmLibType() {
|
|
8079
8127
|
return "GITHUB" /* GITHUB */;
|
|
8080
8128
|
}
|
|
@@ -8131,11 +8179,11 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
8131
8179
|
markdownComment: comment
|
|
8132
8180
|
});
|
|
8133
8181
|
}
|
|
8134
|
-
async getRepoBlameRanges(ref,
|
|
8182
|
+
async getRepoBlameRanges(ref, path21) {
|
|
8135
8183
|
this._validateUrl();
|
|
8136
8184
|
return await this.githubSdk.getGithubBlameRanges({
|
|
8137
8185
|
ref,
|
|
8138
|
-
path:
|
|
8186
|
+
path: path21,
|
|
8139
8187
|
gitHubUrl: this.url
|
|
8140
8188
|
});
|
|
8141
8189
|
}
|
|
@@ -8815,13 +8863,13 @@ function parseGitlabOwnerAndRepo(gitlabUrl) {
|
|
|
8815
8863
|
const { organization, repoName, projectPath } = parsingResult;
|
|
8816
8864
|
return { owner: organization, repo: repoName, projectPath };
|
|
8817
8865
|
}
|
|
8818
|
-
async function getGitlabBlameRanges({ ref, gitlabUrl, path:
|
|
8866
|
+
async function getGitlabBlameRanges({ ref, gitlabUrl, path: path21 }, options) {
|
|
8819
8867
|
const { projectPath } = parseGitlabOwnerAndRepo(gitlabUrl);
|
|
8820
8868
|
const api2 = getGitBeaker({
|
|
8821
8869
|
url: gitlabUrl,
|
|
8822
8870
|
gitlabAuthToken: options?.gitlabAuthToken
|
|
8823
8871
|
});
|
|
8824
|
-
const resp = await api2.RepositoryFiles.allFileBlames(projectPath,
|
|
8872
|
+
const resp = await api2.RepositoryFiles.allFileBlames(projectPath, path21, ref);
|
|
8825
8873
|
let lineNumber = 1;
|
|
8826
8874
|
return resp.filter((range) => range.lines).map((range) => {
|
|
8827
8875
|
const oldLineNumber = lineNumber;
|
|
@@ -8998,10 +9046,10 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
8998
9046
|
markdownComment: comment
|
|
8999
9047
|
});
|
|
9000
9048
|
}
|
|
9001
|
-
async getRepoBlameRanges(ref,
|
|
9049
|
+
async getRepoBlameRanges(ref, path21) {
|
|
9002
9050
|
this._validateUrl();
|
|
9003
9051
|
return await getGitlabBlameRanges(
|
|
9004
|
-
{ ref, path:
|
|
9052
|
+
{ ref, path: path21, gitlabUrl: this.url },
|
|
9005
9053
|
{
|
|
9006
9054
|
url: this.url,
|
|
9007
9055
|
gitlabAuthToken: this.accessToken
|
|
@@ -10354,6 +10402,13 @@ var GQLClient = class {
|
|
|
10354
10402
|
const { me } = await this._clientSdk.Me();
|
|
10355
10403
|
return me;
|
|
10356
10404
|
}
|
|
10405
|
+
async getLastOrg(email) {
|
|
10406
|
+
const getLastOrgRes = await this._clientSdk.getLastOrg({ email });
|
|
10407
|
+
return {
|
|
10408
|
+
organizationId: getLastOrgRes?.user?.[0]?.userOrganizationsAndUserOrganizationRoles?.[0]?.organization?.id,
|
|
10409
|
+
userName: getLastOrgRes?.user?.[0]?.name ?? ""
|
|
10410
|
+
};
|
|
10411
|
+
}
|
|
10357
10412
|
async createCliLogin(variables) {
|
|
10358
10413
|
const res = await this._clientSdk.CreateCliLogin(variables, {
|
|
10359
10414
|
// We may have outdated API key in the config storage. Avoid using it for the login request.
|
|
@@ -11033,7 +11088,7 @@ async function postIssueComment(params) {
|
|
|
11033
11088
|
fpDescription
|
|
11034
11089
|
} = params;
|
|
11035
11090
|
const {
|
|
11036
|
-
path:
|
|
11091
|
+
path: path21,
|
|
11037
11092
|
startLine,
|
|
11038
11093
|
vulnerabilityReportIssue: {
|
|
11039
11094
|
vulnerabilityReportIssueTags,
|
|
@@ -11048,7 +11103,7 @@ async function postIssueComment(params) {
|
|
|
11048
11103
|
Refresh the page in order to see the changes.`,
|
|
11049
11104
|
pull_number: pullRequest,
|
|
11050
11105
|
commit_id: commitSha,
|
|
11051
|
-
path:
|
|
11106
|
+
path: path21,
|
|
11052
11107
|
line: startLine
|
|
11053
11108
|
});
|
|
11054
11109
|
const commentId = commentRes.data.id;
|
|
@@ -11082,7 +11137,7 @@ async function postFixComment(params) {
|
|
|
11082
11137
|
scanner
|
|
11083
11138
|
} = params;
|
|
11084
11139
|
const {
|
|
11085
|
-
path:
|
|
11140
|
+
path: path21,
|
|
11086
11141
|
startLine,
|
|
11087
11142
|
vulnerabilityReportIssue: { fixId, vulnerabilityReportIssueTags, category },
|
|
11088
11143
|
vulnerabilityReportIssueId
|
|
@@ -11100,7 +11155,7 @@ async function postFixComment(params) {
|
|
|
11100
11155
|
Refresh the page in order to see the changes.`,
|
|
11101
11156
|
pull_number: pullRequest,
|
|
11102
11157
|
commit_id: commitSha,
|
|
11103
|
-
path:
|
|
11158
|
+
path: path21,
|
|
11104
11159
|
line: startLine
|
|
11105
11160
|
});
|
|
11106
11161
|
const commentId = commentRes.data.id;
|
|
@@ -11681,8 +11736,8 @@ if (typeof __filename !== "undefined") {
|
|
|
11681
11736
|
}
|
|
11682
11737
|
var costumeRequire = createRequire(moduleUrl);
|
|
11683
11738
|
var getCheckmarxPath = () => {
|
|
11684
|
-
const
|
|
11685
|
-
const cxFileName =
|
|
11739
|
+
const os9 = type();
|
|
11740
|
+
const cxFileName = os9 === "Windows_NT" ? "cx.exe" : "cx";
|
|
11686
11741
|
try {
|
|
11687
11742
|
return costumeRequire.resolve(`.bin/${cxFileName}`);
|
|
11688
11743
|
} catch (e) {
|
|
@@ -12858,8 +12913,8 @@ var WorkspaceService = class {
|
|
|
12858
12913
|
* Sets a known workspace path that was discovered through successful validation
|
|
12859
12914
|
* @param path The validated workspace path to store
|
|
12860
12915
|
*/
|
|
12861
|
-
static setKnownWorkspacePath(
|
|
12862
|
-
this.knownWorkspacePath =
|
|
12916
|
+
static setKnownWorkspacePath(path21) {
|
|
12917
|
+
this.knownWorkspacePath = path21;
|
|
12863
12918
|
}
|
|
12864
12919
|
/**
|
|
12865
12920
|
* Gets the known workspace path that was previously validated
|
|
@@ -14072,16 +14127,16 @@ var versionCommands = {
|
|
|
14072
14127
|
}
|
|
14073
14128
|
};
|
|
14074
14129
|
var getProcessInfo = (pid) => {
|
|
14075
|
-
const
|
|
14130
|
+
const platform2 = os3.platform();
|
|
14076
14131
|
try {
|
|
14077
|
-
if (
|
|
14132
|
+
if (platform2 === "linux" || platform2 === "darwin") {
|
|
14078
14133
|
const output = execSync(`ps -o pid=,ppid=,comm= -p ${pid}`, {
|
|
14079
14134
|
stdio: ["pipe", "pipe", "ignore"]
|
|
14080
14135
|
}).toString().trim();
|
|
14081
14136
|
if (!output) return null;
|
|
14082
14137
|
const [pidStr, ppid, ...cmd] = output.trim().split(/\s+/);
|
|
14083
14138
|
return { pid: pidStr ?? "", ppid: ppid ?? "", cmd: cmd.join(" ") };
|
|
14084
|
-
} else if (
|
|
14139
|
+
} else if (platform2 === "win32") {
|
|
14085
14140
|
const output = execSync(
|
|
14086
14141
|
`powershell -Command "Get-CimInstance Win32_Process -Filter 'ProcessId=${pid}' | Select-Object ProcessId,ParentProcessId,Name | Format-Table -HideTableHeaders"`,
|
|
14087
14142
|
{ stdio: ["pipe", "pipe", "ignore"] }
|
|
@@ -14093,7 +14148,7 @@ var getProcessInfo = (pid) => {
|
|
|
14093
14148
|
const cmd = parts.slice(2).join(" ");
|
|
14094
14149
|
return { pid: pidStr ?? "", ppid: ppid ?? "", cmd };
|
|
14095
14150
|
} else {
|
|
14096
|
-
logWarn(`[UsageService] Unsupported platform: ${
|
|
14151
|
+
logWarn(`[UsageService] Unsupported platform: ${platform2}`);
|
|
14097
14152
|
return null;
|
|
14098
14153
|
}
|
|
14099
14154
|
} catch {
|
|
@@ -14107,10 +14162,10 @@ var getHostInfo = (additionalMcpList) => {
|
|
|
14107
14162
|
const ideConfigPaths = /* @__PURE__ */ new Set();
|
|
14108
14163
|
for (const ide of IDEs) {
|
|
14109
14164
|
const configPaths = getMCPConfigPaths(ide);
|
|
14110
|
-
configPaths.forEach((
|
|
14165
|
+
configPaths.forEach((path21) => ideConfigPaths.add(path21));
|
|
14111
14166
|
}
|
|
14112
14167
|
const uniqueAdditionalPaths = additionalMcpList.filter(
|
|
14113
|
-
(
|
|
14168
|
+
(path21) => !ideConfigPaths.has(path21)
|
|
14114
14169
|
);
|
|
14115
14170
|
for (const ide of IDEs) {
|
|
14116
14171
|
const cfg = readMCPConfig(ide);
|
|
@@ -14191,8 +14246,8 @@ var getHostInfo = (additionalMcpList) => {
|
|
|
14191
14246
|
const config6 = allConfigs[ide] || null;
|
|
14192
14247
|
const ideName = ide.charAt(0).toUpperCase() + ide.slice(1) || "Unknown";
|
|
14193
14248
|
let ideVersion = "Unknown";
|
|
14194
|
-
const
|
|
14195
|
-
const cmds = versionCommands[ideName]?.[
|
|
14249
|
+
const platform2 = os3.platform();
|
|
14250
|
+
const cmds = versionCommands[ideName]?.[platform2] ?? [];
|
|
14196
14251
|
for (const cmd of cmds) {
|
|
14197
14252
|
try {
|
|
14198
14253
|
const versionOutput = cmd.includes("grep") || cmd.includes("--version") || cmd.includes("sed") ? execSync(cmd, { stdio: ["pipe", "pipe", "ignore"] }).toString().split("\n")[0] ?? "" : cmd;
|
|
@@ -14267,8 +14322,8 @@ var searchDir = async (dir, depth = 0) => {
|
|
|
14267
14322
|
var findSystemMCPConfigs = async () => {
|
|
14268
14323
|
try {
|
|
14269
14324
|
const home = os4.homedir();
|
|
14270
|
-
const
|
|
14271
|
-
const knownDirs =
|
|
14325
|
+
const platform2 = os4.platform();
|
|
14326
|
+
const knownDirs = platform2 === "win32" ? [
|
|
14272
14327
|
path12.join(home, ".cursor"),
|
|
14273
14328
|
path12.join(home, "Documents"),
|
|
14274
14329
|
path12.join(home, "Downloads")
|
|
@@ -16691,12 +16746,32 @@ For a complete security audit workflow, use the \`full-security-audit\` prompt.
|
|
|
16691
16746
|
}
|
|
16692
16747
|
};
|
|
16693
16748
|
|
|
16749
|
+
// src/mcp/services/McpDetectionService/CursorMcpDetectionService.ts
|
|
16750
|
+
import * as fs15 from "fs";
|
|
16751
|
+
import * as os7 from "os";
|
|
16752
|
+
import * as path14 from "path";
|
|
16753
|
+
|
|
16754
|
+
// src/mcp/services/McpDetectionService/BaseMcpDetectionService.ts
|
|
16755
|
+
init_configs();
|
|
16756
|
+
import * as fs14 from "fs";
|
|
16757
|
+
import fetch6 from "node-fetch";
|
|
16758
|
+
import * as path13 from "path";
|
|
16759
|
+
|
|
16760
|
+
// src/mcp/services/McpDetectionService/McpDetectionServiceUtils.ts
|
|
16761
|
+
import * as fs13 from "fs";
|
|
16762
|
+
import * as os6 from "os";
|
|
16763
|
+
|
|
16764
|
+
// src/mcp/services/McpDetectionService/VscodeMcpDetectionService.ts
|
|
16765
|
+
import * as fs16 from "fs";
|
|
16766
|
+
import * as os8 from "os";
|
|
16767
|
+
import * as path15 from "path";
|
|
16768
|
+
|
|
16694
16769
|
// src/mcp/tools/checkForNewAvailableFixes/CheckForNewAvailableFixesTool.ts
|
|
16695
16770
|
import { z as z40 } from "zod";
|
|
16696
16771
|
|
|
16697
16772
|
// src/mcp/services/PathValidation.ts
|
|
16698
|
-
import
|
|
16699
|
-
import
|
|
16773
|
+
import fs17 from "fs";
|
|
16774
|
+
import path16 from "path";
|
|
16700
16775
|
async function validatePath(inputPath) {
|
|
16701
16776
|
logDebug("Validating MCP path", { inputPath });
|
|
16702
16777
|
if (/^\/[a-zA-Z]:\//.test(inputPath)) {
|
|
@@ -16728,7 +16803,7 @@ async function validatePath(inputPath) {
|
|
|
16728
16803
|
logError(error);
|
|
16729
16804
|
return { isValid: false, error, path: inputPath };
|
|
16730
16805
|
}
|
|
16731
|
-
const normalizedPath =
|
|
16806
|
+
const normalizedPath = path16.normalize(inputPath);
|
|
16732
16807
|
if (normalizedPath.includes("..")) {
|
|
16733
16808
|
const error = `Normalized path contains path traversal patterns: ${inputPath}`;
|
|
16734
16809
|
logError(error);
|
|
@@ -16755,7 +16830,7 @@ async function validatePath(inputPath) {
|
|
|
16755
16830
|
logDebug("Path validation successful", { inputPath });
|
|
16756
16831
|
logDebug("Checking path existence", { inputPath });
|
|
16757
16832
|
try {
|
|
16758
|
-
await
|
|
16833
|
+
await fs17.promises.access(inputPath);
|
|
16759
16834
|
logDebug("Path exists and is accessible", { inputPath });
|
|
16760
16835
|
WorkspaceService.setKnownWorkspacePath(inputPath);
|
|
16761
16836
|
logDebug("Stored validated path in WorkspaceService", { inputPath });
|
|
@@ -17379,10 +17454,10 @@ If you wish to scan files that were recently changed in your git history call th
|
|
|
17379
17454
|
init_FileUtils();
|
|
17380
17455
|
init_GitService();
|
|
17381
17456
|
init_configs();
|
|
17382
|
-
import
|
|
17457
|
+
import fs18 from "fs/promises";
|
|
17383
17458
|
import nodePath from "path";
|
|
17384
17459
|
var getLocalFiles = async ({
|
|
17385
|
-
path:
|
|
17460
|
+
path: path21,
|
|
17386
17461
|
maxFileSize = MCP_MAX_FILE_SIZE,
|
|
17387
17462
|
maxFiles,
|
|
17388
17463
|
isAllFilesScan,
|
|
@@ -17390,17 +17465,17 @@ var getLocalFiles = async ({
|
|
|
17390
17465
|
scanRecentlyChangedFiles
|
|
17391
17466
|
}) => {
|
|
17392
17467
|
logDebug(`[${scanContext}] Starting getLocalFiles`, {
|
|
17393
|
-
path:
|
|
17468
|
+
path: path21,
|
|
17394
17469
|
maxFileSize,
|
|
17395
17470
|
maxFiles,
|
|
17396
17471
|
isAllFilesScan,
|
|
17397
17472
|
scanRecentlyChangedFiles
|
|
17398
17473
|
});
|
|
17399
17474
|
try {
|
|
17400
|
-
const resolvedRepoPath = await
|
|
17475
|
+
const resolvedRepoPath = await fs18.realpath(path21);
|
|
17401
17476
|
logDebug(`[${scanContext}] Resolved repository path`, {
|
|
17402
17477
|
resolvedRepoPath,
|
|
17403
|
-
originalPath:
|
|
17478
|
+
originalPath: path21
|
|
17404
17479
|
});
|
|
17405
17480
|
const gitService = new GitService(resolvedRepoPath, log);
|
|
17406
17481
|
const gitValidation = await gitService.validateRepository();
|
|
@@ -17413,7 +17488,7 @@ var getLocalFiles = async ({
|
|
|
17413
17488
|
if (!gitValidation.isValid || isAllFilesScan) {
|
|
17414
17489
|
try {
|
|
17415
17490
|
files = await FileUtils.getLastChangedFiles({
|
|
17416
|
-
dir:
|
|
17491
|
+
dir: path21,
|
|
17417
17492
|
maxFileSize,
|
|
17418
17493
|
maxFiles,
|
|
17419
17494
|
isAllFilesScan
|
|
@@ -17477,7 +17552,7 @@ var getLocalFiles = async ({
|
|
|
17477
17552
|
absoluteFilePath
|
|
17478
17553
|
);
|
|
17479
17554
|
try {
|
|
17480
|
-
const fileStat = await
|
|
17555
|
+
const fileStat = await fs18.stat(absoluteFilePath);
|
|
17481
17556
|
return {
|
|
17482
17557
|
filename: nodePath.basename(absoluteFilePath),
|
|
17483
17558
|
relativePath,
|
|
@@ -17505,15 +17580,15 @@ var getLocalFiles = async ({
|
|
|
17505
17580
|
logError(`${scanContext}Unexpected error in getLocalFiles`, {
|
|
17506
17581
|
error: error instanceof Error ? error.message : String(error),
|
|
17507
17582
|
stack: error instanceof Error ? error.stack : void 0,
|
|
17508
|
-
path:
|
|
17583
|
+
path: path21
|
|
17509
17584
|
});
|
|
17510
17585
|
throw error;
|
|
17511
17586
|
}
|
|
17512
17587
|
};
|
|
17513
17588
|
|
|
17514
17589
|
// src/mcp/services/LocalMobbFolderService.ts
|
|
17515
|
-
import
|
|
17516
|
-
import
|
|
17590
|
+
import fs19 from "fs";
|
|
17591
|
+
import path17 from "path";
|
|
17517
17592
|
import { z as z39 } from "zod";
|
|
17518
17593
|
init_GitService();
|
|
17519
17594
|
function extractPathFromPatch(patch) {
|
|
@@ -17600,19 +17675,19 @@ var LocalMobbFolderService = class {
|
|
|
17600
17675
|
"[LocalMobbFolderService] Non-git repository detected, skipping .gitignore operations"
|
|
17601
17676
|
);
|
|
17602
17677
|
}
|
|
17603
|
-
const mobbFolderPath =
|
|
17678
|
+
const mobbFolderPath = path17.join(
|
|
17604
17679
|
this.repoPath,
|
|
17605
17680
|
this.defaultMobbFolderName
|
|
17606
17681
|
);
|
|
17607
|
-
if (!
|
|
17682
|
+
if (!fs19.existsSync(mobbFolderPath)) {
|
|
17608
17683
|
logInfo("[LocalMobbFolderService] Creating .mobb folder", {
|
|
17609
17684
|
mobbFolderPath
|
|
17610
17685
|
});
|
|
17611
|
-
|
|
17686
|
+
fs19.mkdirSync(mobbFolderPath, { recursive: true });
|
|
17612
17687
|
} else {
|
|
17613
17688
|
logDebug("[LocalMobbFolderService] .mobb folder already exists");
|
|
17614
17689
|
}
|
|
17615
|
-
const stats =
|
|
17690
|
+
const stats = fs19.statSync(mobbFolderPath);
|
|
17616
17691
|
if (!stats.isDirectory()) {
|
|
17617
17692
|
throw new Error(`Path exists but is not a directory: ${mobbFolderPath}`);
|
|
17618
17693
|
}
|
|
@@ -17653,13 +17728,13 @@ var LocalMobbFolderService = class {
|
|
|
17653
17728
|
logDebug("[LocalMobbFolderService] Git repository validated successfully");
|
|
17654
17729
|
} else {
|
|
17655
17730
|
try {
|
|
17656
|
-
const stats =
|
|
17731
|
+
const stats = fs19.statSync(this.repoPath);
|
|
17657
17732
|
if (!stats.isDirectory()) {
|
|
17658
17733
|
throw new Error(
|
|
17659
17734
|
`Path exists but is not a directory: ${this.repoPath}`
|
|
17660
17735
|
);
|
|
17661
17736
|
}
|
|
17662
|
-
|
|
17737
|
+
fs19.accessSync(this.repoPath, fs19.constants.R_OK | fs19.constants.W_OK);
|
|
17663
17738
|
logDebug(
|
|
17664
17739
|
"[LocalMobbFolderService] Non-git directory validated successfully"
|
|
17665
17740
|
);
|
|
@@ -17772,8 +17847,8 @@ var LocalMobbFolderService = class {
|
|
|
17772
17847
|
mobbFolderPath,
|
|
17773
17848
|
baseFileName
|
|
17774
17849
|
);
|
|
17775
|
-
const filePath =
|
|
17776
|
-
await
|
|
17850
|
+
const filePath = path17.join(mobbFolderPath, uniqueFileName);
|
|
17851
|
+
await fs19.promises.writeFile(filePath, patch, "utf8");
|
|
17777
17852
|
logInfo("[LocalMobbFolderService] Patch saved successfully", {
|
|
17778
17853
|
filePath,
|
|
17779
17854
|
fileName: uniqueFileName,
|
|
@@ -17830,11 +17905,11 @@ var LocalMobbFolderService = class {
|
|
|
17830
17905
|
* @returns Unique filename that doesn't conflict with existing files
|
|
17831
17906
|
*/
|
|
17832
17907
|
getUniqueFileName(folderPath, baseFileName) {
|
|
17833
|
-
const baseName =
|
|
17834
|
-
const extension =
|
|
17908
|
+
const baseName = path17.parse(baseFileName).name;
|
|
17909
|
+
const extension = path17.parse(baseFileName).ext;
|
|
17835
17910
|
let uniqueFileName = baseFileName;
|
|
17836
17911
|
let index = 1;
|
|
17837
|
-
while (
|
|
17912
|
+
while (fs19.existsSync(path17.join(folderPath, uniqueFileName))) {
|
|
17838
17913
|
uniqueFileName = `${baseName}-${index}${extension}`;
|
|
17839
17914
|
index++;
|
|
17840
17915
|
if (index > 1e3) {
|
|
@@ -17865,18 +17940,18 @@ var LocalMobbFolderService = class {
|
|
|
17865
17940
|
logDebug("[LocalMobbFolderService] Logging patch info", { fixId: fix.id });
|
|
17866
17941
|
try {
|
|
17867
17942
|
const mobbFolderPath = await this.getFolder();
|
|
17868
|
-
const patchInfoPath =
|
|
17943
|
+
const patchInfoPath = path17.join(mobbFolderPath, "patchInfo.md");
|
|
17869
17944
|
const markdownContent = this.generateFixMarkdown(fix, savedPatchFileName);
|
|
17870
17945
|
let existingContent = "";
|
|
17871
|
-
if (
|
|
17872
|
-
existingContent = await
|
|
17946
|
+
if (fs19.existsSync(patchInfoPath)) {
|
|
17947
|
+
existingContent = await fs19.promises.readFile(patchInfoPath, "utf8");
|
|
17873
17948
|
logDebug("[LocalMobbFolderService] Existing patchInfo.md found");
|
|
17874
17949
|
} else {
|
|
17875
17950
|
logDebug("[LocalMobbFolderService] Creating new patchInfo.md file");
|
|
17876
17951
|
}
|
|
17877
17952
|
const separator = existingContent ? "\n\n================================================================================\n\n" : "";
|
|
17878
17953
|
const updatedContent = `${markdownContent}${separator}${existingContent}`;
|
|
17879
|
-
await
|
|
17954
|
+
await fs19.promises.writeFile(patchInfoPath, updatedContent, "utf8");
|
|
17880
17955
|
logInfo("[LocalMobbFolderService] Patch info logged successfully", {
|
|
17881
17956
|
patchInfoPath,
|
|
17882
17957
|
fixId: fix.id,
|
|
@@ -17907,7 +17982,7 @@ var LocalMobbFolderService = class {
|
|
|
17907
17982
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
17908
17983
|
const patch = this.extractPatchFromFix(fix);
|
|
17909
17984
|
const relativePatchedFilePath = patch ? extractPathFromPatch(patch) : null;
|
|
17910
|
-
const patchedFilePath = relativePatchedFilePath ?
|
|
17985
|
+
const patchedFilePath = relativePatchedFilePath ? path17.resolve(this.repoPath, relativePatchedFilePath) : null;
|
|
17911
17986
|
const fixIdentifier = savedPatchFileName ? savedPatchFileName.replace(".patch", "") : fix.id;
|
|
17912
17987
|
let markdown = `# Fix ${fixIdentifier}
|
|
17913
17988
|
|
|
@@ -18243,22 +18318,22 @@ var LocalMobbFolderService = class {
|
|
|
18243
18318
|
// src/mcp/services/PatchApplicationService.ts
|
|
18244
18319
|
init_configs();
|
|
18245
18320
|
import {
|
|
18246
|
-
existsSync as
|
|
18321
|
+
existsSync as existsSync6,
|
|
18247
18322
|
mkdirSync,
|
|
18248
|
-
readFileSync,
|
|
18323
|
+
readFileSync as readFileSync3,
|
|
18249
18324
|
unlinkSync,
|
|
18250
18325
|
writeFileSync
|
|
18251
18326
|
} from "fs";
|
|
18252
|
-
import
|
|
18327
|
+
import fs20 from "fs/promises";
|
|
18253
18328
|
import parseDiff2 from "parse-diff";
|
|
18254
|
-
import
|
|
18329
|
+
import path18 from "path";
|
|
18255
18330
|
var PatchApplicationService = class {
|
|
18256
18331
|
/**
|
|
18257
18332
|
* Gets the appropriate comment syntax for a file based on its extension
|
|
18258
18333
|
*/
|
|
18259
18334
|
static getCommentSyntax(filePath) {
|
|
18260
|
-
const ext =
|
|
18261
|
-
const basename2 =
|
|
18335
|
+
const ext = path18.extname(filePath).toLowerCase();
|
|
18336
|
+
const basename2 = path18.basename(filePath);
|
|
18262
18337
|
const commentMap = {
|
|
18263
18338
|
// C-style languages (single line comments)
|
|
18264
18339
|
".js": "//",
|
|
@@ -18461,7 +18536,7 @@ var PatchApplicationService = class {
|
|
|
18461
18536
|
}
|
|
18462
18537
|
);
|
|
18463
18538
|
}
|
|
18464
|
-
const dirPath =
|
|
18539
|
+
const dirPath = path18.dirname(filePath);
|
|
18465
18540
|
mkdirSync(dirPath, { recursive: true });
|
|
18466
18541
|
writeFileSync(filePath, finalContent, "utf8");
|
|
18467
18542
|
return filePath;
|
|
@@ -18745,9 +18820,9 @@ var PatchApplicationService = class {
|
|
|
18745
18820
|
continue;
|
|
18746
18821
|
}
|
|
18747
18822
|
try {
|
|
18748
|
-
const absolutePath =
|
|
18749
|
-
if (
|
|
18750
|
-
const stats = await
|
|
18823
|
+
const absolutePath = path18.resolve(repositoryPath, targetFile);
|
|
18824
|
+
if (existsSync6(absolutePath)) {
|
|
18825
|
+
const stats = await fs20.stat(absolutePath);
|
|
18751
18826
|
const fileModTime = stats.mtime.getTime();
|
|
18752
18827
|
if (fileModTime > scanStartTime) {
|
|
18753
18828
|
logError(
|
|
@@ -18788,7 +18863,7 @@ var PatchApplicationService = class {
|
|
|
18788
18863
|
const appliedFixes = [];
|
|
18789
18864
|
const failedFixes = [];
|
|
18790
18865
|
const skippedFixes = [];
|
|
18791
|
-
const resolvedRepoPath = await
|
|
18866
|
+
const resolvedRepoPath = await fs20.realpath(repositoryPath);
|
|
18792
18867
|
logInfo(
|
|
18793
18868
|
`[${scanContext}] Starting patch application for ${fixes.length} fixes`,
|
|
18794
18869
|
{
|
|
@@ -18936,11 +19011,11 @@ var PatchApplicationService = class {
|
|
|
18936
19011
|
}) {
|
|
18937
19012
|
const sanitizedRepoPath = String(repositoryPath || "").replace("\0", "").replace(/^(\.\.(\/|\\))+/, "");
|
|
18938
19013
|
const sanitizedTargetFile = String(targetFile || "").replace("\0", "").replace(/^(\.\.(\/|\\))+/, "");
|
|
18939
|
-
const absoluteFilePath =
|
|
19014
|
+
const absoluteFilePath = path18.resolve(
|
|
18940
19015
|
sanitizedRepoPath,
|
|
18941
19016
|
sanitizedTargetFile
|
|
18942
19017
|
);
|
|
18943
|
-
const relativePath =
|
|
19018
|
+
const relativePath = path18.relative(sanitizedRepoPath, absoluteFilePath);
|
|
18944
19019
|
if (relativePath.startsWith("..")) {
|
|
18945
19020
|
throw new Error(
|
|
18946
19021
|
`Security violation: target file ${targetFile} resolves outside repository`
|
|
@@ -18951,7 +19026,7 @@ var PatchApplicationService = class {
|
|
|
18951
19026
|
targetFile: sanitizedTargetFile,
|
|
18952
19027
|
absoluteFilePath,
|
|
18953
19028
|
relativePath,
|
|
18954
|
-
exists:
|
|
19029
|
+
exists: existsSync6(absoluteFilePath)
|
|
18955
19030
|
});
|
|
18956
19031
|
return { absoluteFilePath, relativePath };
|
|
18957
19032
|
}
|
|
@@ -18974,7 +19049,7 @@ var PatchApplicationService = class {
|
|
|
18974
19049
|
fix,
|
|
18975
19050
|
scanContext
|
|
18976
19051
|
});
|
|
18977
|
-
appliedFiles.push(
|
|
19052
|
+
appliedFiles.push(path18.relative(repositoryPath, actualPath));
|
|
18978
19053
|
logDebug(`[${scanContext}] Created new file: ${relativePath}`);
|
|
18979
19054
|
}
|
|
18980
19055
|
/**
|
|
@@ -18986,7 +19061,7 @@ var PatchApplicationService = class {
|
|
|
18986
19061
|
appliedFiles,
|
|
18987
19062
|
scanContext
|
|
18988
19063
|
}) {
|
|
18989
|
-
if (
|
|
19064
|
+
if (existsSync6(absoluteFilePath)) {
|
|
18990
19065
|
unlinkSync(absoluteFilePath);
|
|
18991
19066
|
appliedFiles.push(relativePath);
|
|
18992
19067
|
logDebug(`[${scanContext}] Deleted file: ${relativePath}`);
|
|
@@ -19005,12 +19080,12 @@ var PatchApplicationService = class {
|
|
|
19005
19080
|
appliedFiles,
|
|
19006
19081
|
scanContext
|
|
19007
19082
|
}) {
|
|
19008
|
-
if (!
|
|
19083
|
+
if (!existsSync6(absoluteFilePath)) {
|
|
19009
19084
|
throw new Error(
|
|
19010
19085
|
`Target file does not exist: ${targetFile} (resolved to: ${absoluteFilePath})`
|
|
19011
19086
|
);
|
|
19012
19087
|
}
|
|
19013
|
-
const originalContent =
|
|
19088
|
+
const originalContent = readFileSync3(absoluteFilePath, "utf8");
|
|
19014
19089
|
const modifiedContent = this.applyHunksToFile(
|
|
19015
19090
|
originalContent,
|
|
19016
19091
|
fileDiff.chunks
|
|
@@ -19022,7 +19097,7 @@ var PatchApplicationService = class {
|
|
|
19022
19097
|
fix,
|
|
19023
19098
|
scanContext
|
|
19024
19099
|
});
|
|
19025
|
-
appliedFiles.push(
|
|
19100
|
+
appliedFiles.push(path18.relative(repositoryPath, actualPath));
|
|
19026
19101
|
logDebug(`[${scanContext}] Modified file: ${relativePath}`);
|
|
19027
19102
|
}
|
|
19028
19103
|
}
|
|
@@ -19217,8 +19292,8 @@ init_configs();
|
|
|
19217
19292
|
|
|
19218
19293
|
// src/mcp/services/FileOperations.ts
|
|
19219
19294
|
init_FileUtils();
|
|
19220
|
-
import
|
|
19221
|
-
import
|
|
19295
|
+
import fs21 from "fs";
|
|
19296
|
+
import path19 from "path";
|
|
19222
19297
|
import AdmZip2 from "adm-zip";
|
|
19223
19298
|
var FileOperations = class {
|
|
19224
19299
|
/**
|
|
@@ -19238,10 +19313,10 @@ var FileOperations = class {
|
|
|
19238
19313
|
let packedFilesCount = 0;
|
|
19239
19314
|
const packedFiles = [];
|
|
19240
19315
|
const excludedFiles = [];
|
|
19241
|
-
const resolvedRepoPath =
|
|
19316
|
+
const resolvedRepoPath = path19.resolve(repositoryPath);
|
|
19242
19317
|
for (const filepath of fileList) {
|
|
19243
|
-
const absoluteFilepath =
|
|
19244
|
-
const resolvedFilePath =
|
|
19318
|
+
const absoluteFilepath = path19.join(repositoryPath, filepath);
|
|
19319
|
+
const resolvedFilePath = path19.resolve(absoluteFilepath);
|
|
19245
19320
|
if (!resolvedFilePath.startsWith(resolvedRepoPath)) {
|
|
19246
19321
|
const reason = "potential path traversal security risk";
|
|
19247
19322
|
logDebug(`[FileOperations] Skipping ${filepath} due to ${reason}`);
|
|
@@ -19288,11 +19363,11 @@ var FileOperations = class {
|
|
|
19288
19363
|
fileList,
|
|
19289
19364
|
repositoryPath
|
|
19290
19365
|
}) {
|
|
19291
|
-
const resolvedRepoPath =
|
|
19366
|
+
const resolvedRepoPath = path19.resolve(repositoryPath);
|
|
19292
19367
|
const validatedPaths = [];
|
|
19293
19368
|
for (const filepath of fileList) {
|
|
19294
|
-
const absoluteFilepath =
|
|
19295
|
-
const resolvedFilePath =
|
|
19369
|
+
const absoluteFilepath = path19.join(repositoryPath, filepath);
|
|
19370
|
+
const resolvedFilePath = path19.resolve(absoluteFilepath);
|
|
19296
19371
|
if (!resolvedFilePath.startsWith(resolvedRepoPath)) {
|
|
19297
19372
|
logDebug(
|
|
19298
19373
|
`[FileOperations] Rejecting ${filepath} - path traversal attempt detected`
|
|
@@ -19300,7 +19375,7 @@ var FileOperations = class {
|
|
|
19300
19375
|
continue;
|
|
19301
19376
|
}
|
|
19302
19377
|
try {
|
|
19303
|
-
await
|
|
19378
|
+
await fs21.promises.access(absoluteFilepath, fs21.constants.R_OK);
|
|
19304
19379
|
validatedPaths.push(filepath);
|
|
19305
19380
|
} catch (error) {
|
|
19306
19381
|
logDebug(
|
|
@@ -19319,8 +19394,8 @@ var FileOperations = class {
|
|
|
19319
19394
|
const fileDataArray = [];
|
|
19320
19395
|
for (const absolutePath of filePaths) {
|
|
19321
19396
|
try {
|
|
19322
|
-
const content = await
|
|
19323
|
-
const relativePath =
|
|
19397
|
+
const content = await fs21.promises.readFile(absolutePath);
|
|
19398
|
+
const relativePath = path19.basename(absolutePath);
|
|
19324
19399
|
fileDataArray.push({
|
|
19325
19400
|
relativePath,
|
|
19326
19401
|
absolutePath,
|
|
@@ -19345,7 +19420,7 @@ var FileOperations = class {
|
|
|
19345
19420
|
relativeFilepath
|
|
19346
19421
|
}) {
|
|
19347
19422
|
try {
|
|
19348
|
-
return await
|
|
19423
|
+
return await fs21.promises.readFile(absoluteFilepath);
|
|
19349
19424
|
} catch (fsError) {
|
|
19350
19425
|
logError(
|
|
19351
19426
|
`[FileOperations] Failed to read ${relativeFilepath} from filesystem: ${fsError}`
|
|
@@ -19632,14 +19707,14 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
19632
19707
|
* since the last scan.
|
|
19633
19708
|
*/
|
|
19634
19709
|
async scanForSecurityVulnerabilities({
|
|
19635
|
-
path:
|
|
19710
|
+
path: path21,
|
|
19636
19711
|
isAllDetectionRulesScan,
|
|
19637
19712
|
isAllFilesScan,
|
|
19638
19713
|
scanContext
|
|
19639
19714
|
}) {
|
|
19640
19715
|
this.hasAuthenticationFailed = false;
|
|
19641
19716
|
logDebug(`[${scanContext}] Scanning for new security vulnerabilities`, {
|
|
19642
|
-
path:
|
|
19717
|
+
path: path21
|
|
19643
19718
|
});
|
|
19644
19719
|
if (!this.gqlClient) {
|
|
19645
19720
|
logInfo(`[${scanContext}] No GQL client found, skipping scan`);
|
|
@@ -19655,11 +19730,11 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
19655
19730
|
}
|
|
19656
19731
|
logDebug(
|
|
19657
19732
|
`[${scanContext}] Connected to the API, assembling list of files to scan`,
|
|
19658
|
-
{ path:
|
|
19733
|
+
{ path: path21 }
|
|
19659
19734
|
);
|
|
19660
19735
|
const isBackgroundScan = scanContext === ScanContext.BACKGROUND_INITIAL || scanContext === ScanContext.BACKGROUND_PERIODIC;
|
|
19661
19736
|
const files = await getLocalFiles({
|
|
19662
|
-
path:
|
|
19737
|
+
path: path21,
|
|
19663
19738
|
isAllFilesScan,
|
|
19664
19739
|
scanContext,
|
|
19665
19740
|
scanRecentlyChangedFiles: !isBackgroundScan
|
|
@@ -19685,13 +19760,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
19685
19760
|
});
|
|
19686
19761
|
const { fixReportId, projectId } = await scanFiles({
|
|
19687
19762
|
fileList: filesToScan.map((file) => file.relativePath),
|
|
19688
|
-
repositoryPath:
|
|
19763
|
+
repositoryPath: path21,
|
|
19689
19764
|
gqlClient: this.gqlClient,
|
|
19690
19765
|
isAllDetectionRulesScan,
|
|
19691
19766
|
scanContext
|
|
19692
19767
|
});
|
|
19693
19768
|
logInfo(
|
|
19694
|
-
`[${scanContext}] Security scan completed for ${
|
|
19769
|
+
`[${scanContext}] Security scan completed for ${path21} reportId: ${fixReportId} projectId: ${projectId}`
|
|
19695
19770
|
);
|
|
19696
19771
|
if (isAllFilesScan) {
|
|
19697
19772
|
return;
|
|
@@ -19985,13 +20060,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
19985
20060
|
});
|
|
19986
20061
|
return scannedFiles.some((file) => file.relativePath === fixFile);
|
|
19987
20062
|
}
|
|
19988
|
-
async getFreshFixes({ path:
|
|
20063
|
+
async getFreshFixes({ path: path21 }) {
|
|
19989
20064
|
const scanContext = ScanContext.USER_REQUEST;
|
|
19990
|
-
logDebug(`[${scanContext}] Getting fresh fixes`, { path:
|
|
19991
|
-
if (this.path !==
|
|
19992
|
-
this.path =
|
|
20065
|
+
logDebug(`[${scanContext}] Getting fresh fixes`, { path: path21 });
|
|
20066
|
+
if (this.path !== path21) {
|
|
20067
|
+
this.path = path21;
|
|
19993
20068
|
this.reset();
|
|
19994
|
-
logInfo(`[${scanContext}] Reset service state for new path`, { path:
|
|
20069
|
+
logInfo(`[${scanContext}] Reset service state for new path`, { path: path21 });
|
|
19995
20070
|
}
|
|
19996
20071
|
try {
|
|
19997
20072
|
this.gqlClient = await createAuthenticatedMcpGQLClient();
|
|
@@ -20009,7 +20084,7 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
20009
20084
|
}
|
|
20010
20085
|
throw error;
|
|
20011
20086
|
}
|
|
20012
|
-
this.triggerScan({ path:
|
|
20087
|
+
this.triggerScan({ path: path21, gqlClient: this.gqlClient });
|
|
20013
20088
|
let isMvsAutoFixEnabled = null;
|
|
20014
20089
|
try {
|
|
20015
20090
|
isMvsAutoFixEnabled = await this.gqlClient.getMvsAutoFixSettings();
|
|
@@ -20043,33 +20118,33 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
20043
20118
|
return noFreshFixesPrompt;
|
|
20044
20119
|
}
|
|
20045
20120
|
triggerScan({
|
|
20046
|
-
path:
|
|
20121
|
+
path: path21,
|
|
20047
20122
|
gqlClient
|
|
20048
20123
|
}) {
|
|
20049
|
-
if (this.path !==
|
|
20050
|
-
this.path =
|
|
20124
|
+
if (this.path !== path21) {
|
|
20125
|
+
this.path = path21;
|
|
20051
20126
|
this.reset();
|
|
20052
|
-
logInfo(`Reset service state for new path in triggerScan`, { path:
|
|
20127
|
+
logInfo(`Reset service state for new path in triggerScan`, { path: path21 });
|
|
20053
20128
|
}
|
|
20054
20129
|
this.gqlClient = gqlClient;
|
|
20055
20130
|
if (!this.intervalId) {
|
|
20056
|
-
this.startPeriodicScanning(
|
|
20057
|
-
this.executeInitialScan(
|
|
20058
|
-
void this.executeInitialFullScan(
|
|
20131
|
+
this.startPeriodicScanning(path21);
|
|
20132
|
+
this.executeInitialScan(path21);
|
|
20133
|
+
void this.executeInitialFullScan(path21);
|
|
20059
20134
|
}
|
|
20060
20135
|
}
|
|
20061
|
-
startPeriodicScanning(
|
|
20136
|
+
startPeriodicScanning(path21) {
|
|
20062
20137
|
const scanContext = ScanContext.BACKGROUND_PERIODIC;
|
|
20063
20138
|
logDebug(
|
|
20064
20139
|
`[${scanContext}] Starting periodic scan for new security vulnerabilities`,
|
|
20065
20140
|
{
|
|
20066
|
-
path:
|
|
20141
|
+
path: path21
|
|
20067
20142
|
}
|
|
20068
20143
|
);
|
|
20069
20144
|
this.intervalId = setInterval(() => {
|
|
20070
|
-
logDebug(`[${scanContext}] Triggering periodic security scan`, { path:
|
|
20145
|
+
logDebug(`[${scanContext}] Triggering periodic security scan`, { path: path21 });
|
|
20071
20146
|
this.scanForSecurityVulnerabilities({
|
|
20072
|
-
path:
|
|
20147
|
+
path: path21,
|
|
20073
20148
|
scanContext
|
|
20074
20149
|
}).catch((error) => {
|
|
20075
20150
|
logError(`[${scanContext}] Error during periodic security scan`, {
|
|
@@ -20078,45 +20153,45 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
20078
20153
|
});
|
|
20079
20154
|
}, MCP_PERIODIC_CHECK_INTERVAL);
|
|
20080
20155
|
}
|
|
20081
|
-
async executeInitialFullScan(
|
|
20156
|
+
async executeInitialFullScan(path21) {
|
|
20082
20157
|
const scanContext = ScanContext.FULL_SCAN;
|
|
20083
|
-
logDebug(`[${scanContext}] Triggering initial full security scan`, { path:
|
|
20158
|
+
logDebug(`[${scanContext}] Triggering initial full security scan`, { path: path21 });
|
|
20084
20159
|
logDebug(`[${scanContext}] Full scan paths scanned`, {
|
|
20085
20160
|
fullScanPathsScanned: this.fullScanPathsScanned
|
|
20086
20161
|
});
|
|
20087
|
-
if (this.fullScanPathsScanned.includes(
|
|
20162
|
+
if (this.fullScanPathsScanned.includes(path21)) {
|
|
20088
20163
|
logDebug(`[${scanContext}] Full scan already executed for this path`, {
|
|
20089
|
-
path:
|
|
20164
|
+
path: path21
|
|
20090
20165
|
});
|
|
20091
20166
|
return;
|
|
20092
20167
|
}
|
|
20093
20168
|
configStore.set("fullScanPathsScanned", [
|
|
20094
20169
|
...this.fullScanPathsScanned,
|
|
20095
|
-
|
|
20170
|
+
path21
|
|
20096
20171
|
]);
|
|
20097
20172
|
try {
|
|
20098
20173
|
await this.scanForSecurityVulnerabilities({
|
|
20099
|
-
path:
|
|
20174
|
+
path: path21,
|
|
20100
20175
|
isAllFilesScan: true,
|
|
20101
20176
|
isAllDetectionRulesScan: true,
|
|
20102
20177
|
scanContext: ScanContext.FULL_SCAN
|
|
20103
20178
|
});
|
|
20104
|
-
if (!this.fullScanPathsScanned.includes(
|
|
20105
|
-
this.fullScanPathsScanned.push(
|
|
20179
|
+
if (!this.fullScanPathsScanned.includes(path21)) {
|
|
20180
|
+
this.fullScanPathsScanned.push(path21);
|
|
20106
20181
|
configStore.set("fullScanPathsScanned", this.fullScanPathsScanned);
|
|
20107
20182
|
}
|
|
20108
|
-
logInfo(`[${scanContext}] Full scan completed`, { path:
|
|
20183
|
+
logInfo(`[${scanContext}] Full scan completed`, { path: path21 });
|
|
20109
20184
|
} catch (error) {
|
|
20110
20185
|
logError(`[${scanContext}] Error during initial full security scan`, {
|
|
20111
20186
|
error
|
|
20112
20187
|
});
|
|
20113
20188
|
}
|
|
20114
20189
|
}
|
|
20115
|
-
executeInitialScan(
|
|
20190
|
+
executeInitialScan(path21) {
|
|
20116
20191
|
const scanContext = ScanContext.BACKGROUND_INITIAL;
|
|
20117
|
-
logDebug(`[${scanContext}] Triggering initial security scan`, { path:
|
|
20192
|
+
logDebug(`[${scanContext}] Triggering initial security scan`, { path: path21 });
|
|
20118
20193
|
this.scanForSecurityVulnerabilities({
|
|
20119
|
-
path:
|
|
20194
|
+
path: path21,
|
|
20120
20195
|
scanContext: ScanContext.BACKGROUND_INITIAL
|
|
20121
20196
|
}).catch((error) => {
|
|
20122
20197
|
logError(`[${scanContext}] Error during initial security scan`, { error });
|
|
@@ -20213,9 +20288,9 @@ Example payload:
|
|
|
20213
20288
|
`Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
|
|
20214
20289
|
);
|
|
20215
20290
|
}
|
|
20216
|
-
const
|
|
20291
|
+
const path21 = pathValidationResult.path;
|
|
20217
20292
|
const resultText = await this.newFixesService.getFreshFixes({
|
|
20218
|
-
path:
|
|
20293
|
+
path: path21
|
|
20219
20294
|
});
|
|
20220
20295
|
logInfo("CheckForNewAvailableFixesTool execution completed", {
|
|
20221
20296
|
resultText
|
|
@@ -20392,8 +20467,8 @@ Call this tool instead of ${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES} when you only
|
|
|
20392
20467
|
`Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
|
|
20393
20468
|
);
|
|
20394
20469
|
}
|
|
20395
|
-
const
|
|
20396
|
-
const gitService = new GitService(
|
|
20470
|
+
const path21 = pathValidationResult.path;
|
|
20471
|
+
const gitService = new GitService(path21, log);
|
|
20397
20472
|
const gitValidation = await gitService.validateRepository();
|
|
20398
20473
|
if (!gitValidation.isValid) {
|
|
20399
20474
|
throw new Error(`Invalid git repository: ${gitValidation.error}`);
|
|
@@ -20781,9 +20856,9 @@ Example payload:
|
|
|
20781
20856
|
`Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
|
|
20782
20857
|
);
|
|
20783
20858
|
}
|
|
20784
|
-
const
|
|
20859
|
+
const path21 = pathValidationResult.path;
|
|
20785
20860
|
const files = await getLocalFiles({
|
|
20786
|
-
path:
|
|
20861
|
+
path: path21,
|
|
20787
20862
|
maxFileSize: MCP_MAX_FILE_SIZE,
|
|
20788
20863
|
maxFiles: args.maxFiles,
|
|
20789
20864
|
scanContext: ScanContext.USER_REQUEST,
|
|
@@ -20803,7 +20878,7 @@ Example payload:
|
|
|
20803
20878
|
try {
|
|
20804
20879
|
const fixResult = await this.vulnerabilityFixService.processVulnerabilities({
|
|
20805
20880
|
fileList: files.map((file) => file.relativePath),
|
|
20806
|
-
repositoryPath:
|
|
20881
|
+
repositoryPath: path21,
|
|
20807
20882
|
offset: args.offset,
|
|
20808
20883
|
limit: args.limit,
|
|
20809
20884
|
isRescan: args.rescan || !!args.maxFiles
|
|
@@ -20907,7 +20982,7 @@ var mcpHandler = async (_args) => {
|
|
|
20907
20982
|
};
|
|
20908
20983
|
|
|
20909
20984
|
// src/args/commands/review.ts
|
|
20910
|
-
import
|
|
20985
|
+
import fs22 from "fs";
|
|
20911
20986
|
import chalk9 from "chalk";
|
|
20912
20987
|
function reviewBuilder(yargs2) {
|
|
20913
20988
|
return yargs2.option("f", {
|
|
@@ -20944,7 +21019,7 @@ function reviewBuilder(yargs2) {
|
|
|
20944
21019
|
).help();
|
|
20945
21020
|
}
|
|
20946
21021
|
function validateReviewOptions(argv) {
|
|
20947
|
-
if (!
|
|
21022
|
+
if (!fs22.existsSync(argv.f)) {
|
|
20948
21023
|
throw new CliError(`
|
|
20949
21024
|
Can't access ${chalk9.bold(argv.f)}`);
|
|
20950
21025
|
}
|
|
@@ -21018,7 +21093,7 @@ async function addScmTokenHandler(args) {
|
|
|
21018
21093
|
|
|
21019
21094
|
// src/args/commands/upload_ai_blame.ts
|
|
21020
21095
|
import fsPromises3 from "fs/promises";
|
|
21021
|
-
import
|
|
21096
|
+
import path20 from "path";
|
|
21022
21097
|
import chalk10 from "chalk";
|
|
21023
21098
|
import Configstore6 from "configstore";
|
|
21024
21099
|
import { withFile } from "tmp-promise";
|
|
@@ -21073,6 +21148,13 @@ function uploadAiBlameBuilder(args) {
|
|
|
21073
21148
|
type: "string",
|
|
21074
21149
|
array: true,
|
|
21075
21150
|
describe: chalk10.bold("Tool/IDE name(s) (optional, one per session)")
|
|
21151
|
+
}).option("blame-type", {
|
|
21152
|
+
type: "string",
|
|
21153
|
+
array: true,
|
|
21154
|
+
choices: Object.values(AiBlameInferenceType),
|
|
21155
|
+
describe: chalk10.bold(
|
|
21156
|
+
"Blame type(s) (optional, one per session, defaults to CHAT)"
|
|
21157
|
+
)
|
|
21076
21158
|
}).strict();
|
|
21077
21159
|
}
|
|
21078
21160
|
var config5 = new Configstore6(packageJson.name, { apiToken: "" });
|
|
@@ -21093,6 +21175,7 @@ async function uploadAiBlameHandler(args, exitOnError = true) {
|
|
|
21093
21175
|
const models = args.model || [];
|
|
21094
21176
|
const tools = args.toolName || args["tool-name"] || [];
|
|
21095
21177
|
const responseTimes = args.aiResponseAt || args["ai-response-at"] || [];
|
|
21178
|
+
const blameTypes = args.blameType || args["blame-type"] || [];
|
|
21096
21179
|
if (prompts.length !== inferences.length) {
|
|
21097
21180
|
const errorMsg = "prompt and inference must have the same number of entries";
|
|
21098
21181
|
console.error(chalk10.red(errorMsg));
|
|
@@ -21120,11 +21203,12 @@ async function uploadAiBlameHandler(args, exitOnError = true) {
|
|
|
21120
21203
|
throw new Error(errorMsg);
|
|
21121
21204
|
}
|
|
21122
21205
|
sessions.push({
|
|
21123
|
-
promptFileName:
|
|
21124
|
-
inferenceFileName:
|
|
21206
|
+
promptFileName: path20.basename(promptPath),
|
|
21207
|
+
inferenceFileName: path20.basename(inferencePath),
|
|
21125
21208
|
aiResponseAt: responseTimes[i] || nowIso,
|
|
21126
21209
|
model: models[i],
|
|
21127
|
-
toolName: tools[i]
|
|
21210
|
+
toolName: tools[i],
|
|
21211
|
+
blameType: blameTypes[i] || "CHAT" /* Chat */
|
|
21128
21212
|
});
|
|
21129
21213
|
}
|
|
21130
21214
|
const authenticatedClient = await getAuthenticatedGQLClientForIdeExtension();
|
|
@@ -21144,18 +21228,22 @@ async function uploadAiBlameHandler(args, exitOnError = true) {
|
|
|
21144
21228
|
const us = uploadSessions[i];
|
|
21145
21229
|
const promptPath = String(prompts[i]);
|
|
21146
21230
|
const inferencePath = String(inferences[i]);
|
|
21147
|
-
await
|
|
21148
|
-
|
|
21149
|
-
|
|
21150
|
-
|
|
21151
|
-
|
|
21152
|
-
|
|
21153
|
-
|
|
21154
|
-
|
|
21155
|
-
|
|
21156
|
-
|
|
21157
|
-
|
|
21158
|
-
|
|
21231
|
+
await Promise.all([
|
|
21232
|
+
// Prompt
|
|
21233
|
+
uploadFile({
|
|
21234
|
+
file: promptPath,
|
|
21235
|
+
url: us.prompt.url,
|
|
21236
|
+
uploadFields: JSON.parse(us.prompt.uploadFieldsJSON),
|
|
21237
|
+
uploadKey: us.prompt.uploadKey
|
|
21238
|
+
}),
|
|
21239
|
+
// Inference
|
|
21240
|
+
uploadFile({
|
|
21241
|
+
file: inferencePath,
|
|
21242
|
+
url: us.inference.url,
|
|
21243
|
+
uploadFields: JSON.parse(us.inference.uploadFieldsJSON),
|
|
21244
|
+
uploadKey: us.inference.uploadKey
|
|
21245
|
+
})
|
|
21246
|
+
]);
|
|
21159
21247
|
}
|
|
21160
21248
|
const finalizeSessions = uploadSessions.map((us, i) => {
|
|
21161
21249
|
const s = sessions[i];
|
|
@@ -21165,7 +21253,8 @@ async function uploadAiBlameHandler(args, exitOnError = true) {
|
|
|
21165
21253
|
inferenceKey: us.inference.uploadKey,
|
|
21166
21254
|
aiResponseAt: s.aiResponseAt,
|
|
21167
21255
|
model: s.model,
|
|
21168
|
-
toolName: s.toolName
|
|
21256
|
+
toolName: s.toolName,
|
|
21257
|
+
blameType: s.blameType
|
|
21169
21258
|
};
|
|
21170
21259
|
});
|
|
21171
21260
|
const finRes = await authenticatedClient.finalizeAIBlameInferencesUploadRaw({
|