mobbdev 1.0.178 → 1.0.180
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/index.mjs +432 -101
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2276,6 +2276,39 @@ var UploadS3BucketInfoDocument = `
|
|
|
2276
2276
|
}
|
|
2277
2277
|
}
|
|
2278
2278
|
`;
|
|
2279
|
+
var UploadAiBlameInferencesInitDocument = `
|
|
2280
|
+
mutation UploadAIBlameInferencesInit($sessions: [AIBlameInferenceInitInput!]!) {
|
|
2281
|
+
uploadAIBlameInferencesInit(sessions: $sessions) {
|
|
2282
|
+
status
|
|
2283
|
+
error
|
|
2284
|
+
uploadSessions {
|
|
2285
|
+
aiBlameInferenceId
|
|
2286
|
+
prompt {
|
|
2287
|
+
url
|
|
2288
|
+
artifactId
|
|
2289
|
+
fileName
|
|
2290
|
+
uploadFieldsJSON
|
|
2291
|
+
uploadKey
|
|
2292
|
+
}
|
|
2293
|
+
inference {
|
|
2294
|
+
url
|
|
2295
|
+
artifactId
|
|
2296
|
+
fileName
|
|
2297
|
+
uploadFieldsJSON
|
|
2298
|
+
uploadKey
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
2303
|
+
`;
|
|
2304
|
+
var FinalizeAiBlameInferencesUploadDocument = `
|
|
2305
|
+
mutation FinalizeAIBlameInferencesUpload($sessions: [AIBlameInferenceFinalizeInput!]!) {
|
|
2306
|
+
finalizeAIBlameInferencesUpload(sessions: $sessions) {
|
|
2307
|
+
status
|
|
2308
|
+
error
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
`;
|
|
2279
2312
|
var DigestVulnerabilityReportDocument = `
|
|
2280
2313
|
mutation DigestVulnerabilityReport($vulnerabilityReportFileName: String, $fixReportId: String!, $projectId: String!, $scanSource: String!, $repoUrl: String, $reference: String, $sha: String) {
|
|
2281
2314
|
digestVulnerabilityReport(
|
|
@@ -2533,6 +2566,12 @@ function getSdk(client, withWrapper = defaultWrapper) {
|
|
|
2533
2566
|
uploadS3BucketInfo(variables, requestHeaders, signal) {
|
|
2534
2567
|
return withWrapper((wrappedRequestHeaders) => client.request({ document: UploadS3BucketInfoDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "uploadS3BucketInfo", "mutation", variables);
|
|
2535
2568
|
},
|
|
2569
|
+
UploadAIBlameInferencesInit(variables, requestHeaders, signal) {
|
|
2570
|
+
return withWrapper((wrappedRequestHeaders) => client.request({ document: UploadAiBlameInferencesInitDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "UploadAIBlameInferencesInit", "mutation", variables);
|
|
2571
|
+
},
|
|
2572
|
+
FinalizeAIBlameInferencesUpload(variables, requestHeaders, signal) {
|
|
2573
|
+
return withWrapper((wrappedRequestHeaders) => client.request({ document: FinalizeAiBlameInferencesUploadDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "FinalizeAIBlameInferencesUpload", "mutation", variables);
|
|
2574
|
+
},
|
|
2536
2575
|
DigestVulnerabilityReport(variables, requestHeaders, signal) {
|
|
2537
2576
|
return withWrapper((wrappedRequestHeaders) => client.request({ document: DigestVulnerabilityReportDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "DigestVulnerabilityReport", "mutation", variables);
|
|
2538
2577
|
},
|
|
@@ -6375,7 +6414,7 @@ async function getAdoSdk(params) {
|
|
|
6375
6414
|
const url = new URL(repoUrl);
|
|
6376
6415
|
const origin2 = url.origin.toLowerCase().endsWith(".visualstudio.com") ? DEFUALT_ADO_ORIGIN : url.origin.toLowerCase();
|
|
6377
6416
|
const params2 = `path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=commit&versionDescriptor[version]=${branch}&resolveLfs=true&$format=zip&api-version=5.0&download=true`;
|
|
6378
|
-
const
|
|
6417
|
+
const path17 = [
|
|
6379
6418
|
prefixPath,
|
|
6380
6419
|
owner,
|
|
6381
6420
|
projectName,
|
|
@@ -6386,7 +6425,7 @@ async function getAdoSdk(params) {
|
|
|
6386
6425
|
"items",
|
|
6387
6426
|
"items"
|
|
6388
6427
|
].filter(Boolean).join("/");
|
|
6389
|
-
return new URL(`${
|
|
6428
|
+
return new URL(`${path17}?${params2}`, origin2).toString();
|
|
6390
6429
|
},
|
|
6391
6430
|
async getAdoBranchList({ repoUrl }) {
|
|
6392
6431
|
try {
|
|
@@ -6877,6 +6916,9 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
6877
6916
|
markdownComment: comment
|
|
6878
6917
|
});
|
|
6879
6918
|
}
|
|
6919
|
+
async getCommitDiff(_commitSha) {
|
|
6920
|
+
throw new Error("getCommitDiff not implemented for ADO");
|
|
6921
|
+
}
|
|
6880
6922
|
};
|
|
6881
6923
|
|
|
6882
6924
|
// src/features/analysis/scm/bitbucket/bitbucket.ts
|
|
@@ -7440,6 +7482,9 @@ var BitbucketSCMLib = class extends SCMLib {
|
|
|
7440
7482
|
markdownComment: comment
|
|
7441
7483
|
});
|
|
7442
7484
|
}
|
|
7485
|
+
async getCommitDiff(_commitSha) {
|
|
7486
|
+
throw new Error("getCommitDiff not implemented for Bitbucket");
|
|
7487
|
+
}
|
|
7443
7488
|
};
|
|
7444
7489
|
|
|
7445
7490
|
// src/features/analysis/scm/constants.ts
|
|
@@ -7808,6 +7853,33 @@ function getGithubSdk(params = {}) {
|
|
|
7808
7853
|
commit_sha: commitSha
|
|
7809
7854
|
});
|
|
7810
7855
|
},
|
|
7856
|
+
async getCommitWithDiff({
|
|
7857
|
+
commitSha,
|
|
7858
|
+
owner,
|
|
7859
|
+
repo
|
|
7860
|
+
}) {
|
|
7861
|
+
const [commitData, diffData] = await Promise.all([
|
|
7862
|
+
// Get commit metadata
|
|
7863
|
+
octokit.rest.repos.getCommit({
|
|
7864
|
+
repo,
|
|
7865
|
+
owner,
|
|
7866
|
+
ref: commitSha
|
|
7867
|
+
}),
|
|
7868
|
+
// Get commit diff
|
|
7869
|
+
octokit.request("GET /repos/{owner}/{repo}/commits/{ref}", {
|
|
7870
|
+
owner,
|
|
7871
|
+
repo,
|
|
7872
|
+
ref: commitSha,
|
|
7873
|
+
headers: {
|
|
7874
|
+
Accept: "application/vnd.github.v3.diff"
|
|
7875
|
+
}
|
|
7876
|
+
})
|
|
7877
|
+
]);
|
|
7878
|
+
return {
|
|
7879
|
+
commit: commitData.data,
|
|
7880
|
+
diff: diffData.data
|
|
7881
|
+
};
|
|
7882
|
+
},
|
|
7811
7883
|
async getTagDate({
|
|
7812
7884
|
tag,
|
|
7813
7885
|
owner,
|
|
@@ -7841,14 +7913,14 @@ function getGithubSdk(params = {}) {
|
|
|
7841
7913
|
};
|
|
7842
7914
|
},
|
|
7843
7915
|
async getGithubBlameRanges(params2) {
|
|
7844
|
-
const { ref, gitHubUrl, path:
|
|
7916
|
+
const { ref, gitHubUrl, path: path17 } = params2;
|
|
7845
7917
|
const { owner, repo } = parseGithubOwnerAndRepo(gitHubUrl);
|
|
7846
7918
|
const res = await octokit.graphql(
|
|
7847
7919
|
GET_BLAME_DOCUMENT,
|
|
7848
7920
|
{
|
|
7849
7921
|
owner,
|
|
7850
7922
|
repo,
|
|
7851
|
-
path:
|
|
7923
|
+
path: path17,
|
|
7852
7924
|
ref
|
|
7853
7925
|
}
|
|
7854
7926
|
);
|
|
@@ -8155,11 +8227,11 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
8155
8227
|
markdownComment: comment
|
|
8156
8228
|
});
|
|
8157
8229
|
}
|
|
8158
|
-
async getRepoBlameRanges(ref,
|
|
8230
|
+
async getRepoBlameRanges(ref, path17) {
|
|
8159
8231
|
this._validateUrl();
|
|
8160
8232
|
return await this.githubSdk.getGithubBlameRanges({
|
|
8161
8233
|
ref,
|
|
8162
|
-
path:
|
|
8234
|
+
path: path17,
|
|
8163
8235
|
gitHubUrl: this.url
|
|
8164
8236
|
});
|
|
8165
8237
|
}
|
|
@@ -8243,6 +8315,24 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
8243
8315
|
comment_id: commentId
|
|
8244
8316
|
});
|
|
8245
8317
|
}
|
|
8318
|
+
async getCommitDiff(commitSha) {
|
|
8319
|
+
this._validateAccessTokenAndUrl();
|
|
8320
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
8321
|
+
const { commit, diff } = await this.githubSdk.getCommitWithDiff({
|
|
8322
|
+
owner,
|
|
8323
|
+
repo,
|
|
8324
|
+
commitSha
|
|
8325
|
+
});
|
|
8326
|
+
const commitTimestamp = commit.commit.committer?.date ? new Date(commit.commit.committer.date) : new Date(commit.commit.author?.date || Date.now());
|
|
8327
|
+
return {
|
|
8328
|
+
diff,
|
|
8329
|
+
commitTimestamp,
|
|
8330
|
+
commitSha: commit.sha,
|
|
8331
|
+
authorName: commit.commit.author?.name,
|
|
8332
|
+
authorEmail: commit.commit.author?.email,
|
|
8333
|
+
message: commit.commit.message
|
|
8334
|
+
};
|
|
8335
|
+
}
|
|
8246
8336
|
};
|
|
8247
8337
|
|
|
8248
8338
|
// src/features/analysis/scm/gitlab/gitlab.ts
|
|
@@ -8573,13 +8663,13 @@ function parseGitlabOwnerAndRepo(gitlabUrl) {
|
|
|
8573
8663
|
const { organization, repoName, projectPath } = parsingResult;
|
|
8574
8664
|
return { owner: organization, repo: repoName, projectPath };
|
|
8575
8665
|
}
|
|
8576
|
-
async function getGitlabBlameRanges({ ref, gitlabUrl, path:
|
|
8666
|
+
async function getGitlabBlameRanges({ ref, gitlabUrl, path: path17 }, options) {
|
|
8577
8667
|
const { projectPath } = parseGitlabOwnerAndRepo(gitlabUrl);
|
|
8578
8668
|
const api2 = getGitBeaker({
|
|
8579
8669
|
url: gitlabUrl,
|
|
8580
8670
|
gitlabAuthToken: options?.gitlabAuthToken
|
|
8581
8671
|
});
|
|
8582
|
-
const resp = await api2.RepositoryFiles.allFileBlames(projectPath,
|
|
8672
|
+
const resp = await api2.RepositoryFiles.allFileBlames(projectPath, path17, ref);
|
|
8583
8673
|
let lineNumber = 1;
|
|
8584
8674
|
return resp.filter((range) => range.lines).map((range) => {
|
|
8585
8675
|
const oldLineNumber = lineNumber;
|
|
@@ -8755,10 +8845,10 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
8755
8845
|
markdownComment: comment
|
|
8756
8846
|
});
|
|
8757
8847
|
}
|
|
8758
|
-
async getRepoBlameRanges(ref,
|
|
8848
|
+
async getRepoBlameRanges(ref, path17) {
|
|
8759
8849
|
this._validateUrl();
|
|
8760
8850
|
return await getGitlabBlameRanges(
|
|
8761
|
-
{ ref, path:
|
|
8851
|
+
{ ref, path: path17, gitlabUrl: this.url },
|
|
8762
8852
|
{
|
|
8763
8853
|
url: this.url,
|
|
8764
8854
|
gitlabAuthToken: this.accessToken
|
|
@@ -8808,6 +8898,9 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
8808
8898
|
this._validateAccessTokenAndUrl();
|
|
8809
8899
|
return `${this.url}/-/commits/${branchName}`;
|
|
8810
8900
|
}
|
|
8901
|
+
async getCommitDiff(_commitSha) {
|
|
8902
|
+
throw new Error("getCommitDiff not implemented for GitLab");
|
|
8903
|
+
}
|
|
8811
8904
|
};
|
|
8812
8905
|
|
|
8813
8906
|
// src/features/analysis/scm/scmFactory.ts
|
|
@@ -8904,6 +8997,17 @@ var StubSCMLib = class extends SCMLib {
|
|
|
8904
8997
|
async addCommentToSubmitRequest(_submitRequestId, _comment) {
|
|
8905
8998
|
console.warn("addCommentToSubmitRequest() no-op");
|
|
8906
8999
|
}
|
|
9000
|
+
async getCommitDiff(_commitSha) {
|
|
9001
|
+
console.warn("getCommitDiff() returning stub diff");
|
|
9002
|
+
return {
|
|
9003
|
+
diff: "",
|
|
9004
|
+
commitTimestamp: /* @__PURE__ */ new Date(),
|
|
9005
|
+
commitSha: _commitSha,
|
|
9006
|
+
authorName: void 0,
|
|
9007
|
+
authorEmail: void 0,
|
|
9008
|
+
message: void 0
|
|
9009
|
+
};
|
|
9010
|
+
}
|
|
8907
9011
|
};
|
|
8908
9012
|
|
|
8909
9013
|
// src/features/analysis/scm/scmFactory.ts
|
|
@@ -9456,7 +9560,8 @@ var mobbCliCommand = {
|
|
|
9456
9560
|
analyze: "analyze",
|
|
9457
9561
|
review: "review",
|
|
9458
9562
|
convertToSarif: "convert-to-sarif",
|
|
9459
|
-
mcp: "mcp"
|
|
9563
|
+
mcp: "mcp",
|
|
9564
|
+
uploadAiBlame: "upload-ai-blame"
|
|
9460
9565
|
};
|
|
9461
9566
|
var ScanContext = {
|
|
9462
9567
|
FULL_SCAN: "FULL_SCAN",
|
|
@@ -9467,7 +9572,7 @@ var ScanContext = {
|
|
|
9467
9572
|
};
|
|
9468
9573
|
|
|
9469
9574
|
// src/args/yargs.ts
|
|
9470
|
-
import
|
|
9575
|
+
import chalk11 from "chalk";
|
|
9471
9576
|
import yargs from "yargs/yargs";
|
|
9472
9577
|
|
|
9473
9578
|
// src/args/commands/analyze.ts
|
|
@@ -9836,7 +9941,7 @@ async function postIssueComment(params) {
|
|
|
9836
9941
|
fpDescription
|
|
9837
9942
|
} = params;
|
|
9838
9943
|
const {
|
|
9839
|
-
path:
|
|
9944
|
+
path: path17,
|
|
9840
9945
|
startLine,
|
|
9841
9946
|
vulnerabilityReportIssue: {
|
|
9842
9947
|
vulnerabilityReportIssueTags,
|
|
@@ -9851,7 +9956,7 @@ async function postIssueComment(params) {
|
|
|
9851
9956
|
Refresh the page in order to see the changes.`,
|
|
9852
9957
|
pull_number: pullRequest,
|
|
9853
9958
|
commit_id: commitSha,
|
|
9854
|
-
path:
|
|
9959
|
+
path: path17,
|
|
9855
9960
|
line: startLine
|
|
9856
9961
|
});
|
|
9857
9962
|
const commentId = commentRes.data.id;
|
|
@@ -9885,7 +9990,7 @@ async function postFixComment(params) {
|
|
|
9885
9990
|
scanner
|
|
9886
9991
|
} = params;
|
|
9887
9992
|
const {
|
|
9888
|
-
path:
|
|
9993
|
+
path: path17,
|
|
9889
9994
|
startLine,
|
|
9890
9995
|
vulnerabilityReportIssue: { fixId, vulnerabilityReportIssueTags, category },
|
|
9891
9996
|
vulnerabilityReportIssueId
|
|
@@ -9903,7 +10008,7 @@ async function postFixComment(params) {
|
|
|
9903
10008
|
Refresh the page in order to see the changes.`,
|
|
9904
10009
|
pull_number: pullRequest,
|
|
9905
10010
|
commit_id: commitSha,
|
|
9906
|
-
path:
|
|
10011
|
+
path: path17,
|
|
9907
10012
|
line: startLine
|
|
9908
10013
|
});
|
|
9909
10014
|
const commentId = commentRes.data.id;
|
|
@@ -12559,6 +12664,12 @@ var McpGQLClient = class {
|
|
|
12559
12664
|
}
|
|
12560
12665
|
};
|
|
12561
12666
|
}
|
|
12667
|
+
async uploadAIBlameInferencesInitRaw(variables) {
|
|
12668
|
+
return await this.clientSdk.UploadAIBlameInferencesInit(variables);
|
|
12669
|
+
}
|
|
12670
|
+
async finalizeAIBlameInferencesUploadRaw(variables) {
|
|
12671
|
+
return await this.clientSdk.FinalizeAIBlameInferencesUpload(variables);
|
|
12672
|
+
}
|
|
12562
12673
|
async isApiEndpointReachable() {
|
|
12563
12674
|
try {
|
|
12564
12675
|
logDebug("[GraphQL] Calling Me query for API connection verification");
|
|
@@ -13095,7 +13206,7 @@ var McpGQLClient = class {
|
|
|
13095
13206
|
}
|
|
13096
13207
|
};
|
|
13097
13208
|
async function createAuthenticatedMcpGQLClient({
|
|
13098
|
-
|
|
13209
|
+
isBackgroundCall = false
|
|
13099
13210
|
} = {}) {
|
|
13100
13211
|
logDebug("[GraphQL] Getting config", {
|
|
13101
13212
|
apiToken: configStore.get("apiToken")
|
|
@@ -13116,18 +13227,18 @@ async function createAuthenticatedMcpGQLClient({
|
|
|
13116
13227
|
return initialClient;
|
|
13117
13228
|
}
|
|
13118
13229
|
const authService = new McpAuthService(initialClient);
|
|
13119
|
-
const newApiToken = await authService.authenticate(
|
|
13230
|
+
const newApiToken = await authService.authenticate(isBackgroundCall);
|
|
13120
13231
|
configStore.set("apiToken", newApiToken);
|
|
13121
13232
|
return new McpGQLClient({ apiKey: newApiToken, type: "apiKey" });
|
|
13122
13233
|
}
|
|
13123
13234
|
|
|
13124
|
-
// src/mcp/services/McpUsageService.ts
|
|
13235
|
+
// src/mcp/services/McpUsageService/McpUsageService.ts
|
|
13125
13236
|
init_configs();
|
|
13126
13237
|
import fetch5 from "node-fetch";
|
|
13127
13238
|
import os4 from "os";
|
|
13128
13239
|
import { v4 as uuidv43, v5 as uuidv5 } from "uuid";
|
|
13129
13240
|
|
|
13130
|
-
// src/mcp/
|
|
13241
|
+
// src/mcp/services/McpUsageService/host.ts
|
|
13131
13242
|
import { execSync } from "child_process";
|
|
13132
13243
|
import fs10 from "fs";
|
|
13133
13244
|
import os3 from "os";
|
|
@@ -13242,7 +13353,7 @@ var getProcessInfo = (pid) => {
|
|
|
13242
13353
|
const cmd = parts.slice(2).join(" ");
|
|
13243
13354
|
return { pid: pidStr ?? "", ppid: ppid ?? "", cmd };
|
|
13244
13355
|
} else {
|
|
13245
|
-
logWarn(`Unsupported platform: ${platform}`);
|
|
13356
|
+
logWarn(`[UsageService] Unsupported platform: ${platform}`);
|
|
13246
13357
|
return null;
|
|
13247
13358
|
}
|
|
13248
13359
|
} catch {
|
|
@@ -13350,7 +13461,7 @@ var getHostInfo = () => {
|
|
|
13350
13461
|
return { mcps: results, user: gitInfo };
|
|
13351
13462
|
};
|
|
13352
13463
|
|
|
13353
|
-
// src/mcp/services/McpUsageService.ts
|
|
13464
|
+
// src/mcp/services/McpUsageService/McpUsageService.ts
|
|
13354
13465
|
var McpUsageService = class {
|
|
13355
13466
|
constructor() {
|
|
13356
13467
|
__publicField(this, "configKey", "mcpUsage");
|
|
@@ -13364,10 +13475,9 @@ var McpUsageService = class {
|
|
|
13364
13475
|
}
|
|
13365
13476
|
}
|
|
13366
13477
|
startPeriodicTracking() {
|
|
13367
|
-
|
|
13368
|
-
logDebug(`[${scanContext}] Starting periodic tracking for mcps`, {});
|
|
13478
|
+
logDebug(`[UsageService] Starting periodic tracking for mcps`, {});
|
|
13369
13479
|
this.intervalId = setInterval(async () => {
|
|
13370
|
-
logDebug(`[
|
|
13480
|
+
logDebug(`[UsageService] Triggering periodic usage service`, {
|
|
13371
13481
|
MCP_PERIODIC_TRACK_INTERVAL
|
|
13372
13482
|
});
|
|
13373
13483
|
await mcpUsageService.trackServerStart();
|
|
@@ -13386,13 +13496,13 @@ var McpUsageService = class {
|
|
|
13386
13496
|
}
|
|
13387
13497
|
const macString = macs.length ? macs.sort().join(",") : `${os4.hostname()}-${uuidv43()}`;
|
|
13388
13498
|
const hostId = uuidv5(macString, uuidv5.DNS);
|
|
13389
|
-
logDebug("Generated new host ID", { hostId });
|
|
13499
|
+
logDebug("[UsageService] Generated new host ID", { hostId });
|
|
13390
13500
|
return hostId;
|
|
13391
13501
|
}
|
|
13392
13502
|
getOrganizationId() {
|
|
13393
13503
|
const organizationId = configStore.get("GOV-ORG-ID") || "";
|
|
13394
13504
|
if (organizationId) {
|
|
13395
|
-
logDebug("Using stored organization ID", {
|
|
13505
|
+
logDebug("[UsageService] Using stored organization ID", {
|
|
13396
13506
|
organizationId
|
|
13397
13507
|
});
|
|
13398
13508
|
return organizationId;
|
|
@@ -13419,7 +13529,9 @@ var McpUsageService = class {
|
|
|
13419
13529
|
const hostId = this.generateHostId();
|
|
13420
13530
|
const organizationId = this.getOrganizationId();
|
|
13421
13531
|
if (!organizationId) {
|
|
13422
|
-
logError(
|
|
13532
|
+
logError(
|
|
13533
|
+
"[UsageService] Cannot track MCP usage - organization ID not available"
|
|
13534
|
+
);
|
|
13423
13535
|
return;
|
|
13424
13536
|
}
|
|
13425
13537
|
const usageData = this.createUsageData(hostId, organizationId, status);
|
|
@@ -13428,10 +13540,12 @@ var McpUsageService = class {
|
|
|
13428
13540
|
(key) => usageData[key] !== stored[key]
|
|
13429
13541
|
);
|
|
13430
13542
|
if (!hasChanges) {
|
|
13431
|
-
logDebug(
|
|
13543
|
+
logDebug(
|
|
13544
|
+
`[UsageService] Skipping ${status} usage tracking - no changes`
|
|
13545
|
+
);
|
|
13432
13546
|
return;
|
|
13433
13547
|
}
|
|
13434
|
-
logDebug("Before", { usageData });
|
|
13548
|
+
logDebug("[UsageService] Before", { usageData });
|
|
13435
13549
|
try {
|
|
13436
13550
|
const res = await fetch5(this.REST_API_URL, {
|
|
13437
13551
|
method: "POST",
|
|
@@ -13448,19 +13562,19 @@ var McpUsageService = class {
|
|
|
13448
13562
|
})
|
|
13449
13563
|
});
|
|
13450
13564
|
const authResult = await res.json();
|
|
13451
|
-
logDebug("Success usage data", { authResult });
|
|
13565
|
+
logDebug("[UsageService] Success usage data", { authResult });
|
|
13452
13566
|
} catch (err) {
|
|
13453
|
-
logDebug("Error usage data", { err });
|
|
13567
|
+
logDebug("[UsageService] Error usage data", { err });
|
|
13454
13568
|
}
|
|
13455
|
-
logDebug("Saving usage data", { usageData });
|
|
13569
|
+
logDebug("[UsageService] Saving usage data", { usageData });
|
|
13456
13570
|
configStore.set(this.configKey, usageData);
|
|
13457
13571
|
logInfo(
|
|
13458
|
-
`MCP server ${status === "ACTIVE" ? "start" : "stop"} tracked successfully`
|
|
13572
|
+
`[UsageService] MCP server ${status === "ACTIVE" ? "start" : "stop"} tracked successfully`
|
|
13459
13573
|
);
|
|
13460
13574
|
} catch (error) {
|
|
13461
13575
|
configStore.set(this.configKey, { status: "FAILED" });
|
|
13462
13576
|
logError(
|
|
13463
|
-
`Failed to track MCP server ${status === "ACTIVE" ? "start" : "stop"}`,
|
|
13577
|
+
`[UsageService] Failed to track MCP server ${status === "ACTIVE" ? "start" : "stop"}`,
|
|
13464
13578
|
{ error }
|
|
13465
13579
|
);
|
|
13466
13580
|
}
|
|
@@ -13530,6 +13644,9 @@ var McpServer = class {
|
|
|
13530
13644
|
__publicField(this, "toolRegistry");
|
|
13531
13645
|
__publicField(this, "isEventHandlersSetup", false);
|
|
13532
13646
|
__publicField(this, "eventHandlers", /* @__PURE__ */ new Map());
|
|
13647
|
+
__publicField(this, "parentProcessCheckInterval");
|
|
13648
|
+
__publicField(this, "parentPid");
|
|
13649
|
+
this.parentPid = process.ppid;
|
|
13533
13650
|
this.server = new Server(
|
|
13534
13651
|
{
|
|
13535
13652
|
name: config4.name,
|
|
@@ -13544,8 +13661,12 @@ var McpServer = class {
|
|
|
13544
13661
|
this.toolRegistry = new ToolRegistry();
|
|
13545
13662
|
this.setupHandlers();
|
|
13546
13663
|
this.setupProcessEventHandlers();
|
|
13664
|
+
this.setupParentProcessMonitoring();
|
|
13547
13665
|
logInfo("MCP server instance created");
|
|
13548
|
-
logDebug("MCP server instance config", {
|
|
13666
|
+
logDebug("MCP server instance config", {
|
|
13667
|
+
config: config4,
|
|
13668
|
+
parentPid: this.parentPid
|
|
13669
|
+
});
|
|
13549
13670
|
}
|
|
13550
13671
|
async trackServerUsage(action, signalOrError) {
|
|
13551
13672
|
try {
|
|
@@ -13570,6 +13691,12 @@ var McpServer = class {
|
|
|
13570
13691
|
const messages = {
|
|
13571
13692
|
SIGINT: "MCP server interrupted",
|
|
13572
13693
|
SIGTERM: "MCP server terminated",
|
|
13694
|
+
SIGHUP: "MCP server hangup signal received",
|
|
13695
|
+
SIGQUIT: "MCP server quit signal received",
|
|
13696
|
+
SIGABRT: "MCP server abort signal received",
|
|
13697
|
+
SIGPIPE: "MCP server broken pipe signal received",
|
|
13698
|
+
SIGCHLD: "MCP server child process signal received",
|
|
13699
|
+
SIGTSTP: "MCP server terminal stop signal received",
|
|
13573
13700
|
exit: "MCP server exiting",
|
|
13574
13701
|
uncaughtException: "Uncaught exception in MCP server",
|
|
13575
13702
|
unhandledRejection: "Unhandled promise rejection in MCP server",
|
|
@@ -13600,7 +13727,10 @@ var McpServer = class {
|
|
|
13600
13727
|
} else {
|
|
13601
13728
|
logDebug(message, { signal });
|
|
13602
13729
|
}
|
|
13603
|
-
if (signal === "
|
|
13730
|
+
if (signal === "SIGCHLD") {
|
|
13731
|
+
return;
|
|
13732
|
+
}
|
|
13733
|
+
if (signal === "SIGINT" || signal === "SIGTERM" || signal === "SIGHUP" || signal === "SIGQUIT" || signal === "SIGABRT" || signal === "SIGPIPE" || signal === "SIGTSTP") {
|
|
13604
13734
|
await this.trackServerUsage("stop", signal);
|
|
13605
13735
|
process.exit(0);
|
|
13606
13736
|
}
|
|
@@ -13609,6 +13739,62 @@ var McpServer = class {
|
|
|
13609
13739
|
process.exit(1);
|
|
13610
13740
|
}
|
|
13611
13741
|
}
|
|
13742
|
+
isParentProcessAlive() {
|
|
13743
|
+
try {
|
|
13744
|
+
process.kill(this.parentPid, 0);
|
|
13745
|
+
return true;
|
|
13746
|
+
} catch (error) {
|
|
13747
|
+
return false;
|
|
13748
|
+
}
|
|
13749
|
+
}
|
|
13750
|
+
async handleParentProcessDeath(source) {
|
|
13751
|
+
logInfo(`Parent process death detected via ${source}`, {
|
|
13752
|
+
parentPid: this.parentPid
|
|
13753
|
+
});
|
|
13754
|
+
await this.trackServerUsage("stop", `parent-death-${source}`);
|
|
13755
|
+
process.exit(0);
|
|
13756
|
+
}
|
|
13757
|
+
setupParentProcessMonitoring() {
|
|
13758
|
+
logInfo("Setting up parent process monitoring", {
|
|
13759
|
+
parentPid: this.parentPid
|
|
13760
|
+
});
|
|
13761
|
+
process.stdin.on("close", async () => {
|
|
13762
|
+
logDebug("stdin closed - parent likely terminated");
|
|
13763
|
+
await this.handleParentProcessDeath("stdin-close");
|
|
13764
|
+
});
|
|
13765
|
+
process.stdin.on("end", async () => {
|
|
13766
|
+
logDebug("stdin ended - parent likely terminated");
|
|
13767
|
+
await this.handleParentProcessDeath("stdin-end");
|
|
13768
|
+
});
|
|
13769
|
+
process.stdout.on("error", async (error) => {
|
|
13770
|
+
logWarn("stdout error - parent may have terminated", { error });
|
|
13771
|
+
if (error.message.includes("EPIPE") || error.message.includes("ECONNRESET")) {
|
|
13772
|
+
await this.handleParentProcessDeath("stdout-error");
|
|
13773
|
+
}
|
|
13774
|
+
});
|
|
13775
|
+
process.stderr.on("error", async (error) => {
|
|
13776
|
+
logWarn("stderr error - parent may have terminated", { error });
|
|
13777
|
+
if (error.message.includes("EPIPE") || error.message.includes("ECONNRESET")) {
|
|
13778
|
+
await this.handleParentProcessDeath("stderr-error");
|
|
13779
|
+
}
|
|
13780
|
+
});
|
|
13781
|
+
if (process.send) {
|
|
13782
|
+
process.on("disconnect", async () => {
|
|
13783
|
+
logDebug("IPC disconnected - parent terminated");
|
|
13784
|
+
await this.handleParentProcessDeath("ipc-disconnect");
|
|
13785
|
+
});
|
|
13786
|
+
logDebug("IPC monitoring enabled");
|
|
13787
|
+
} else {
|
|
13788
|
+
logDebug("IPC not available - skipping IPC monitoring");
|
|
13789
|
+
}
|
|
13790
|
+
this.parentProcessCheckInterval = setInterval(async () => {
|
|
13791
|
+
if (!this.isParentProcessAlive()) {
|
|
13792
|
+
logDebug("Parent process not alive during periodic check");
|
|
13793
|
+
await this.handleParentProcessDeath("periodic-check");
|
|
13794
|
+
}
|
|
13795
|
+
}, 1e4);
|
|
13796
|
+
logInfo("Parent process monitoring setup complete");
|
|
13797
|
+
}
|
|
13612
13798
|
setupProcessEventHandlers() {
|
|
13613
13799
|
if (this.isEventHandlersSetup) {
|
|
13614
13800
|
logDebug("Process event handlers already setup, skipping");
|
|
@@ -13617,6 +13803,12 @@ var McpServer = class {
|
|
|
13617
13803
|
const signals = [
|
|
13618
13804
|
"SIGINT",
|
|
13619
13805
|
"SIGTERM",
|
|
13806
|
+
"SIGHUP",
|
|
13807
|
+
"SIGQUIT",
|
|
13808
|
+
"SIGABRT",
|
|
13809
|
+
"SIGPIPE",
|
|
13810
|
+
"SIGCHLD",
|
|
13811
|
+
"SIGTSTP",
|
|
13620
13812
|
"exit",
|
|
13621
13813
|
"uncaughtException",
|
|
13622
13814
|
"unhandledRejection",
|
|
@@ -13640,12 +13832,17 @@ var McpServer = class {
|
|
|
13640
13832
|
};
|
|
13641
13833
|
process.once("SIGINT", cleanup);
|
|
13642
13834
|
process.once("SIGTERM", cleanup);
|
|
13835
|
+
process.once("SIGHUP", cleanup);
|
|
13836
|
+
process.once("SIGQUIT", cleanup);
|
|
13837
|
+
process.once("SIGABRT", cleanup);
|
|
13838
|
+
process.once("SIGPIPE", cleanup);
|
|
13839
|
+
process.once("SIGTSTP", cleanup);
|
|
13643
13840
|
});
|
|
13644
13841
|
}
|
|
13645
13842
|
async triggerScanForNewAvailableFixes() {
|
|
13646
13843
|
try {
|
|
13647
13844
|
const gqlClient = await createAuthenticatedMcpGQLClient({
|
|
13648
|
-
|
|
13845
|
+
isBackgroundCall: true
|
|
13649
13846
|
});
|
|
13650
13847
|
const isConnected = await gqlClient.verifyApiConnection();
|
|
13651
13848
|
if (!isConnected) {
|
|
@@ -13770,6 +13967,12 @@ var McpServer = class {
|
|
|
13770
13967
|
this.toolRegistry.registerTool(tool);
|
|
13771
13968
|
logInfo(`Tool registered: ${tool.name}`);
|
|
13772
13969
|
}
|
|
13970
|
+
getParentProcessId() {
|
|
13971
|
+
return this.parentPid;
|
|
13972
|
+
}
|
|
13973
|
+
checkParentProcessAlive() {
|
|
13974
|
+
return this.isParentProcessAlive();
|
|
13975
|
+
}
|
|
13773
13976
|
async start() {
|
|
13774
13977
|
try {
|
|
13775
13978
|
logInfo("Starting MCP server");
|
|
@@ -13788,6 +13991,11 @@ var McpServer = class {
|
|
|
13788
13991
|
async stop() {
|
|
13789
13992
|
logDebug("MCP server shutting down");
|
|
13790
13993
|
await this.trackServerUsage("stop");
|
|
13994
|
+
if (this.parentProcessCheckInterval) {
|
|
13995
|
+
clearInterval(this.parentProcessCheckInterval);
|
|
13996
|
+
this.parentProcessCheckInterval = void 0;
|
|
13997
|
+
logDebug("Parent process check interval cleared");
|
|
13998
|
+
}
|
|
13791
13999
|
this.eventHandlers.forEach((handler, signal) => {
|
|
13792
14000
|
process.removeListener(signal, handler);
|
|
13793
14001
|
});
|
|
@@ -14421,23 +14629,23 @@ init_configs();
|
|
|
14421
14629
|
import fs12 from "fs/promises";
|
|
14422
14630
|
import nodePath from "path";
|
|
14423
14631
|
var getLocalFiles = async ({
|
|
14424
|
-
path:
|
|
14632
|
+
path: path17,
|
|
14425
14633
|
maxFileSize = MCP_MAX_FILE_SIZE,
|
|
14426
14634
|
maxFiles,
|
|
14427
14635
|
isAllFilesScan,
|
|
14428
14636
|
scanContext
|
|
14429
14637
|
}) => {
|
|
14430
14638
|
logDebug(`[${scanContext}] Starting getLocalFiles`, {
|
|
14431
|
-
path:
|
|
14639
|
+
path: path17,
|
|
14432
14640
|
maxFileSize,
|
|
14433
14641
|
maxFiles,
|
|
14434
14642
|
isAllFilesScan
|
|
14435
14643
|
});
|
|
14436
14644
|
try {
|
|
14437
|
-
const resolvedRepoPath = await fs12.realpath(
|
|
14645
|
+
const resolvedRepoPath = await fs12.realpath(path17);
|
|
14438
14646
|
logDebug(`[${scanContext}] Resolved repository path`, {
|
|
14439
14647
|
resolvedRepoPath,
|
|
14440
|
-
originalPath:
|
|
14648
|
+
originalPath: path17
|
|
14441
14649
|
});
|
|
14442
14650
|
const gitService = new GitService(resolvedRepoPath, log);
|
|
14443
14651
|
const gitValidation = await gitService.validateRepository();
|
|
@@ -14450,7 +14658,7 @@ var getLocalFiles = async ({
|
|
|
14450
14658
|
if (!gitValidation.isValid || isAllFilesScan) {
|
|
14451
14659
|
try {
|
|
14452
14660
|
files = await FileUtils.getLastChangedFiles({
|
|
14453
|
-
dir:
|
|
14661
|
+
dir: path17,
|
|
14454
14662
|
maxFileSize,
|
|
14455
14663
|
maxFiles,
|
|
14456
14664
|
isAllFilesScan
|
|
@@ -14542,7 +14750,7 @@ var getLocalFiles = async ({
|
|
|
14542
14750
|
logError(`${scanContext}Unexpected error in getLocalFiles`, {
|
|
14543
14751
|
error: error instanceof Error ? error.message : String(error),
|
|
14544
14752
|
stack: error instanceof Error ? error.stack : void 0,
|
|
14545
|
-
path:
|
|
14753
|
+
path: path17
|
|
14546
14754
|
});
|
|
14547
14755
|
throw error;
|
|
14548
14756
|
}
|
|
@@ -16676,14 +16884,14 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
16676
16884
|
* since the last scan.
|
|
16677
16885
|
*/
|
|
16678
16886
|
async scanForSecurityVulnerabilities({
|
|
16679
|
-
path:
|
|
16887
|
+
path: path17,
|
|
16680
16888
|
isAllDetectionRulesScan,
|
|
16681
16889
|
isAllFilesScan,
|
|
16682
16890
|
scanContext
|
|
16683
16891
|
}) {
|
|
16684
16892
|
this.hasAuthenticationFailed = false;
|
|
16685
16893
|
logDebug(`[${scanContext}] Scanning for new security vulnerabilities`, {
|
|
16686
|
-
path:
|
|
16894
|
+
path: path17
|
|
16687
16895
|
});
|
|
16688
16896
|
if (!this.gqlClient) {
|
|
16689
16897
|
logInfo(`[${scanContext}] No GQL client found, skipping scan`);
|
|
@@ -16699,10 +16907,10 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
16699
16907
|
}
|
|
16700
16908
|
logDebug(
|
|
16701
16909
|
`[${scanContext}] Connected to the API, assembling list of files to scan`,
|
|
16702
|
-
{ path:
|
|
16910
|
+
{ path: path17 }
|
|
16703
16911
|
);
|
|
16704
16912
|
const files = await getLocalFiles({
|
|
16705
|
-
path:
|
|
16913
|
+
path: path17,
|
|
16706
16914
|
isAllFilesScan,
|
|
16707
16915
|
scanContext
|
|
16708
16916
|
});
|
|
@@ -16727,13 +16935,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
16727
16935
|
});
|
|
16728
16936
|
const { fixReportId, projectId } = await scanFiles({
|
|
16729
16937
|
fileList: filesToScan.map((file) => file.relativePath),
|
|
16730
|
-
repositoryPath:
|
|
16938
|
+
repositoryPath: path17,
|
|
16731
16939
|
gqlClient: this.gqlClient,
|
|
16732
16940
|
isAllDetectionRulesScan,
|
|
16733
16941
|
scanContext
|
|
16734
16942
|
});
|
|
16735
16943
|
logInfo(
|
|
16736
|
-
`[${scanContext}] Security scan completed for ${
|
|
16944
|
+
`[${scanContext}] Security scan completed for ${path17} reportId: ${fixReportId} projectId: ${projectId}`
|
|
16737
16945
|
);
|
|
16738
16946
|
if (isAllFilesScan) {
|
|
16739
16947
|
return;
|
|
@@ -17027,13 +17235,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
17027
17235
|
});
|
|
17028
17236
|
return scannedFiles.some((file) => file.relativePath === fixFile);
|
|
17029
17237
|
}
|
|
17030
|
-
async getFreshFixes({ path:
|
|
17238
|
+
async getFreshFixes({ path: path17 }) {
|
|
17031
17239
|
const scanContext = ScanContext.USER_REQUEST;
|
|
17032
|
-
logDebug(`[${scanContext}] Getting fresh fixes`, { path:
|
|
17033
|
-
if (this.path !==
|
|
17034
|
-
this.path =
|
|
17240
|
+
logDebug(`[${scanContext}] Getting fresh fixes`, { path: path17 });
|
|
17241
|
+
if (this.path !== path17) {
|
|
17242
|
+
this.path = path17;
|
|
17035
17243
|
this.reset();
|
|
17036
|
-
logInfo(`[${scanContext}] Reset service state for new path`, { path:
|
|
17244
|
+
logInfo(`[${scanContext}] Reset service state for new path`, { path: path17 });
|
|
17037
17245
|
}
|
|
17038
17246
|
try {
|
|
17039
17247
|
this.gqlClient = await createAuthenticatedMcpGQLClient();
|
|
@@ -17051,7 +17259,7 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
17051
17259
|
}
|
|
17052
17260
|
throw error;
|
|
17053
17261
|
}
|
|
17054
|
-
this.triggerScan({ path:
|
|
17262
|
+
this.triggerScan({ path: path17, gqlClient: this.gqlClient });
|
|
17055
17263
|
let isMvsAutoFixEnabled = null;
|
|
17056
17264
|
try {
|
|
17057
17265
|
isMvsAutoFixEnabled = await this.gqlClient.getMvsAutoFixSettings();
|
|
@@ -17085,33 +17293,33 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
17085
17293
|
return noFreshFixesPrompt;
|
|
17086
17294
|
}
|
|
17087
17295
|
triggerScan({
|
|
17088
|
-
path:
|
|
17296
|
+
path: path17,
|
|
17089
17297
|
gqlClient
|
|
17090
17298
|
}) {
|
|
17091
|
-
if (this.path !==
|
|
17092
|
-
this.path =
|
|
17299
|
+
if (this.path !== path17) {
|
|
17300
|
+
this.path = path17;
|
|
17093
17301
|
this.reset();
|
|
17094
|
-
logInfo(`Reset service state for new path in triggerScan`, { path:
|
|
17302
|
+
logInfo(`Reset service state for new path in triggerScan`, { path: path17 });
|
|
17095
17303
|
}
|
|
17096
17304
|
this.gqlClient = gqlClient;
|
|
17097
17305
|
if (!this.intervalId) {
|
|
17098
|
-
this.startPeriodicScanning(
|
|
17099
|
-
this.executeInitialScan(
|
|
17100
|
-
void this.executeInitialFullScan(
|
|
17306
|
+
this.startPeriodicScanning(path17);
|
|
17307
|
+
this.executeInitialScan(path17);
|
|
17308
|
+
void this.executeInitialFullScan(path17);
|
|
17101
17309
|
}
|
|
17102
17310
|
}
|
|
17103
|
-
startPeriodicScanning(
|
|
17311
|
+
startPeriodicScanning(path17) {
|
|
17104
17312
|
const scanContext = ScanContext.BACKGROUND_PERIODIC;
|
|
17105
17313
|
logDebug(
|
|
17106
17314
|
`[${scanContext}] Starting periodic scan for new security vulnerabilities`,
|
|
17107
17315
|
{
|
|
17108
|
-
path:
|
|
17316
|
+
path: path17
|
|
17109
17317
|
}
|
|
17110
17318
|
);
|
|
17111
17319
|
this.intervalId = setInterval(() => {
|
|
17112
|
-
logDebug(`[${scanContext}] Triggering periodic security scan`, { path:
|
|
17320
|
+
logDebug(`[${scanContext}] Triggering periodic security scan`, { path: path17 });
|
|
17113
17321
|
this.scanForSecurityVulnerabilities({
|
|
17114
|
-
path:
|
|
17322
|
+
path: path17,
|
|
17115
17323
|
scanContext
|
|
17116
17324
|
}).catch((error) => {
|
|
17117
17325
|
logError(`[${scanContext}] Error during periodic security scan`, {
|
|
@@ -17120,45 +17328,45 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
17120
17328
|
});
|
|
17121
17329
|
}, MCP_PERIODIC_CHECK_INTERVAL);
|
|
17122
17330
|
}
|
|
17123
|
-
async executeInitialFullScan(
|
|
17331
|
+
async executeInitialFullScan(path17) {
|
|
17124
17332
|
const scanContext = ScanContext.FULL_SCAN;
|
|
17125
|
-
logDebug(`[${scanContext}] Triggering initial full security scan`, { path:
|
|
17333
|
+
logDebug(`[${scanContext}] Triggering initial full security scan`, { path: path17 });
|
|
17126
17334
|
logDebug(`[${scanContext}] Full scan paths scanned`, {
|
|
17127
17335
|
fullScanPathsScanned: this.fullScanPathsScanned
|
|
17128
17336
|
});
|
|
17129
|
-
if (this.fullScanPathsScanned.includes(
|
|
17337
|
+
if (this.fullScanPathsScanned.includes(path17)) {
|
|
17130
17338
|
logDebug(`[${scanContext}] Full scan already executed for this path`, {
|
|
17131
|
-
path:
|
|
17339
|
+
path: path17
|
|
17132
17340
|
});
|
|
17133
17341
|
return;
|
|
17134
17342
|
}
|
|
17135
17343
|
configStore.set("fullScanPathsScanned", [
|
|
17136
17344
|
...this.fullScanPathsScanned,
|
|
17137
|
-
|
|
17345
|
+
path17
|
|
17138
17346
|
]);
|
|
17139
17347
|
try {
|
|
17140
17348
|
await this.scanForSecurityVulnerabilities({
|
|
17141
|
-
path:
|
|
17349
|
+
path: path17,
|
|
17142
17350
|
isAllFilesScan: true,
|
|
17143
17351
|
isAllDetectionRulesScan: true,
|
|
17144
17352
|
scanContext: ScanContext.FULL_SCAN
|
|
17145
17353
|
});
|
|
17146
|
-
if (!this.fullScanPathsScanned.includes(
|
|
17147
|
-
this.fullScanPathsScanned.push(
|
|
17354
|
+
if (!this.fullScanPathsScanned.includes(path17)) {
|
|
17355
|
+
this.fullScanPathsScanned.push(path17);
|
|
17148
17356
|
configStore.set("fullScanPathsScanned", this.fullScanPathsScanned);
|
|
17149
17357
|
}
|
|
17150
|
-
logInfo(`[${scanContext}] Full scan completed`, { path:
|
|
17358
|
+
logInfo(`[${scanContext}] Full scan completed`, { path: path17 });
|
|
17151
17359
|
} catch (error) {
|
|
17152
17360
|
logError(`[${scanContext}] Error during initial full security scan`, {
|
|
17153
17361
|
error
|
|
17154
17362
|
});
|
|
17155
17363
|
}
|
|
17156
17364
|
}
|
|
17157
|
-
executeInitialScan(
|
|
17365
|
+
executeInitialScan(path17) {
|
|
17158
17366
|
const scanContext = ScanContext.BACKGROUND_INITIAL;
|
|
17159
|
-
logDebug(`[${scanContext}] Triggering initial security scan`, { path:
|
|
17367
|
+
logDebug(`[${scanContext}] Triggering initial security scan`, { path: path17 });
|
|
17160
17368
|
this.scanForSecurityVulnerabilities({
|
|
17161
|
-
path:
|
|
17369
|
+
path: path17,
|
|
17162
17370
|
scanContext: ScanContext.BACKGROUND_INITIAL
|
|
17163
17371
|
}).catch((error) => {
|
|
17164
17372
|
logError(`[${scanContext}] Error during initial security scan`, { error });
|
|
@@ -17254,9 +17462,9 @@ Example payload:
|
|
|
17254
17462
|
`Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
|
|
17255
17463
|
);
|
|
17256
17464
|
}
|
|
17257
|
-
const
|
|
17465
|
+
const path17 = pathValidationResult.path;
|
|
17258
17466
|
const resultText = await this.newFixesService.getFreshFixes({
|
|
17259
|
-
path:
|
|
17467
|
+
path: path17
|
|
17260
17468
|
});
|
|
17261
17469
|
logInfo("CheckForNewAvailableFixesTool execution completed", {
|
|
17262
17470
|
resultText
|
|
@@ -17404,8 +17612,8 @@ Call this tool instead of ${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES} when you only
|
|
|
17404
17612
|
`Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
|
|
17405
17613
|
);
|
|
17406
17614
|
}
|
|
17407
|
-
const
|
|
17408
|
-
const gitService = new GitService(
|
|
17615
|
+
const path17 = pathValidationResult.path;
|
|
17616
|
+
const gitService = new GitService(path17, log);
|
|
17409
17617
|
const gitValidation = await gitService.validateRepository();
|
|
17410
17618
|
if (!gitValidation.isValid) {
|
|
17411
17619
|
throw new Error(`Invalid git repository: ${gitValidation.error}`);
|
|
@@ -17671,9 +17879,9 @@ Example payload:
|
|
|
17671
17879
|
`Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
|
|
17672
17880
|
);
|
|
17673
17881
|
}
|
|
17674
|
-
const
|
|
17882
|
+
const path17 = pathValidationResult.path;
|
|
17675
17883
|
const files = await getLocalFiles({
|
|
17676
|
-
path:
|
|
17884
|
+
path: path17,
|
|
17677
17885
|
maxFileSize: MCP_MAX_FILE_SIZE,
|
|
17678
17886
|
maxFiles: args.maxFiles,
|
|
17679
17887
|
scanContext: ScanContext.USER_REQUEST
|
|
@@ -17692,7 +17900,7 @@ Example payload:
|
|
|
17692
17900
|
try {
|
|
17693
17901
|
const fixResult = await this.vulnerabilityFixService.processVulnerabilities({
|
|
17694
17902
|
fileList: files.map((file) => file.relativePath),
|
|
17695
|
-
repositoryPath:
|
|
17903
|
+
repositoryPath: path17,
|
|
17696
17904
|
offset: args.offset,
|
|
17697
17905
|
limit: args.limit,
|
|
17698
17906
|
isRescan: args.rescan || !!args.maxFiles
|
|
@@ -17886,60 +18094,183 @@ async function addScmTokenHandler(args) {
|
|
|
17886
18094
|
await addScmToken(args);
|
|
17887
18095
|
}
|
|
17888
18096
|
|
|
18097
|
+
// src/args/commands/upload_ai_blame.ts
|
|
18098
|
+
import fs17 from "fs/promises";
|
|
18099
|
+
import path16 from "path";
|
|
18100
|
+
import chalk10 from "chalk";
|
|
18101
|
+
function uploadAiBlameBuilder(args) {
|
|
18102
|
+
return args.option("prompt", {
|
|
18103
|
+
type: "string",
|
|
18104
|
+
array: true,
|
|
18105
|
+
demandOption: true,
|
|
18106
|
+
describe: chalk10.bold("Path(s) to prompt artifact(s) (one per session)")
|
|
18107
|
+
}).option("inference", {
|
|
18108
|
+
type: "string",
|
|
18109
|
+
array: true,
|
|
18110
|
+
demandOption: true,
|
|
18111
|
+
describe: chalk10.bold(
|
|
18112
|
+
"Path(s) to inference artifact(s) (one per session)"
|
|
18113
|
+
)
|
|
18114
|
+
}).option("ai-response-at", {
|
|
18115
|
+
type: "string",
|
|
18116
|
+
array: true,
|
|
18117
|
+
describe: chalk10.bold(
|
|
18118
|
+
"ISO timestamp(s) for AI response (one per session, defaults to now)"
|
|
18119
|
+
)
|
|
18120
|
+
}).option("model", {
|
|
18121
|
+
type: "string",
|
|
18122
|
+
array: true,
|
|
18123
|
+
describe: chalk10.bold("AI model name(s) (optional, one per session)")
|
|
18124
|
+
}).option("tool-name", {
|
|
18125
|
+
type: "string",
|
|
18126
|
+
array: true,
|
|
18127
|
+
describe: chalk10.bold("Tool/IDE name(s) (optional, one per session)")
|
|
18128
|
+
}).strict();
|
|
18129
|
+
}
|
|
18130
|
+
async function uploadAiBlameHandler(args) {
|
|
18131
|
+
const prompts = args.prompt || [];
|
|
18132
|
+
const inferences = args.inference || [];
|
|
18133
|
+
const models = args.model || [];
|
|
18134
|
+
const tools = args.toolName || args["tool-name"] || [];
|
|
18135
|
+
const responseTimes = args.aiResponseAt || args["ai-response-at"] || [];
|
|
18136
|
+
if (prompts.length !== inferences.length) {
|
|
18137
|
+
console.error(
|
|
18138
|
+
chalk10.red("prompt and inference must have the same number of entries")
|
|
18139
|
+
);
|
|
18140
|
+
process.exit(1);
|
|
18141
|
+
}
|
|
18142
|
+
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
18143
|
+
const sessions = [];
|
|
18144
|
+
for (let i = 0; i < prompts.length; i++) {
|
|
18145
|
+
const promptPath = String(prompts[i]);
|
|
18146
|
+
const inferencePath = String(inferences[i]);
|
|
18147
|
+
try {
|
|
18148
|
+
await Promise.all([fs17.access(promptPath), fs17.access(inferencePath)]);
|
|
18149
|
+
} catch {
|
|
18150
|
+
console.error(chalk10.red(`File not found for session ${i + 1}`));
|
|
18151
|
+
process.exit(1);
|
|
18152
|
+
}
|
|
18153
|
+
sessions.push({
|
|
18154
|
+
promptFileName: path16.basename(promptPath),
|
|
18155
|
+
inferenceFileName: path16.basename(inferencePath),
|
|
18156
|
+
aiResponseAt: responseTimes[i] || nowIso,
|
|
18157
|
+
model: models[i],
|
|
18158
|
+
toolName: tools[i]
|
|
18159
|
+
});
|
|
18160
|
+
}
|
|
18161
|
+
const gqlClient = await createAuthenticatedMcpGQLClient();
|
|
18162
|
+
const initRes = await gqlClient.uploadAIBlameInferencesInitRaw({ sessions });
|
|
18163
|
+
const uploadSessions = initRes.uploadAIBlameInferencesInit?.uploadSessions ?? [];
|
|
18164
|
+
if (uploadSessions.length !== sessions.length) {
|
|
18165
|
+
console.error(
|
|
18166
|
+
chalk10.red("Init failed to return expected number of sessions")
|
|
18167
|
+
);
|
|
18168
|
+
process.exit(1);
|
|
18169
|
+
}
|
|
18170
|
+
for (let i = 0; i < uploadSessions.length; i++) {
|
|
18171
|
+
const us = uploadSessions[i];
|
|
18172
|
+
const promptPath = String(prompts[i]);
|
|
18173
|
+
const inferencePath = String(inferences[i]);
|
|
18174
|
+
await uploadFile({
|
|
18175
|
+
file: promptPath,
|
|
18176
|
+
url: us.prompt.url,
|
|
18177
|
+
uploadFields: JSON.parse(us.prompt.uploadFieldsJSON),
|
|
18178
|
+
uploadKey: us.prompt.uploadKey
|
|
18179
|
+
});
|
|
18180
|
+
await uploadFile({
|
|
18181
|
+
file: inferencePath,
|
|
18182
|
+
url: us.inference.url,
|
|
18183
|
+
uploadFields: JSON.parse(us.inference.uploadFieldsJSON),
|
|
18184
|
+
uploadKey: us.inference.uploadKey
|
|
18185
|
+
});
|
|
18186
|
+
}
|
|
18187
|
+
const finalizeSessions = uploadSessions.map((us, i) => {
|
|
18188
|
+
const s = sessions[i];
|
|
18189
|
+
return {
|
|
18190
|
+
aiBlameInferenceId: us.aiBlameInferenceId,
|
|
18191
|
+
promptKey: us.prompt.uploadKey,
|
|
18192
|
+
inferenceKey: us.inference.uploadKey,
|
|
18193
|
+
aiResponseAt: s.aiResponseAt,
|
|
18194
|
+
model: s.model,
|
|
18195
|
+
toolName: s.toolName
|
|
18196
|
+
};
|
|
18197
|
+
});
|
|
18198
|
+
const finRes = await gqlClient.finalizeAIBlameInferencesUploadRaw({
|
|
18199
|
+
sessions: finalizeSessions
|
|
18200
|
+
});
|
|
18201
|
+
const status = finRes?.finalizeAIBlameInferencesUpload?.status;
|
|
18202
|
+
if (status !== "OK") {
|
|
18203
|
+
console.error(
|
|
18204
|
+
chalk10.red(
|
|
18205
|
+
`Finalize failed: ${finRes?.finalizeAIBlameInferencesUpload?.error || "unknown error"}`
|
|
18206
|
+
)
|
|
18207
|
+
);
|
|
18208
|
+
process.exit(1);
|
|
18209
|
+
}
|
|
18210
|
+
console.log(chalk10.green("AI Blame uploads finalized successfully"));
|
|
18211
|
+
}
|
|
18212
|
+
|
|
17889
18213
|
// src/args/yargs.ts
|
|
17890
18214
|
var parseArgs = async (args) => {
|
|
17891
18215
|
const yargsInstance = yargs(args);
|
|
17892
18216
|
return yargsInstance.updateStrings({
|
|
17893
|
-
"Commands:":
|
|
17894
|
-
"Options:":
|
|
17895
|
-
"Examples:":
|
|
17896
|
-
"Show help":
|
|
18217
|
+
"Commands:": chalk11.yellow.underline.bold("Commands:"),
|
|
18218
|
+
"Options:": chalk11.yellow.underline.bold("Options:"),
|
|
18219
|
+
"Examples:": chalk11.yellow.underline.bold("Examples:"),
|
|
18220
|
+
"Show help": chalk11.bold("Show help")
|
|
17897
18221
|
}).usage(
|
|
17898
|
-
`${
|
|
18222
|
+
`${chalk11.bold(
|
|
17899
18223
|
"\n Bugsy - Trusted, Automatic Vulnerability Fixer \u{1F575}\uFE0F\u200D\u2642\uFE0F\n\n"
|
|
17900
|
-
)} ${
|
|
17901
|
-
$0 ${
|
|
18224
|
+
)} ${chalk11.yellow.underline.bold("Usage:")}
|
|
18225
|
+
$0 ${chalk11.green(
|
|
17902
18226
|
"<command>"
|
|
17903
|
-
)} ${
|
|
18227
|
+
)} ${chalk11.dim("[options]")}
|
|
17904
18228
|
`
|
|
17905
18229
|
).version(false).command(
|
|
17906
18230
|
mobbCliCommand.scan,
|
|
17907
|
-
|
|
18231
|
+
chalk11.bold(
|
|
17908
18232
|
"Scan your code for vulnerabilities, get automated fixes right away."
|
|
17909
18233
|
),
|
|
17910
18234
|
scanBuilder,
|
|
17911
18235
|
scanHandler
|
|
17912
18236
|
).command(
|
|
17913
18237
|
mobbCliCommand.analyze,
|
|
17914
|
-
|
|
18238
|
+
chalk11.bold(
|
|
17915
18239
|
"Provide a code repository, get automated fixes right away. You can also provide a vulnerability report to analyze or have Mobb scan the code for you."
|
|
17916
18240
|
),
|
|
17917
18241
|
analyzeBuilder,
|
|
17918
18242
|
analyzeHandler
|
|
17919
18243
|
).command(
|
|
17920
18244
|
mobbCliCommand.review,
|
|
17921
|
-
|
|
18245
|
+
chalk11.bold(
|
|
17922
18246
|
"Mobb will review your github pull requests and provide comments with fixes "
|
|
17923
18247
|
),
|
|
17924
18248
|
reviewBuilder,
|
|
17925
18249
|
reviewHandler
|
|
17926
18250
|
).command(
|
|
17927
18251
|
mobbCliCommand.addScmToken,
|
|
17928
|
-
|
|
18252
|
+
chalk11.bold(
|
|
17929
18253
|
"Add your SCM (Github, Gitlab, Azure DevOps) token to Mobb to enable automated fixes."
|
|
17930
18254
|
),
|
|
17931
18255
|
addScmTokenBuilder,
|
|
17932
18256
|
addScmTokenHandler
|
|
17933
18257
|
).command(
|
|
17934
18258
|
mobbCliCommand.convertToSarif,
|
|
17935
|
-
|
|
18259
|
+
chalk11.bold("Convert an existing SAST report to SARIF format."),
|
|
17936
18260
|
convertToSarifBuilder,
|
|
17937
18261
|
convertToSarifHandler
|
|
17938
18262
|
).command(
|
|
17939
18263
|
mobbCliCommand.mcp,
|
|
17940
|
-
|
|
18264
|
+
chalk11.bold("Launch the MCP (Model Context Protocol) server."),
|
|
17941
18265
|
mcpBuilder,
|
|
17942
18266
|
mcpHandler
|
|
18267
|
+
).command(
|
|
18268
|
+
mobbCliCommand.uploadAiBlame,
|
|
18269
|
+
chalk11.bold(
|
|
18270
|
+
"Upload AI Blame inference artifacts (prompt + inference) and finalize them."
|
|
18271
|
+
),
|
|
18272
|
+
uploadAiBlameBuilder,
|
|
18273
|
+
uploadAiBlameHandler
|
|
17943
18274
|
).example(
|
|
17944
18275
|
"npx mobbdev@latest scan -r https://github.com/WebGoat/WebGoat",
|
|
17945
18276
|
"Scan an existing repository"
|
|
@@ -17948,7 +18279,7 @@ var parseArgs = async (args) => {
|
|
|
17948
18279
|
handler() {
|
|
17949
18280
|
yargsInstance.showHelp();
|
|
17950
18281
|
}
|
|
17951
|
-
}).strictOptions().help("h").alias("h", "help").epilog(
|
|
18282
|
+
}).strictOptions().help("h").alias("h", "help").epilog(chalk11.bgBlue("Made with \u2764\uFE0F by Mobb")).showHelpOnFail(true).wrap(Math.min(120, yargsInstance.terminalWidth())).parse();
|
|
17952
18283
|
};
|
|
17953
18284
|
|
|
17954
18285
|
// src/index.ts
|