mobbdev 1.2.0 → 1.2.3
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/README.md +18 -0
- package/dist/args/commands/upload_ai_blame.d.mts +52 -32
- package/dist/args/commands/upload_ai_blame.mjs +69 -2
- package/dist/index.mjs +510 -248
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1371,7 +1371,7 @@ import Debug19 from "debug";
|
|
|
1371
1371
|
import { hideBin } from "yargs/helpers";
|
|
1372
1372
|
|
|
1373
1373
|
// src/args/yargs.ts
|
|
1374
|
-
import
|
|
1374
|
+
import chalk13 from "chalk";
|
|
1375
1375
|
import yargs from "yargs/yargs";
|
|
1376
1376
|
|
|
1377
1377
|
// src/args/commands/convert_to_sarif.ts
|
|
@@ -6572,7 +6572,7 @@ async function getAdoSdk(params) {
|
|
|
6572
6572
|
const url = new URL(repoUrl);
|
|
6573
6573
|
const origin2 = url.origin.toLowerCase().endsWith(".visualstudio.com") ? DEFUALT_ADO_ORIGIN : url.origin.toLowerCase();
|
|
6574
6574
|
const params2 = `path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=commit&versionDescriptor[version]=${branch}&resolveLfs=true&$format=zip&api-version=5.0&download=true`;
|
|
6575
|
-
const
|
|
6575
|
+
const path25 = [
|
|
6576
6576
|
prefixPath,
|
|
6577
6577
|
owner,
|
|
6578
6578
|
projectName,
|
|
@@ -6583,7 +6583,7 @@ async function getAdoSdk(params) {
|
|
|
6583
6583
|
"items",
|
|
6584
6584
|
"items"
|
|
6585
6585
|
].filter(Boolean).join("/");
|
|
6586
|
-
return new URL(`${
|
|
6586
|
+
return new URL(`${path25}?${params2}`, origin2).toString();
|
|
6587
6587
|
},
|
|
6588
6588
|
async getAdoBranchList({ repoUrl }) {
|
|
6589
6589
|
try {
|
|
@@ -8180,8 +8180,8 @@ function extractBlameRanges(data) {
|
|
|
8180
8180
|
}
|
|
8181
8181
|
function buildBlameFragment(ref) {
|
|
8182
8182
|
const escapedRef = safeGraphQLString(ref, "ref");
|
|
8183
|
-
return (
|
|
8184
|
-
const escapedPath = safeGraphQLString(
|
|
8183
|
+
return (path25, index) => {
|
|
8184
|
+
const escapedPath = safeGraphQLString(path25, "path");
|
|
8185
8185
|
return `
|
|
8186
8186
|
file${index}: object(expression: "${escapedRef}") {
|
|
8187
8187
|
... on Commit {
|
|
@@ -8229,8 +8229,8 @@ async function processBlameAttempt(params) {
|
|
|
8229
8229
|
)
|
|
8230
8230
|
);
|
|
8231
8231
|
for (const batchResult of batchResults) {
|
|
8232
|
-
for (const [
|
|
8233
|
-
result.set(
|
|
8232
|
+
for (const [path25, blameData] of batchResult) {
|
|
8233
|
+
result.set(path25, blameData);
|
|
8234
8234
|
}
|
|
8235
8235
|
}
|
|
8236
8236
|
return result;
|
|
@@ -8550,14 +8550,14 @@ function getGithubSdk(params = {}) {
|
|
|
8550
8550
|
};
|
|
8551
8551
|
},
|
|
8552
8552
|
async getGithubBlameRanges(params2) {
|
|
8553
|
-
const { ref, gitHubUrl, path:
|
|
8553
|
+
const { ref, gitHubUrl, path: path25 } = params2;
|
|
8554
8554
|
const { owner, repo } = parseGithubOwnerAndRepo(gitHubUrl);
|
|
8555
8555
|
const res = await octokit.graphql(
|
|
8556
8556
|
GET_BLAME_DOCUMENT,
|
|
8557
8557
|
{
|
|
8558
8558
|
owner,
|
|
8559
8559
|
repo,
|
|
8560
|
-
path:
|
|
8560
|
+
path: path25,
|
|
8561
8561
|
ref
|
|
8562
8562
|
}
|
|
8563
8563
|
);
|
|
@@ -9030,8 +9030,8 @@ function getGithubSdk(params = {}) {
|
|
|
9030
9030
|
return executeBatchGraphQL(octokit, params2.owner, params2.repo, {
|
|
9031
9031
|
items: params2.filePaths,
|
|
9032
9032
|
aliasPrefix: "file",
|
|
9033
|
-
buildFragment: (
|
|
9034
|
-
const escapedPath = safeGraphQLString(
|
|
9033
|
+
buildFragment: (path25, index) => {
|
|
9034
|
+
const escapedPath = safeGraphQLString(path25, "path");
|
|
9035
9035
|
return `
|
|
9036
9036
|
file${index}: object(expression: "${escapedRef}") {
|
|
9037
9037
|
... on Commit {
|
|
@@ -9346,11 +9346,11 @@ var GithubSCMLib = class _GithubSCMLib extends SCMLib {
|
|
|
9346
9346
|
markdownComment: comment
|
|
9347
9347
|
});
|
|
9348
9348
|
}
|
|
9349
|
-
async getRepoBlameRanges(ref,
|
|
9349
|
+
async getRepoBlameRanges(ref, path25) {
|
|
9350
9350
|
this._validateUrl();
|
|
9351
9351
|
return await this.githubSdk.getGithubBlameRanges({
|
|
9352
9352
|
ref,
|
|
9353
|
-
path:
|
|
9353
|
+
path: path25,
|
|
9354
9354
|
gitHubUrl: this.url
|
|
9355
9355
|
});
|
|
9356
9356
|
}
|
|
@@ -10282,13 +10282,13 @@ function parseGitlabOwnerAndRepo(gitlabUrl) {
|
|
|
10282
10282
|
const { organization, repoName, projectPath } = parsingResult;
|
|
10283
10283
|
return { owner: organization, repo: repoName, projectPath };
|
|
10284
10284
|
}
|
|
10285
|
-
async function getGitlabBlameRanges({ ref, gitlabUrl, path:
|
|
10285
|
+
async function getGitlabBlameRanges({ ref, gitlabUrl, path: path25 }, options) {
|
|
10286
10286
|
const { projectPath } = parseGitlabOwnerAndRepo(gitlabUrl);
|
|
10287
10287
|
const api2 = getGitBeaker({
|
|
10288
10288
|
url: gitlabUrl,
|
|
10289
10289
|
gitlabAuthToken: options?.gitlabAuthToken
|
|
10290
10290
|
});
|
|
10291
|
-
const resp = await api2.RepositoryFiles.allFileBlames(projectPath,
|
|
10291
|
+
const resp = await api2.RepositoryFiles.allFileBlames(projectPath, path25, ref);
|
|
10292
10292
|
let lineNumber = 1;
|
|
10293
10293
|
return resp.filter((range) => range.lines).map((range) => {
|
|
10294
10294
|
const oldLineNumber = lineNumber;
|
|
@@ -10462,10 +10462,10 @@ var GitlabSCMLib = class extends SCMLib {
|
|
|
10462
10462
|
markdownComment: comment
|
|
10463
10463
|
});
|
|
10464
10464
|
}
|
|
10465
|
-
async getRepoBlameRanges(ref,
|
|
10465
|
+
async getRepoBlameRanges(ref, path25) {
|
|
10466
10466
|
this._validateUrl();
|
|
10467
10467
|
return await getGitlabBlameRanges(
|
|
10468
|
-
{ ref, path:
|
|
10468
|
+
{ ref, path: path25, gitlabUrl: this.url },
|
|
10469
10469
|
{
|
|
10470
10470
|
url: this.url,
|
|
10471
10471
|
gitlabAuthToken: this.accessToken
|
|
@@ -11524,6 +11524,13 @@ var convertToSarifCodePathPatternsOption = {
|
|
|
11524
11524
|
type: "string",
|
|
11525
11525
|
array: true
|
|
11526
11526
|
};
|
|
11527
|
+
var pollingOption = {
|
|
11528
|
+
describe: chalk2.bold(
|
|
11529
|
+
"Use HTTP polling instead of WebSocket for status updates. Useful for proxy environments or firewalls that block WebSocket connections. Polling interval: 5 seconds, timeout: 30 minutes."
|
|
11530
|
+
),
|
|
11531
|
+
type: "boolean",
|
|
11532
|
+
default: false
|
|
11533
|
+
};
|
|
11527
11534
|
|
|
11528
11535
|
// src/args/commands/convert_to_sarif.ts
|
|
11529
11536
|
function convertToSarifBuilder(args) {
|
|
@@ -11555,7 +11562,8 @@ var mobbCliCommand = {
|
|
|
11555
11562
|
uploadAiBlame: "upload-ai-blame",
|
|
11556
11563
|
claudeCodeInstallHook: "claude-code-install-hook",
|
|
11557
11564
|
claudeCodeProcessHook: "claude-code-process-hook",
|
|
11558
|
-
|
|
11565
|
+
windsurfIntellijInstallHook: "windsurf-intellij-install-hook",
|
|
11566
|
+
windsurfIntellijProcessHook: "windsurf-intellij-process-hook"
|
|
11559
11567
|
};
|
|
11560
11568
|
var ScanContext = {
|
|
11561
11569
|
FULL_SCAN: "FULL_SCAN",
|
|
@@ -12235,6 +12243,61 @@ var GQLClient = class {
|
|
|
12235
12243
|
}
|
|
12236
12244
|
);
|
|
12237
12245
|
}
|
|
12246
|
+
async pollForAnalysisState(params) {
|
|
12247
|
+
const { analysisId, callbackStates, callback, timeoutInMs } = params;
|
|
12248
|
+
const startTime = Date.now();
|
|
12249
|
+
const maxDuration = timeoutInMs ?? 30 * 60 * 1e3;
|
|
12250
|
+
const pollingIntervalSec = REPORT_STATE_CHECK_DELAY / 1e3;
|
|
12251
|
+
debug6(
|
|
12252
|
+
`[pollForAnalysisState] Starting polling for analysis ${analysisId}, target states: ${callbackStates.join(", ")}, interval: ${pollingIntervalSec}s`
|
|
12253
|
+
);
|
|
12254
|
+
let isPolling = true;
|
|
12255
|
+
let pollCount = 0;
|
|
12256
|
+
while (isPolling) {
|
|
12257
|
+
pollCount++;
|
|
12258
|
+
const elapsedSec = Math.round((Date.now() - startTime) / 1e3);
|
|
12259
|
+
if (Date.now() - startTime > maxDuration) {
|
|
12260
|
+
debug6(
|
|
12261
|
+
`[pollForAnalysisState] Timeout expired after ${pollCount} polls (${elapsedSec}s)`
|
|
12262
|
+
);
|
|
12263
|
+
throw new ReportDigestError(
|
|
12264
|
+
`Polling timeout expired for analysis: ${analysisId} with timeout: ${maxDuration}ms`,
|
|
12265
|
+
`Analysis timed out after ${Math.round(maxDuration / 6e4)} minutes. Please try again or check the Mobb platform for status.`
|
|
12266
|
+
);
|
|
12267
|
+
}
|
|
12268
|
+
debug6(
|
|
12269
|
+
`[pollForAnalysisState] Poll #${pollCount} (elapsed: ${elapsedSec}s) - fetching analysis state...`
|
|
12270
|
+
);
|
|
12271
|
+
const analysis = await this.getAnalysis(analysisId);
|
|
12272
|
+
debug6(
|
|
12273
|
+
`[pollForAnalysisState] Poll #${pollCount} - current state: ${analysis.state}`
|
|
12274
|
+
);
|
|
12275
|
+
if (!analysis.state || analysis.state === "Failed" /* Failed */) {
|
|
12276
|
+
const errorMessage = analysis.failReason || `Analysis failed with id: ${analysis.id}`;
|
|
12277
|
+
debug6(`[pollForAnalysisState] Analysis failed: ${errorMessage}`);
|
|
12278
|
+
throw new ReportDigestError(errorMessage, analysis.failReason ?? "");
|
|
12279
|
+
}
|
|
12280
|
+
if (callbackStates.includes(analysis.state)) {
|
|
12281
|
+
debug6(
|
|
12282
|
+
`[pollForAnalysisState] Target state reached: ${analysis.state} after ${pollCount} polls (${elapsedSec}s)`
|
|
12283
|
+
);
|
|
12284
|
+
await callback(analysis.id);
|
|
12285
|
+
isPolling = false;
|
|
12286
|
+
return {
|
|
12287
|
+
analysis: {
|
|
12288
|
+
id: analysis.id,
|
|
12289
|
+
state: analysis.state,
|
|
12290
|
+
failReason: analysis.failReason
|
|
12291
|
+
}
|
|
12292
|
+
};
|
|
12293
|
+
}
|
|
12294
|
+
debug6(
|
|
12295
|
+
`[pollForAnalysisState] State ${analysis.state} not in target states, waiting ${pollingIntervalSec}s before next poll...`
|
|
12296
|
+
);
|
|
12297
|
+
await sleep(REPORT_STATE_CHECK_DELAY);
|
|
12298
|
+
}
|
|
12299
|
+
throw new Error(`Unexpected end of polling for analysis: ${analysisId}`);
|
|
12300
|
+
}
|
|
12238
12301
|
async getFixReportsByRepoUrl({ repoUrl }) {
|
|
12239
12302
|
const res = await this._clientSdk.GetFixReportsByRepoUrl({
|
|
12240
12303
|
repoUrl
|
|
@@ -12635,7 +12698,8 @@ var debug8 = Debug7("mobbdev:index");
|
|
|
12635
12698
|
async function sendReport({
|
|
12636
12699
|
spinner,
|
|
12637
12700
|
submitVulnerabilityReportVariables,
|
|
12638
|
-
gqlClient
|
|
12701
|
+
gqlClient,
|
|
12702
|
+
polling
|
|
12639
12703
|
}) {
|
|
12640
12704
|
try {
|
|
12641
12705
|
const submitRes = await gqlClient.submitVulnerabilityReport(
|
|
@@ -12646,19 +12710,32 @@ async function sendReport({
|
|
|
12646
12710
|
throw new Error("\u{1F575}\uFE0F\u200D\u2642\uFE0F Mobb analysis failed");
|
|
12647
12711
|
}
|
|
12648
12712
|
spinner.update({ text: progressMassages.processingVulnerabilityReport });
|
|
12649
|
-
|
|
12650
|
-
|
|
12651
|
-
analysisId: submitRes.submitVulnerabilityReport.fixReportId
|
|
12652
|
-
},
|
|
12653
|
-
callback: () => spinner.update({
|
|
12654
|
-
text: "\u2699\uFE0F Vulnerability report processed successfully"
|
|
12655
|
-
}),
|
|
12656
|
-
callbackStates: [
|
|
12657
|
-
"Digested" /* Digested */,
|
|
12658
|
-
"Finished" /* Finished */
|
|
12659
|
-
],
|
|
12660
|
-
timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
|
|
12713
|
+
const callback = (_analysisId) => spinner.update({
|
|
12714
|
+
text: "\u2699\uFE0F Vulnerability report processed successfully"
|
|
12661
12715
|
});
|
|
12716
|
+
const callbackStates = [
|
|
12717
|
+
"Digested" /* Digested */,
|
|
12718
|
+
"Finished" /* Finished */
|
|
12719
|
+
];
|
|
12720
|
+
if (polling) {
|
|
12721
|
+
debug8("[sendReport] Using POLLING mode for analysis state updates");
|
|
12722
|
+
await gqlClient.pollForAnalysisState({
|
|
12723
|
+
analysisId: submitRes.submitVulnerabilityReport.fixReportId,
|
|
12724
|
+
callback,
|
|
12725
|
+
callbackStates,
|
|
12726
|
+
timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
|
|
12727
|
+
});
|
|
12728
|
+
} else {
|
|
12729
|
+
debug8("[sendReport] Using WEBSOCKET mode for analysis state updates");
|
|
12730
|
+
await gqlClient.subscribeToAnalysis({
|
|
12731
|
+
subscribeToAnalysisParams: {
|
|
12732
|
+
analysisId: submitRes.submitVulnerabilityReport.fixReportId
|
|
12733
|
+
},
|
|
12734
|
+
callback,
|
|
12735
|
+
callbackStates,
|
|
12736
|
+
timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
|
|
12737
|
+
});
|
|
12738
|
+
}
|
|
12662
12739
|
return submitRes;
|
|
12663
12740
|
} catch (e) {
|
|
12664
12741
|
spinner.error({ text: "\u{1F575}\uFE0F\u200D\u2642\uFE0F Mobb analysis failed" });
|
|
@@ -12885,7 +12962,7 @@ async function postIssueComment(params) {
|
|
|
12885
12962
|
fpDescription
|
|
12886
12963
|
} = params;
|
|
12887
12964
|
const {
|
|
12888
|
-
path:
|
|
12965
|
+
path: path25,
|
|
12889
12966
|
startLine,
|
|
12890
12967
|
vulnerabilityReportIssue: {
|
|
12891
12968
|
vulnerabilityReportIssueTags,
|
|
@@ -12900,7 +12977,7 @@ async function postIssueComment(params) {
|
|
|
12900
12977
|
Refresh the page in order to see the changes.`,
|
|
12901
12978
|
pull_number: pullRequest,
|
|
12902
12979
|
commit_id: commitSha,
|
|
12903
|
-
path:
|
|
12980
|
+
path: path25,
|
|
12904
12981
|
line: startLine
|
|
12905
12982
|
});
|
|
12906
12983
|
const commentId = commentRes.data.id;
|
|
@@ -12934,7 +13011,7 @@ async function postFixComment(params) {
|
|
|
12934
13011
|
scanner
|
|
12935
13012
|
} = params;
|
|
12936
13013
|
const {
|
|
12937
|
-
path:
|
|
13014
|
+
path: path25,
|
|
12938
13015
|
startLine,
|
|
12939
13016
|
vulnerabilityReportIssue: { fixId, vulnerabilityReportIssueTags, category },
|
|
12940
13017
|
vulnerabilityReportIssueId
|
|
@@ -12952,7 +13029,7 @@ async function postFixComment(params) {
|
|
|
12952
13029
|
Refresh the page in order to see the changes.`,
|
|
12953
13030
|
pull_number: pullRequest,
|
|
12954
13031
|
commit_id: commitSha,
|
|
12955
|
-
path:
|
|
13032
|
+
path: path25,
|
|
12956
13033
|
line: startLine
|
|
12957
13034
|
});
|
|
12958
13035
|
const commentId = commentRes.data.id;
|
|
@@ -13196,44 +13273,57 @@ async function handleAutoPr(params) {
|
|
|
13196
13273
|
commitDirectly,
|
|
13197
13274
|
prId,
|
|
13198
13275
|
createSpinner: createSpinner5,
|
|
13199
|
-
createOnePr
|
|
13276
|
+
createOnePr,
|
|
13277
|
+
polling
|
|
13200
13278
|
} = params;
|
|
13201
13279
|
const createAutoPrSpinner = createSpinner5(
|
|
13202
13280
|
"\u{1F504} Waiting for the analysis to finish before initiating automatic pull request creation"
|
|
13203
13281
|
).start();
|
|
13204
|
-
|
|
13205
|
-
|
|
13206
|
-
analysisId
|
|
13207
|
-
|
|
13208
|
-
|
|
13209
|
-
|
|
13210
|
-
|
|
13211
|
-
|
|
13212
|
-
|
|
13213
|
-
|
|
13282
|
+
const callback = async (analysisId2) => {
|
|
13283
|
+
const autoPrAnalysisRes = await gqlClient.autoPrAnalysis({
|
|
13284
|
+
analysisId: analysisId2,
|
|
13285
|
+
commitDirectly,
|
|
13286
|
+
prId,
|
|
13287
|
+
prStrategy: createOnePr ? "CONDENSE" /* Condense */ : "SPREAD" /* Spread */
|
|
13288
|
+
});
|
|
13289
|
+
debug12("auto pr analysis res %o", autoPrAnalysisRes);
|
|
13290
|
+
if (autoPrAnalysisRes.autoPrAnalysis?.__typename === "AutoPrError") {
|
|
13291
|
+
createAutoPrSpinner.error({
|
|
13292
|
+
text: `\u{1F504} Automatic pull request failed - ${autoPrAnalysisRes.autoPrAnalysis.error}`
|
|
13214
13293
|
});
|
|
13215
|
-
|
|
13216
|
-
|
|
13217
|
-
|
|
13218
|
-
|
|
13219
|
-
|
|
13220
|
-
return;
|
|
13221
|
-
}
|
|
13222
|
-
if (autoPrAnalysisRes.autoPrAnalysis?.__typename === "AutoPrSuccess") {
|
|
13223
|
-
const { appliedAutoPrIssueTypes } = autoPrAnalysisRes.autoPrAnalysis;
|
|
13224
|
-
if (appliedAutoPrIssueTypes.length === 0) {
|
|
13225
|
-
createAutoPrSpinner.success({
|
|
13226
|
-
text: "\u{1F504} Automatic pull request did not find any new fixes to open a pull request for"
|
|
13227
|
-
});
|
|
13228
|
-
return;
|
|
13229
|
-
}
|
|
13294
|
+
return;
|
|
13295
|
+
}
|
|
13296
|
+
if (autoPrAnalysisRes.autoPrAnalysis?.__typename === "AutoPrSuccess") {
|
|
13297
|
+
const { appliedAutoPrIssueTypes } = autoPrAnalysisRes.autoPrAnalysis;
|
|
13298
|
+
if (appliedAutoPrIssueTypes.length === 0) {
|
|
13230
13299
|
createAutoPrSpinner.success({
|
|
13231
|
-
text:
|
|
13300
|
+
text: "\u{1F504} Automatic pull request did not find any new fixes to open a pull request for"
|
|
13232
13301
|
});
|
|
13302
|
+
return;
|
|
13233
13303
|
}
|
|
13234
|
-
|
|
13235
|
-
|
|
13236
|
-
|
|
13304
|
+
createAutoPrSpinner.success({
|
|
13305
|
+
text: `\u{1F504} Automatic pull request creation initiated successfully for the following issue types: ${appliedAutoPrIssueTypes}`
|
|
13306
|
+
});
|
|
13307
|
+
}
|
|
13308
|
+
};
|
|
13309
|
+
const callbackStates = ["Finished" /* Finished */];
|
|
13310
|
+
if (polling) {
|
|
13311
|
+
debug12("[handleAutoPr] Using POLLING mode for analysis state updates");
|
|
13312
|
+
return await gqlClient.pollForAnalysisState({
|
|
13313
|
+
analysisId,
|
|
13314
|
+
callback,
|
|
13315
|
+
callbackStates
|
|
13316
|
+
});
|
|
13317
|
+
} else {
|
|
13318
|
+
debug12("[handleAutoPr] Using WEBSOCKET mode for analysis state updates");
|
|
13319
|
+
return await gqlClient.subscribeToAnalysis({
|
|
13320
|
+
subscribeToAnalysisParams: {
|
|
13321
|
+
analysisId
|
|
13322
|
+
},
|
|
13323
|
+
callback,
|
|
13324
|
+
callbackStates
|
|
13325
|
+
});
|
|
13326
|
+
}
|
|
13237
13327
|
}
|
|
13238
13328
|
|
|
13239
13329
|
// src/features/analysis/git.ts
|
|
@@ -13542,8 +13632,8 @@ if (typeof __filename !== "undefined") {
|
|
|
13542
13632
|
}
|
|
13543
13633
|
var costumeRequire = createRequire(moduleUrl);
|
|
13544
13634
|
var getCheckmarxPath = () => {
|
|
13545
|
-
const
|
|
13546
|
-
const cxFileName =
|
|
13635
|
+
const os14 = type();
|
|
13636
|
+
const cxFileName = os14 === "Windows_NT" ? "cx.exe" : "cx";
|
|
13547
13637
|
try {
|
|
13548
13638
|
return costumeRequire.resolve(`.bin/${cxFileName}`);
|
|
13549
13639
|
} catch (e) {
|
|
@@ -13986,7 +14076,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
13986
14076
|
autoPr,
|
|
13987
14077
|
createOnePr,
|
|
13988
14078
|
commitDirectly,
|
|
13989
|
-
pullRequest
|
|
14079
|
+
pullRequest,
|
|
14080
|
+
polling
|
|
13990
14081
|
} = params;
|
|
13991
14082
|
debug18("start %s %s", dirname, repo);
|
|
13992
14083
|
const { createSpinner: createSpinner5 } = Spinner2({ ci });
|
|
@@ -14098,7 +14189,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
14098
14189
|
repoUrl: repo,
|
|
14099
14190
|
sha,
|
|
14100
14191
|
reference,
|
|
14101
|
-
shouldScan
|
|
14192
|
+
shouldScan,
|
|
14193
|
+
polling
|
|
14102
14194
|
});
|
|
14103
14195
|
uploadReportSpinner.success({ text: "\u{1F4C1} Report uploaded successfully" });
|
|
14104
14196
|
const mobbSpinner = createSpinner5("\u{1F575}\uFE0F\u200D\u2642\uFE0F Initiating Mobb analysis").start();
|
|
@@ -14116,7 +14208,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
14116
14208
|
pullRequest: params.pullRequest,
|
|
14117
14209
|
scanSource: _getScanSource(command, ci),
|
|
14118
14210
|
scanContext: ScanContext.BUGSY
|
|
14119
|
-
}
|
|
14211
|
+
},
|
|
14212
|
+
polling
|
|
14120
14213
|
});
|
|
14121
14214
|
if (sendReportRes.submitVulnerabilityReport.__typename !== "VulnerabilityReport") {
|
|
14122
14215
|
mobbSpinner.error({ text: "\u{1F575}\uFE0F\u200D\u2642\uFE0F Mobb analysis failed" });
|
|
@@ -14132,7 +14225,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
14132
14225
|
commitDirectly,
|
|
14133
14226
|
prId: pullRequest,
|
|
14134
14227
|
createSpinner: createSpinner5,
|
|
14135
|
-
createOnePr
|
|
14228
|
+
createOnePr,
|
|
14229
|
+
polling
|
|
14136
14230
|
});
|
|
14137
14231
|
}
|
|
14138
14232
|
await askToOpenAnalysis();
|
|
@@ -14142,7 +14236,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
14142
14236
|
githubActionToken,
|
|
14143
14237
|
analysisId: reportUploadInfo.fixReportId,
|
|
14144
14238
|
scanner,
|
|
14145
|
-
gqlClient
|
|
14239
|
+
gqlClient,
|
|
14240
|
+
polling
|
|
14146
14241
|
});
|
|
14147
14242
|
}
|
|
14148
14243
|
return reportUploadInfo.fixReportId;
|
|
@@ -14237,7 +14332,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
14237
14332
|
projectId,
|
|
14238
14333
|
command,
|
|
14239
14334
|
ci,
|
|
14240
|
-
shouldScan: shouldScan2
|
|
14335
|
+
shouldScan: shouldScan2,
|
|
14336
|
+
polling
|
|
14241
14337
|
});
|
|
14242
14338
|
const res = await _zipAndUploadRepo({
|
|
14243
14339
|
srcPath,
|
|
@@ -14260,7 +14356,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
14260
14356
|
projectId,
|
|
14261
14357
|
command,
|
|
14262
14358
|
ci,
|
|
14263
|
-
shouldScan: shouldScan2
|
|
14359
|
+
shouldScan: shouldScan2,
|
|
14360
|
+
polling
|
|
14264
14361
|
});
|
|
14265
14362
|
}
|
|
14266
14363
|
const mobbSpinner2 = createSpinner5("\u{1F575}\uFE0F\u200D\u2642\uFE0F Initiating Mobb analysis").start();
|
|
@@ -14278,7 +14375,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
14278
14375
|
pullRequest: params.pullRequest,
|
|
14279
14376
|
experimentalEnabled: !!experimentalEnabled,
|
|
14280
14377
|
scanContext: ScanContext.BUGSY
|
|
14281
|
-
}
|
|
14378
|
+
},
|
|
14379
|
+
polling
|
|
14282
14380
|
});
|
|
14283
14381
|
if (command === "review") {
|
|
14284
14382
|
await waitForAnaysisAndReviewPr({
|
|
@@ -14286,7 +14384,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
14286
14384
|
githubActionToken,
|
|
14287
14385
|
analysisId: reportUploadInfo.fixReportId,
|
|
14288
14386
|
scanner,
|
|
14289
|
-
gqlClient
|
|
14387
|
+
gqlClient,
|
|
14388
|
+
polling
|
|
14290
14389
|
});
|
|
14291
14390
|
}
|
|
14292
14391
|
} catch (e) {
|
|
@@ -14303,7 +14402,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
14303
14402
|
commitDirectly,
|
|
14304
14403
|
prId: pullRequest,
|
|
14305
14404
|
createSpinner: createSpinner5,
|
|
14306
|
-
createOnePr
|
|
14405
|
+
createOnePr,
|
|
14406
|
+
polling
|
|
14307
14407
|
});
|
|
14308
14408
|
}
|
|
14309
14409
|
await askToOpenAnalysis();
|
|
@@ -14351,7 +14451,8 @@ async function _digestReport({
|
|
|
14351
14451
|
repoUrl,
|
|
14352
14452
|
sha,
|
|
14353
14453
|
reference,
|
|
14354
|
-
shouldScan
|
|
14454
|
+
shouldScan,
|
|
14455
|
+
polling
|
|
14355
14456
|
}) {
|
|
14356
14457
|
const digestSpinner = createSpinner4(
|
|
14357
14458
|
progressMassages.processingVulnerabilityReport
|
|
@@ -14368,19 +14469,46 @@ async function _digestReport({
|
|
|
14368
14469
|
shouldScan
|
|
14369
14470
|
}
|
|
14370
14471
|
);
|
|
14371
|
-
|
|
14372
|
-
|
|
14373
|
-
|
|
14374
|
-
|
|
14375
|
-
|
|
14376
|
-
|
|
14377
|
-
}),
|
|
14378
|
-
callbackStates: [
|
|
14379
|
-
"Digested" /* Digested */,
|
|
14380
|
-
"Finished" /* Finished */
|
|
14381
|
-
],
|
|
14382
|
-
timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
|
|
14472
|
+
const callbackStates = [
|
|
14473
|
+
"Digested" /* Digested */,
|
|
14474
|
+
"Finished" /* Finished */
|
|
14475
|
+
];
|
|
14476
|
+
const callback = (_analysisId) => digestSpinner.update({
|
|
14477
|
+
text: progressMassages.processingVulnerabilityReportSuccess
|
|
14383
14478
|
});
|
|
14479
|
+
if (polling) {
|
|
14480
|
+
debug18(
|
|
14481
|
+
"[_digestReport] Using POLLING mode for analysis state updates (--polling flag enabled)"
|
|
14482
|
+
);
|
|
14483
|
+
console.log(
|
|
14484
|
+
chalk6.cyan(
|
|
14485
|
+
"\u{1F504} [Polling Mode] Using HTTP polling instead of WebSocket for status updates"
|
|
14486
|
+
)
|
|
14487
|
+
);
|
|
14488
|
+
await gqlClient.pollForAnalysisState({
|
|
14489
|
+
analysisId: fixReportId,
|
|
14490
|
+
callback,
|
|
14491
|
+
callbackStates,
|
|
14492
|
+
timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
|
|
14493
|
+
});
|
|
14494
|
+
} else {
|
|
14495
|
+
debug18(
|
|
14496
|
+
"[_digestReport] Using WEBSOCKET mode for analysis state updates (default)"
|
|
14497
|
+
);
|
|
14498
|
+
console.log(
|
|
14499
|
+
chalk6.cyan(
|
|
14500
|
+
"\u{1F50C} [WebSocket Mode] Using WebSocket subscription for status updates"
|
|
14501
|
+
)
|
|
14502
|
+
);
|
|
14503
|
+
await gqlClient.subscribeToAnalysis({
|
|
14504
|
+
subscribeToAnalysisParams: {
|
|
14505
|
+
analysisId: fixReportId
|
|
14506
|
+
},
|
|
14507
|
+
callback,
|
|
14508
|
+
callbackStates,
|
|
14509
|
+
timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
|
|
14510
|
+
});
|
|
14511
|
+
}
|
|
14384
14512
|
const vulnFiles = await gqlClient.getVulnerabilityReportPaths(
|
|
14385
14513
|
vulnerabilityReportId
|
|
14386
14514
|
);
|
|
@@ -14401,7 +14529,8 @@ async function waitForAnaysisAndReviewPr({
|
|
|
14401
14529
|
githubActionToken,
|
|
14402
14530
|
analysisId,
|
|
14403
14531
|
scanner,
|
|
14404
|
-
gqlClient
|
|
14532
|
+
gqlClient,
|
|
14533
|
+
polling
|
|
14405
14534
|
}) {
|
|
14406
14535
|
const params = z29.object({
|
|
14407
14536
|
repo: z29.string().url(),
|
|
@@ -14418,20 +14547,45 @@ async function waitForAnaysisAndReviewPr({
|
|
|
14418
14547
|
propagateExceptions: true
|
|
14419
14548
|
}
|
|
14420
14549
|
);
|
|
14421
|
-
|
|
14422
|
-
|
|
14423
|
-
analysisId
|
|
14424
|
-
|
|
14425
|
-
|
|
14426
|
-
|
|
14427
|
-
|
|
14428
|
-
|
|
14429
|
-
|
|
14430
|
-
|
|
14431
|
-
|
|
14432
|
-
|
|
14433
|
-
|
|
14434
|
-
|
|
14550
|
+
const callback = (analysisId2) => {
|
|
14551
|
+
return addFixCommentsForPr({
|
|
14552
|
+
analysisId: analysisId2,
|
|
14553
|
+
gqlClient,
|
|
14554
|
+
scm,
|
|
14555
|
+
scanner: z29.nativeEnum(SCANNERS).parse(scanner)
|
|
14556
|
+
});
|
|
14557
|
+
};
|
|
14558
|
+
if (polling) {
|
|
14559
|
+
debug18(
|
|
14560
|
+
"[waitForAnaysisAndReviewPr] Using POLLING mode for analysis state updates"
|
|
14561
|
+
);
|
|
14562
|
+
console.log(
|
|
14563
|
+
chalk6.cyan(
|
|
14564
|
+
"\u{1F504} [Polling Mode] Waiting for analysis completion using HTTP polling"
|
|
14565
|
+
)
|
|
14566
|
+
);
|
|
14567
|
+
await gqlClient.pollForAnalysisState({
|
|
14568
|
+
analysisId,
|
|
14569
|
+
callback,
|
|
14570
|
+
callbackStates: ["Finished" /* Finished */]
|
|
14571
|
+
});
|
|
14572
|
+
} else {
|
|
14573
|
+
debug18(
|
|
14574
|
+
"[waitForAnaysisAndReviewPr] Using WEBSOCKET mode for analysis state updates"
|
|
14575
|
+
);
|
|
14576
|
+
console.log(
|
|
14577
|
+
chalk6.cyan(
|
|
14578
|
+
"\u{1F50C} [WebSocket Mode] Waiting for analysis completion using WebSocket"
|
|
14579
|
+
)
|
|
14580
|
+
);
|
|
14581
|
+
await gqlClient.subscribeToAnalysis({
|
|
14582
|
+
subscribeToAnalysisParams: {
|
|
14583
|
+
analysisId
|
|
14584
|
+
},
|
|
14585
|
+
callback,
|
|
14586
|
+
callbackStates: ["Finished" /* Finished */]
|
|
14587
|
+
});
|
|
14588
|
+
}
|
|
14435
14589
|
}
|
|
14436
14590
|
|
|
14437
14591
|
// src/commands/index.ts
|
|
@@ -14446,7 +14600,8 @@ async function review(params, { skipPrompts = true } = {}) {
|
|
|
14446
14600
|
pullRequest,
|
|
14447
14601
|
githubToken,
|
|
14448
14602
|
scanner,
|
|
14449
|
-
srcPath
|
|
14603
|
+
srcPath,
|
|
14604
|
+
polling
|
|
14450
14605
|
} = params;
|
|
14451
14606
|
await runAnalysis(
|
|
14452
14607
|
{
|
|
@@ -14462,7 +14617,8 @@ async function review(params, { skipPrompts = true } = {}) {
|
|
|
14462
14617
|
githubToken,
|
|
14463
14618
|
scanner,
|
|
14464
14619
|
command: "review",
|
|
14465
|
-
srcPath
|
|
14620
|
+
srcPath,
|
|
14621
|
+
polling
|
|
14466
14622
|
},
|
|
14467
14623
|
{ skipPrompts }
|
|
14468
14624
|
);
|
|
@@ -14480,7 +14636,8 @@ async function analyze({
|
|
|
14480
14636
|
autoPr,
|
|
14481
14637
|
createOnePr,
|
|
14482
14638
|
commitDirectly,
|
|
14483
|
-
pullRequest
|
|
14639
|
+
pullRequest,
|
|
14640
|
+
polling
|
|
14484
14641
|
}, { skipPrompts = false } = {}) {
|
|
14485
14642
|
!ci && await showWelcomeMessage(skipPrompts);
|
|
14486
14643
|
await runAnalysis(
|
|
@@ -14498,7 +14655,8 @@ async function analyze({
|
|
|
14498
14655
|
autoPr,
|
|
14499
14656
|
commitDirectly,
|
|
14500
14657
|
pullRequest,
|
|
14501
|
-
createOnePr
|
|
14658
|
+
createOnePr,
|
|
14659
|
+
polling
|
|
14502
14660
|
},
|
|
14503
14661
|
{ skipPrompts }
|
|
14504
14662
|
);
|
|
@@ -14638,7 +14796,7 @@ function analyzeBuilder(yargs2) {
|
|
|
14638
14796
|
describe: chalk8.bold("Number of the pull request"),
|
|
14639
14797
|
type: "number",
|
|
14640
14798
|
demandOption: false
|
|
14641
|
-
}).example(
|
|
14799
|
+
}).option("polling", pollingOption).example(
|
|
14642
14800
|
"npx mobbdev@latest analyze -r https://github.com/WebGoat/WebGoat -f <your_vulnerability_report_path>",
|
|
14643
14801
|
"analyze an existing repository"
|
|
14644
14802
|
).help();
|
|
@@ -14947,7 +15105,14 @@ var defaultLogger2 = {
|
|
|
14947
15105
|
}
|
|
14948
15106
|
};
|
|
14949
15107
|
var PromptItemZ = z31.object({
|
|
14950
|
-
type: z31.enum([
|
|
15108
|
+
type: z31.enum([
|
|
15109
|
+
"USER_PROMPT",
|
|
15110
|
+
"AI_RESPONSE",
|
|
15111
|
+
"TOOL_EXECUTION",
|
|
15112
|
+
"AI_THINKING",
|
|
15113
|
+
"MCP_TOOL_CALL"
|
|
15114
|
+
// MCP (Model Context Protocol) tool invocation
|
|
15115
|
+
]),
|
|
14951
15116
|
attachedFiles: z31.array(
|
|
14952
15117
|
z31.object({
|
|
14953
15118
|
relativePath: z31.string(),
|
|
@@ -14965,7 +15130,12 @@ var PromptItemZ = z31.object({
|
|
|
14965
15130
|
parameters: z31.string(),
|
|
14966
15131
|
result: z31.string(),
|
|
14967
15132
|
rawArguments: z31.string().optional(),
|
|
14968
|
-
accepted: z31.boolean().optional()
|
|
15133
|
+
accepted: z31.boolean().optional(),
|
|
15134
|
+
// MCP-specific fields (only populated for MCP_TOOL_CALL type)
|
|
15135
|
+
mcpServer: z31.string().optional(),
|
|
15136
|
+
// MCP server name (e.g., "datadog", "mobb-mcp")
|
|
15137
|
+
mcpToolName: z31.string().optional()
|
|
15138
|
+
// MCP tool name without prefix (e.g., "scan_and_fix_vulnerabilities")
|
|
14969
15139
|
}).optional()
|
|
14970
15140
|
});
|
|
14971
15141
|
var PromptItemArrayZ = z31.array(PromptItemZ);
|
|
@@ -15698,8 +15868,8 @@ var WorkspaceService = class {
|
|
|
15698
15868
|
* Sets a known workspace path that was discovered through successful validation
|
|
15699
15869
|
* @param path The validated workspace path to store
|
|
15700
15870
|
*/
|
|
15701
|
-
static setKnownWorkspacePath(
|
|
15702
|
-
this.knownWorkspacePath =
|
|
15871
|
+
static setKnownWorkspacePath(path25) {
|
|
15872
|
+
this.knownWorkspacePath = path25;
|
|
15703
15873
|
}
|
|
15704
15874
|
/**
|
|
15705
15875
|
* Gets the known workspace path that was previously validated
|
|
@@ -16972,10 +17142,10 @@ var getHostInfo = (additionalMcpList) => {
|
|
|
16972
17142
|
const ideConfigPaths = /* @__PURE__ */ new Set();
|
|
16973
17143
|
for (const ide of IDEs) {
|
|
16974
17144
|
const configPaths = getMCPConfigPaths(ide);
|
|
16975
|
-
configPaths.forEach((
|
|
17145
|
+
configPaths.forEach((path25) => ideConfigPaths.add(path25));
|
|
16976
17146
|
}
|
|
16977
17147
|
const uniqueAdditionalPaths = additionalMcpList.filter(
|
|
16978
|
-
(
|
|
17148
|
+
(path25) => !ideConfigPaths.has(path25)
|
|
16979
17149
|
);
|
|
16980
17150
|
for (const ide of IDEs) {
|
|
16981
17151
|
const cfg = readMCPConfig(ide);
|
|
@@ -20268,7 +20438,7 @@ init_configs();
|
|
|
20268
20438
|
import fs19 from "fs/promises";
|
|
20269
20439
|
import nodePath from "path";
|
|
20270
20440
|
var getLocalFiles = async ({
|
|
20271
|
-
path:
|
|
20441
|
+
path: path25,
|
|
20272
20442
|
maxFileSize = MCP_MAX_FILE_SIZE,
|
|
20273
20443
|
maxFiles,
|
|
20274
20444
|
isAllFilesScan,
|
|
@@ -20276,17 +20446,17 @@ var getLocalFiles = async ({
|
|
|
20276
20446
|
scanRecentlyChangedFiles
|
|
20277
20447
|
}) => {
|
|
20278
20448
|
logDebug(`[${scanContext}] Starting getLocalFiles`, {
|
|
20279
|
-
path:
|
|
20449
|
+
path: path25,
|
|
20280
20450
|
maxFileSize,
|
|
20281
20451
|
maxFiles,
|
|
20282
20452
|
isAllFilesScan,
|
|
20283
20453
|
scanRecentlyChangedFiles
|
|
20284
20454
|
});
|
|
20285
20455
|
try {
|
|
20286
|
-
const resolvedRepoPath = await fs19.realpath(
|
|
20456
|
+
const resolvedRepoPath = await fs19.realpath(path25);
|
|
20287
20457
|
logDebug(`[${scanContext}] Resolved repository path`, {
|
|
20288
20458
|
resolvedRepoPath,
|
|
20289
|
-
originalPath:
|
|
20459
|
+
originalPath: path25
|
|
20290
20460
|
});
|
|
20291
20461
|
const gitService = new GitService(resolvedRepoPath, log);
|
|
20292
20462
|
const gitValidation = await gitService.validateRepository();
|
|
@@ -20299,7 +20469,7 @@ var getLocalFiles = async ({
|
|
|
20299
20469
|
if (!gitValidation.isValid || isAllFilesScan) {
|
|
20300
20470
|
try {
|
|
20301
20471
|
files = await FileUtils.getLastChangedFiles({
|
|
20302
|
-
dir:
|
|
20472
|
+
dir: path25,
|
|
20303
20473
|
maxFileSize,
|
|
20304
20474
|
maxFiles,
|
|
20305
20475
|
isAllFilesScan
|
|
@@ -20391,7 +20561,7 @@ var getLocalFiles = async ({
|
|
|
20391
20561
|
logError(`${scanContext}Unexpected error in getLocalFiles`, {
|
|
20392
20562
|
error: error instanceof Error ? error.message : String(error),
|
|
20393
20563
|
stack: error instanceof Error ? error.stack : void 0,
|
|
20394
|
-
path:
|
|
20564
|
+
path: path25
|
|
20395
20565
|
});
|
|
20396
20566
|
throw error;
|
|
20397
20567
|
}
|
|
@@ -22539,14 +22709,14 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
22539
22709
|
* since the last scan.
|
|
22540
22710
|
*/
|
|
22541
22711
|
async scanForSecurityVulnerabilities({
|
|
22542
|
-
path:
|
|
22712
|
+
path: path25,
|
|
22543
22713
|
isAllDetectionRulesScan,
|
|
22544
22714
|
isAllFilesScan,
|
|
22545
22715
|
scanContext
|
|
22546
22716
|
}) {
|
|
22547
22717
|
this.hasAuthenticationFailed = false;
|
|
22548
22718
|
logDebug(`[${scanContext}] Scanning for new security vulnerabilities`, {
|
|
22549
|
-
path:
|
|
22719
|
+
path: path25
|
|
22550
22720
|
});
|
|
22551
22721
|
if (!this.gqlClient) {
|
|
22552
22722
|
logInfo(`[${scanContext}] No GQL client found, skipping scan`);
|
|
@@ -22562,11 +22732,11 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
22562
22732
|
}
|
|
22563
22733
|
logDebug(
|
|
22564
22734
|
`[${scanContext}] Connected to the API, assembling list of files to scan`,
|
|
22565
|
-
{ path:
|
|
22735
|
+
{ path: path25 }
|
|
22566
22736
|
);
|
|
22567
22737
|
const isBackgroundScan = scanContext === ScanContext.BACKGROUND_INITIAL || scanContext === ScanContext.BACKGROUND_PERIODIC;
|
|
22568
22738
|
const files = await getLocalFiles({
|
|
22569
|
-
path:
|
|
22739
|
+
path: path25,
|
|
22570
22740
|
isAllFilesScan,
|
|
22571
22741
|
scanContext,
|
|
22572
22742
|
scanRecentlyChangedFiles: !isBackgroundScan
|
|
@@ -22592,13 +22762,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
22592
22762
|
});
|
|
22593
22763
|
const { fixReportId, projectId } = await scanFiles({
|
|
22594
22764
|
fileList: filesToScan.map((file) => file.relativePath),
|
|
22595
|
-
repositoryPath:
|
|
22765
|
+
repositoryPath: path25,
|
|
22596
22766
|
gqlClient: this.gqlClient,
|
|
22597
22767
|
isAllDetectionRulesScan,
|
|
22598
22768
|
scanContext
|
|
22599
22769
|
});
|
|
22600
22770
|
logInfo(
|
|
22601
|
-
`[${scanContext}] Security scan completed for ${
|
|
22771
|
+
`[${scanContext}] Security scan completed for ${path25} reportId: ${fixReportId} projectId: ${projectId}`
|
|
22602
22772
|
);
|
|
22603
22773
|
if (isAllFilesScan) {
|
|
22604
22774
|
return;
|
|
@@ -22892,13 +23062,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
22892
23062
|
});
|
|
22893
23063
|
return scannedFiles.some((file) => file.relativePath === fixFile);
|
|
22894
23064
|
}
|
|
22895
|
-
async getFreshFixes({ path:
|
|
23065
|
+
async getFreshFixes({ path: path25 }) {
|
|
22896
23066
|
const scanContext = ScanContext.USER_REQUEST;
|
|
22897
|
-
logDebug(`[${scanContext}] Getting fresh fixes`, { path:
|
|
22898
|
-
if (this.path !==
|
|
22899
|
-
this.path =
|
|
23067
|
+
logDebug(`[${scanContext}] Getting fresh fixes`, { path: path25 });
|
|
23068
|
+
if (this.path !== path25) {
|
|
23069
|
+
this.path = path25;
|
|
22900
23070
|
this.reset();
|
|
22901
|
-
logInfo(`[${scanContext}] Reset service state for new path`, { path:
|
|
23071
|
+
logInfo(`[${scanContext}] Reset service state for new path`, { path: path25 });
|
|
22902
23072
|
}
|
|
22903
23073
|
try {
|
|
22904
23074
|
const loginContext = createMcpLoginContext("check_new_fixes");
|
|
@@ -22917,7 +23087,7 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
22917
23087
|
}
|
|
22918
23088
|
throw error;
|
|
22919
23089
|
}
|
|
22920
|
-
this.triggerScan({ path:
|
|
23090
|
+
this.triggerScan({ path: path25, gqlClient: this.gqlClient });
|
|
22921
23091
|
let isMvsAutoFixEnabled = null;
|
|
22922
23092
|
try {
|
|
22923
23093
|
isMvsAutoFixEnabled = await this.gqlClient.getMvsAutoFixSettings();
|
|
@@ -22951,33 +23121,33 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
22951
23121
|
return noFreshFixesPrompt;
|
|
22952
23122
|
}
|
|
22953
23123
|
triggerScan({
|
|
22954
|
-
path:
|
|
23124
|
+
path: path25,
|
|
22955
23125
|
gqlClient
|
|
22956
23126
|
}) {
|
|
22957
|
-
if (this.path !==
|
|
22958
|
-
this.path =
|
|
23127
|
+
if (this.path !== path25) {
|
|
23128
|
+
this.path = path25;
|
|
22959
23129
|
this.reset();
|
|
22960
|
-
logInfo(`Reset service state for new path in triggerScan`, { path:
|
|
23130
|
+
logInfo(`Reset service state for new path in triggerScan`, { path: path25 });
|
|
22961
23131
|
}
|
|
22962
23132
|
this.gqlClient = gqlClient;
|
|
22963
23133
|
if (!this.intervalId) {
|
|
22964
|
-
this.startPeriodicScanning(
|
|
22965
|
-
this.executeInitialScan(
|
|
22966
|
-
void this.executeInitialFullScan(
|
|
23134
|
+
this.startPeriodicScanning(path25);
|
|
23135
|
+
this.executeInitialScan(path25);
|
|
23136
|
+
void this.executeInitialFullScan(path25);
|
|
22967
23137
|
}
|
|
22968
23138
|
}
|
|
22969
|
-
startPeriodicScanning(
|
|
23139
|
+
startPeriodicScanning(path25) {
|
|
22970
23140
|
const scanContext = ScanContext.BACKGROUND_PERIODIC;
|
|
22971
23141
|
logDebug(
|
|
22972
23142
|
`[${scanContext}] Starting periodic scan for new security vulnerabilities`,
|
|
22973
23143
|
{
|
|
22974
|
-
path:
|
|
23144
|
+
path: path25
|
|
22975
23145
|
}
|
|
22976
23146
|
);
|
|
22977
23147
|
this.intervalId = setInterval(() => {
|
|
22978
|
-
logDebug(`[${scanContext}] Triggering periodic security scan`, { path:
|
|
23148
|
+
logDebug(`[${scanContext}] Triggering periodic security scan`, { path: path25 });
|
|
22979
23149
|
this.scanForSecurityVulnerabilities({
|
|
22980
|
-
path:
|
|
23150
|
+
path: path25,
|
|
22981
23151
|
scanContext
|
|
22982
23152
|
}).catch((error) => {
|
|
22983
23153
|
logError(`[${scanContext}] Error during periodic security scan`, {
|
|
@@ -22986,45 +23156,45 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
22986
23156
|
});
|
|
22987
23157
|
}, MCP_PERIODIC_CHECK_INTERVAL);
|
|
22988
23158
|
}
|
|
22989
|
-
async executeInitialFullScan(
|
|
23159
|
+
async executeInitialFullScan(path25) {
|
|
22990
23160
|
const scanContext = ScanContext.FULL_SCAN;
|
|
22991
|
-
logDebug(`[${scanContext}] Triggering initial full security scan`, { path:
|
|
23161
|
+
logDebug(`[${scanContext}] Triggering initial full security scan`, { path: path25 });
|
|
22992
23162
|
logDebug(`[${scanContext}] Full scan paths scanned`, {
|
|
22993
23163
|
fullScanPathsScanned: this.fullScanPathsScanned
|
|
22994
23164
|
});
|
|
22995
|
-
if (this.fullScanPathsScanned.includes(
|
|
23165
|
+
if (this.fullScanPathsScanned.includes(path25)) {
|
|
22996
23166
|
logDebug(`[${scanContext}] Full scan already executed for this path`, {
|
|
22997
|
-
path:
|
|
23167
|
+
path: path25
|
|
22998
23168
|
});
|
|
22999
23169
|
return;
|
|
23000
23170
|
}
|
|
23001
23171
|
configStore.set("fullScanPathsScanned", [
|
|
23002
23172
|
...this.fullScanPathsScanned,
|
|
23003
|
-
|
|
23173
|
+
path25
|
|
23004
23174
|
]);
|
|
23005
23175
|
try {
|
|
23006
23176
|
await this.scanForSecurityVulnerabilities({
|
|
23007
|
-
path:
|
|
23177
|
+
path: path25,
|
|
23008
23178
|
isAllFilesScan: true,
|
|
23009
23179
|
isAllDetectionRulesScan: true,
|
|
23010
23180
|
scanContext: ScanContext.FULL_SCAN
|
|
23011
23181
|
});
|
|
23012
|
-
if (!this.fullScanPathsScanned.includes(
|
|
23013
|
-
this.fullScanPathsScanned.push(
|
|
23182
|
+
if (!this.fullScanPathsScanned.includes(path25)) {
|
|
23183
|
+
this.fullScanPathsScanned.push(path25);
|
|
23014
23184
|
configStore.set("fullScanPathsScanned", this.fullScanPathsScanned);
|
|
23015
23185
|
}
|
|
23016
|
-
logInfo(`[${scanContext}] Full scan completed`, { path:
|
|
23186
|
+
logInfo(`[${scanContext}] Full scan completed`, { path: path25 });
|
|
23017
23187
|
} catch (error) {
|
|
23018
23188
|
logError(`[${scanContext}] Error during initial full security scan`, {
|
|
23019
23189
|
error
|
|
23020
23190
|
});
|
|
23021
23191
|
}
|
|
23022
23192
|
}
|
|
23023
|
-
executeInitialScan(
|
|
23193
|
+
executeInitialScan(path25) {
|
|
23024
23194
|
const scanContext = ScanContext.BACKGROUND_INITIAL;
|
|
23025
|
-
logDebug(`[${scanContext}] Triggering initial security scan`, { path:
|
|
23195
|
+
logDebug(`[${scanContext}] Triggering initial security scan`, { path: path25 });
|
|
23026
23196
|
this.scanForSecurityVulnerabilities({
|
|
23027
|
-
path:
|
|
23197
|
+
path: path25,
|
|
23028
23198
|
scanContext: ScanContext.BACKGROUND_INITIAL
|
|
23029
23199
|
}).catch((error) => {
|
|
23030
23200
|
logError(`[${scanContext}] Error during initial security scan`, { error });
|
|
@@ -23121,9 +23291,9 @@ Example payload:
|
|
|
23121
23291
|
`Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
|
|
23122
23292
|
);
|
|
23123
23293
|
}
|
|
23124
|
-
const
|
|
23294
|
+
const path25 = pathValidationResult.path;
|
|
23125
23295
|
const resultText = await this.newFixesService.getFreshFixes({
|
|
23126
|
-
path:
|
|
23296
|
+
path: path25
|
|
23127
23297
|
});
|
|
23128
23298
|
logInfo("CheckForNewAvailableFixesTool execution completed", {
|
|
23129
23299
|
resultText
|
|
@@ -23301,8 +23471,8 @@ Call this tool instead of ${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES} when you only
|
|
|
23301
23471
|
`Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
|
|
23302
23472
|
);
|
|
23303
23473
|
}
|
|
23304
|
-
const
|
|
23305
|
-
const gitService = new GitService(
|
|
23474
|
+
const path25 = pathValidationResult.path;
|
|
23475
|
+
const gitService = new GitService(path25, log);
|
|
23306
23476
|
const gitValidation = await gitService.validateRepository();
|
|
23307
23477
|
if (!gitValidation.isValid) {
|
|
23308
23478
|
throw new Error(`Invalid git repository: ${gitValidation.error}`);
|
|
@@ -23687,9 +23857,9 @@ Example payload:
|
|
|
23687
23857
|
`Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
|
|
23688
23858
|
);
|
|
23689
23859
|
}
|
|
23690
|
-
const
|
|
23860
|
+
const path25 = pathValidationResult.path;
|
|
23691
23861
|
const files = await getLocalFiles({
|
|
23692
|
-
path:
|
|
23862
|
+
path: path25,
|
|
23693
23863
|
maxFileSize: MCP_MAX_FILE_SIZE,
|
|
23694
23864
|
maxFiles: args.maxFiles,
|
|
23695
23865
|
scanContext: ScanContext.USER_REQUEST,
|
|
@@ -23709,7 +23879,7 @@ Example payload:
|
|
|
23709
23879
|
try {
|
|
23710
23880
|
const fixResult = await this.vulnerabilityFixService.processVulnerabilities({
|
|
23711
23881
|
fileList: files.map((file) => file.relativePath),
|
|
23712
|
-
repositoryPath:
|
|
23882
|
+
repositoryPath: path25,
|
|
23713
23883
|
offset: args.offset,
|
|
23714
23884
|
limit: args.limit,
|
|
23715
23885
|
isRescan: args.rescan || !!args.maxFiles
|
|
@@ -23844,7 +24014,7 @@ function reviewBuilder(yargs2) {
|
|
|
23844
24014
|
),
|
|
23845
24015
|
type: "string",
|
|
23846
24016
|
demandOption: false
|
|
23847
|
-
}).example(
|
|
24017
|
+
}).option("polling", pollingOption).example(
|
|
23848
24018
|
"npx mobbdev@latest review -r https://github.com/WebGoat/WebGoat -f <your_vulnerability_report_path> --ch <pr_last_commit> --pr <pr_number> --ref <pr_branch_name> --api-key <api_key> --src-path <your_repo_path>",
|
|
23849
24019
|
"add fixes to your pr"
|
|
23850
24020
|
).help();
|
|
@@ -23864,7 +24034,7 @@ async function reviewHandler(args) {
|
|
|
23864
24034
|
|
|
23865
24035
|
// src/args/commands/scan.ts
|
|
23866
24036
|
function scanBuilder(args) {
|
|
23867
|
-
return args.coerce("scanner", (arg) => arg.toLowerCase()).option("repo", repoOption).option("ref", refOption).option("scanner", scannerOptions).option("org", organizationIdOptions).option("mobb-project-name", mobbProjectNameOption).option("y", yesOption).option("ci", ciOption).option("api-key", apiKeyOption).option("cx-project-name", projectNameOption).option("auto-pr", autoPrOption).example(
|
|
24037
|
+
return args.coerce("scanner", (arg) => arg.toLowerCase()).option("repo", repoOption).option("ref", refOption).option("scanner", scannerOptions).option("org", organizationIdOptions).option("mobb-project-name", mobbProjectNameOption).option("y", yesOption).option("ci", ciOption).option("api-key", apiKeyOption).option("cx-project-name", projectNameOption).option("auto-pr", autoPrOption).option("polling", pollingOption).example(
|
|
23868
24038
|
"npx mobbdev@latest scan -r https://github.com/WebGoat/WebGoat",
|
|
23869
24039
|
"Scan an existing repository"
|
|
23870
24040
|
).help();
|
|
@@ -23922,10 +24092,8 @@ async function addScmTokenHandler(args) {
|
|
|
23922
24092
|
await addScmToken(args);
|
|
23923
24093
|
}
|
|
23924
24094
|
|
|
23925
|
-
// src/features/codeium_intellij/data_collector_monitor.ts
|
|
23926
|
-
import { setTimeout as setTimeout4 } from "timers/promises";
|
|
23927
|
-
|
|
23928
24095
|
// src/features/codeium_intellij/data_collector.ts
|
|
24096
|
+
import { z as z46 } from "zod";
|
|
23929
24097
|
init_GitService();
|
|
23930
24098
|
|
|
23931
24099
|
// src/features/codeium_intellij/codeium_language_server_grpc_client.ts
|
|
@@ -24065,9 +24233,45 @@ function findRunningCodeiumLanguageServers() {
|
|
|
24065
24233
|
}
|
|
24066
24234
|
|
|
24067
24235
|
// src/features/codeium_intellij/data_collector.ts
|
|
24068
|
-
|
|
24236
|
+
var HookDataSchema2 = z46.object({
|
|
24237
|
+
trajectory_id: z46.string()
|
|
24238
|
+
});
|
|
24239
|
+
async function processAndUploadHookData2() {
|
|
24240
|
+
const tracePayload = await getTraceDataForHook();
|
|
24241
|
+
if (!tracePayload) {
|
|
24242
|
+
console.warn("Warning: Failed to retrieve chat data.");
|
|
24243
|
+
return;
|
|
24244
|
+
}
|
|
24245
|
+
try {
|
|
24246
|
+
const uploadSuccess = await uploadAiBlameHandlerFromExtension({
|
|
24247
|
+
prompts: tracePayload.prompts,
|
|
24248
|
+
inference: tracePayload.inference,
|
|
24249
|
+
model: tracePayload.model,
|
|
24250
|
+
tool: tracePayload.tool,
|
|
24251
|
+
responseTime: tracePayload.responseTime,
|
|
24252
|
+
blameType: "CHAT" /* Chat */,
|
|
24253
|
+
sessionId: tracePayload.sessionId,
|
|
24254
|
+
repositoryUrl: tracePayload.repositoryUrl
|
|
24255
|
+
});
|
|
24256
|
+
if (uploadSuccess) {
|
|
24257
|
+
console.log("Uploaded trace data.");
|
|
24258
|
+
} else {
|
|
24259
|
+
console.warn("Failed to upload trace data.");
|
|
24260
|
+
}
|
|
24261
|
+
} catch (e) {
|
|
24262
|
+
console.warn("Failed to upload trace data:", e);
|
|
24263
|
+
}
|
|
24264
|
+
}
|
|
24265
|
+
function validateHookData2(data) {
|
|
24266
|
+
return HookDataSchema2.parse(data);
|
|
24267
|
+
}
|
|
24268
|
+
async function getTraceDataForHook() {
|
|
24269
|
+
const rawData = await readStdinData();
|
|
24270
|
+
const hookData = validateHookData2(rawData);
|
|
24271
|
+
return await getTraceDataForTrajectory(hookData.trajectory_id);
|
|
24272
|
+
}
|
|
24273
|
+
async function getTraceDataForTrajectory(trajectoryId) {
|
|
24069
24274
|
const instances = findRunningCodeiumLanguageServers();
|
|
24070
|
-
const results = [];
|
|
24071
24275
|
for (const instance of instances) {
|
|
24072
24276
|
const client = await getGrpcClient(instance.port, instance.csrf);
|
|
24073
24277
|
if (!client) {
|
|
@@ -24077,20 +24281,13 @@ async function getLatestInferences(startFrom) {
|
|
|
24077
24281
|
for (const [cascadeId, chatSummary] of Object.entries(
|
|
24078
24282
|
chats.trajectorySummaries
|
|
24079
24283
|
)) {
|
|
24080
|
-
|
|
24081
|
-
if (!chatLastModifiedSecStr) {
|
|
24284
|
+
if (chatSummary.trajectoryId !== trajectoryId) {
|
|
24082
24285
|
continue;
|
|
24083
24286
|
}
|
|
24084
|
-
|
|
24085
|
-
if (chatLastModifiedSec >= Math.floor(startFrom.getTime() / 1e3)) {
|
|
24086
|
-
const traceData = await processChat(client, cascadeId);
|
|
24087
|
-
if (traceData) {
|
|
24088
|
-
results.push(traceData);
|
|
24089
|
-
}
|
|
24090
|
-
}
|
|
24287
|
+
return await processChat(client, cascadeId);
|
|
24091
24288
|
}
|
|
24092
24289
|
}
|
|
24093
|
-
return
|
|
24290
|
+
return null;
|
|
24094
24291
|
}
|
|
24095
24292
|
async function processChat(client, cascadeId) {
|
|
24096
24293
|
const chatDetails = await client.GetCascadeTrajectory({
|
|
@@ -24186,7 +24383,11 @@ function processChatStepPlannerResponse(step) {
|
|
|
24186
24383
|
}
|
|
24187
24384
|
function processChatStepCodeAction(step) {
|
|
24188
24385
|
const inferences = [];
|
|
24386
|
+
const toolCallName = step.metadata?.toolCall?.name;
|
|
24189
24387
|
const unifiedDiff = step.codeAction?.actionResult?.edit?.diff?.unifiedDiff;
|
|
24388
|
+
if (!toolCallName) {
|
|
24389
|
+
return { prompts: [], inferences };
|
|
24390
|
+
}
|
|
24190
24391
|
if (!unifiedDiff) {
|
|
24191
24392
|
return { prompts: [], inferences };
|
|
24192
24393
|
}
|
|
@@ -24198,63 +24399,119 @@ function processChatStepCodeAction(step) {
|
|
|
24198
24399
|
return { prompts: [], inferences };
|
|
24199
24400
|
}
|
|
24200
24401
|
|
|
24201
|
-
// src/features/codeium_intellij/
|
|
24202
|
-
|
|
24203
|
-
|
|
24204
|
-
|
|
24205
|
-
|
|
24206
|
-
|
|
24207
|
-
|
|
24208
|
-
try {
|
|
24209
|
-
const startFrom = lastUpdateTs;
|
|
24210
|
-
lastUpdateTs = /* @__PURE__ */ new Date();
|
|
24211
|
-
tracePayloads = await getLatestInferences(startFrom);
|
|
24212
|
-
} catch (e) {
|
|
24213
|
-
console.error("Failed to retrieve Windsurf IntelliJ inferences.", e);
|
|
24214
|
-
}
|
|
24215
|
-
for (const tracePayload of tracePayloads) {
|
|
24216
|
-
await tryUpload(tracePayload);
|
|
24217
|
-
}
|
|
24218
|
-
await setTimeout4(POLL_INTERVAL);
|
|
24219
|
-
}
|
|
24402
|
+
// src/features/codeium_intellij/install_hook.ts
|
|
24403
|
+
import fsPromises6 from "fs/promises";
|
|
24404
|
+
import os13 from "os";
|
|
24405
|
+
import path24 from "path";
|
|
24406
|
+
import chalk12 from "chalk";
|
|
24407
|
+
function getCodeiumHooksPath() {
|
|
24408
|
+
return path24.join(os13.homedir(), ".codeium", "hooks.json");
|
|
24220
24409
|
}
|
|
24221
|
-
async function
|
|
24410
|
+
async function readCodeiumHooks() {
|
|
24411
|
+
const hooksPath = getCodeiumHooksPath();
|
|
24222
24412
|
try {
|
|
24223
|
-
const
|
|
24224
|
-
|
|
24225
|
-
|
|
24226
|
-
|
|
24227
|
-
|
|
24228
|
-
|
|
24229
|
-
|
|
24230
|
-
|
|
24231
|
-
|
|
24232
|
-
|
|
24233
|
-
|
|
24234
|
-
|
|
24235
|
-
|
|
24236
|
-
|
|
24413
|
+
const content = await fsPromises6.readFile(hooksPath, "utf-8");
|
|
24414
|
+
return JSON.parse(content);
|
|
24415
|
+
} catch {
|
|
24416
|
+
return {};
|
|
24417
|
+
}
|
|
24418
|
+
}
|
|
24419
|
+
async function writeCodeiumHooks(config2) {
|
|
24420
|
+
const hooksPath = getCodeiumHooksPath();
|
|
24421
|
+
const dir = path24.dirname(hooksPath);
|
|
24422
|
+
await fsPromises6.mkdir(dir, { recursive: true });
|
|
24423
|
+
await fsPromises6.writeFile(
|
|
24424
|
+
hooksPath,
|
|
24425
|
+
JSON.stringify(config2, null, 2),
|
|
24426
|
+
"utf-8"
|
|
24427
|
+
);
|
|
24428
|
+
}
|
|
24429
|
+
async function installWindsurfHooks(options = {}) {
|
|
24430
|
+
const hooksPath = getCodeiumHooksPath();
|
|
24431
|
+
console.log(chalk12.blue("Installing Mobb hooks in Windsurf IntelliJ..."));
|
|
24432
|
+
const config2 = await readCodeiumHooks();
|
|
24433
|
+
if (!config2.hooks) {
|
|
24434
|
+
config2.hooks = {};
|
|
24435
|
+
}
|
|
24436
|
+
if (!config2.hooks.post_write_code) {
|
|
24437
|
+
config2.hooks.post_write_code = [];
|
|
24438
|
+
}
|
|
24439
|
+
let command = "npx --yes mobbdev@latest windsurf-intellij-process-hook";
|
|
24440
|
+
if (options.saveEnv) {
|
|
24441
|
+
const envVars = [];
|
|
24442
|
+
if (process.env["WEB_APP_URL"]) {
|
|
24443
|
+
envVars.push(`WEB_APP_URL="${process.env["WEB_APP_URL"]}"`);
|
|
24237
24444
|
}
|
|
24238
|
-
|
|
24239
|
-
|
|
24445
|
+
if (process.env["API_URL"]) {
|
|
24446
|
+
envVars.push(`API_URL="${process.env["API_URL"]}"`);
|
|
24447
|
+
}
|
|
24448
|
+
if (envVars.length > 0) {
|
|
24449
|
+
command = `${envVars.join(" ")} ${command}`;
|
|
24450
|
+
console.log(
|
|
24451
|
+
chalk12.blue(
|
|
24452
|
+
`Adding environment variables to hook command: ${envVars.join(", ")}`
|
|
24453
|
+
)
|
|
24454
|
+
);
|
|
24455
|
+
}
|
|
24456
|
+
}
|
|
24457
|
+
const mobbHook = {
|
|
24458
|
+
command,
|
|
24459
|
+
show_output: true
|
|
24460
|
+
};
|
|
24461
|
+
const existingHookIndex = config2.hooks.post_write_code.findIndex(
|
|
24462
|
+
(hook) => hook.command?.includes("mobbdev@latest windsurf-intellij-process-hook")
|
|
24463
|
+
);
|
|
24464
|
+
if (existingHookIndex >= 0) {
|
|
24465
|
+
console.log(chalk12.yellow("Mobb hook already exists, updating..."));
|
|
24466
|
+
config2.hooks.post_write_code[existingHookIndex] = mobbHook;
|
|
24467
|
+
} else {
|
|
24468
|
+
console.log(chalk12.green("Adding new Mobb hook..."));
|
|
24469
|
+
config2.hooks.post_write_code.push(mobbHook);
|
|
24240
24470
|
}
|
|
24471
|
+
await writeCodeiumHooks(config2);
|
|
24472
|
+
console.log(
|
|
24473
|
+
chalk12.green(
|
|
24474
|
+
`\u2705 Mobb hooks ${options.saveEnv ? "and environment variables " : ""}installed successfully in ${hooksPath}`
|
|
24475
|
+
)
|
|
24476
|
+
);
|
|
24241
24477
|
}
|
|
24242
24478
|
|
|
24243
24479
|
// src/args/commands/windsurf_intellij.ts
|
|
24244
|
-
var
|
|
24480
|
+
var windsurfIntellijInstallHookBuilder = (yargs2) => {
|
|
24481
|
+
return yargs2.option("save-env", {
|
|
24482
|
+
type: "boolean",
|
|
24483
|
+
description: "Save WEB_APP_URL, and API_URL environment variables to hooks config",
|
|
24484
|
+
default: false
|
|
24485
|
+
}).example(
|
|
24486
|
+
"$0 windsurf-intellij-install-hook",
|
|
24487
|
+
"Install Windsurf IntelliJ hooks for data collection"
|
|
24488
|
+
).example(
|
|
24489
|
+
"$0 windsurf-intellij-install-hook --save-env",
|
|
24490
|
+
"Install hooks and save environment variables to config"
|
|
24491
|
+
).strict();
|
|
24492
|
+
};
|
|
24493
|
+
var windsurfIntellijProcessHookBuilder = (yargs2) => {
|
|
24245
24494
|
return yargs2.example(
|
|
24246
|
-
"$0 windsurf-intellij-
|
|
24247
|
-
"
|
|
24495
|
+
"$0 windsurf-intellij-process-hook",
|
|
24496
|
+
"Process Windsurf IntelliJ hook data and upload to backend"
|
|
24248
24497
|
).strict();
|
|
24249
24498
|
};
|
|
24250
|
-
var
|
|
24499
|
+
var windsurfIntellijInstallHookHandler = async (argv) => {
|
|
24500
|
+
try {
|
|
24501
|
+
await getAuthenticatedGQLClient({ isSkipPrompts: false });
|
|
24502
|
+
await installWindsurfHooks({ saveEnv: argv["save-env"] });
|
|
24503
|
+
process.exit(0);
|
|
24504
|
+
} catch (error) {
|
|
24505
|
+
console.error("Failed to install Windsurf IntelliJ hooks:", error);
|
|
24506
|
+
process.exit(1);
|
|
24507
|
+
}
|
|
24508
|
+
};
|
|
24509
|
+
var windsurfIntellijProcessHookHandler = async () => {
|
|
24251
24510
|
try {
|
|
24252
|
-
|
|
24253
|
-
|
|
24254
|
-
console.log("Press Ctrl+C to stop.\n");
|
|
24255
|
-
await startMonitoring();
|
|
24511
|
+
await processAndUploadHookData2();
|
|
24512
|
+
process.exit(0);
|
|
24256
24513
|
} catch (error) {
|
|
24257
|
-
console.error("Windsurf IntelliJ
|
|
24514
|
+
console.error("Failed to process Windsurf IntelliJ hook data:", error);
|
|
24258
24515
|
process.exit(1);
|
|
24259
24516
|
}
|
|
24260
24517
|
};
|
|
@@ -24263,78 +24520,83 @@ var windsurfIntellijMonitorHandler = async () => {
|
|
|
24263
24520
|
var parseArgs = async (args) => {
|
|
24264
24521
|
const yargsInstance = yargs(args);
|
|
24265
24522
|
return yargsInstance.updateStrings({
|
|
24266
|
-
"Commands:":
|
|
24267
|
-
"Options:":
|
|
24268
|
-
"Examples:":
|
|
24269
|
-
"Show help":
|
|
24523
|
+
"Commands:": chalk13.yellow.underline.bold("Commands:"),
|
|
24524
|
+
"Options:": chalk13.yellow.underline.bold("Options:"),
|
|
24525
|
+
"Examples:": chalk13.yellow.underline.bold("Examples:"),
|
|
24526
|
+
"Show help": chalk13.bold("Show help")
|
|
24270
24527
|
}).usage(
|
|
24271
|
-
`${
|
|
24528
|
+
`${chalk13.bold(
|
|
24272
24529
|
"\n Bugsy - Trusted, Automatic Vulnerability Fixer \u{1F575}\uFE0F\u200D\u2642\uFE0F\n\n"
|
|
24273
|
-
)} ${
|
|
24274
|
-
$0 ${
|
|
24530
|
+
)} ${chalk13.yellow.underline.bold("Usage:")}
|
|
24531
|
+
$0 ${chalk13.green(
|
|
24275
24532
|
"<command>"
|
|
24276
|
-
)} ${
|
|
24533
|
+
)} ${chalk13.dim("[options]")}
|
|
24277
24534
|
`
|
|
24278
24535
|
).version(false).command(
|
|
24279
24536
|
mobbCliCommand.scan,
|
|
24280
|
-
|
|
24537
|
+
chalk13.bold(
|
|
24281
24538
|
"Scan your code for vulnerabilities, get automated fixes right away."
|
|
24282
24539
|
),
|
|
24283
24540
|
scanBuilder,
|
|
24284
24541
|
scanHandler
|
|
24285
24542
|
).command(
|
|
24286
24543
|
mobbCliCommand.analyze,
|
|
24287
|
-
|
|
24544
|
+
chalk13.bold(
|
|
24288
24545
|
"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."
|
|
24289
24546
|
),
|
|
24290
24547
|
analyzeBuilder,
|
|
24291
24548
|
analyzeHandler
|
|
24292
24549
|
).command(
|
|
24293
24550
|
mobbCliCommand.review,
|
|
24294
|
-
|
|
24551
|
+
chalk13.bold(
|
|
24295
24552
|
"Mobb will review your github pull requests and provide comments with fixes "
|
|
24296
24553
|
),
|
|
24297
24554
|
reviewBuilder,
|
|
24298
24555
|
reviewHandler
|
|
24299
24556
|
).command(
|
|
24300
24557
|
mobbCliCommand.addScmToken,
|
|
24301
|
-
|
|
24558
|
+
chalk13.bold(
|
|
24302
24559
|
"Add your SCM (Github, Gitlab, Azure DevOps) token to Mobb to enable automated fixes."
|
|
24303
24560
|
),
|
|
24304
24561
|
addScmTokenBuilder,
|
|
24305
24562
|
addScmTokenHandler
|
|
24306
24563
|
).command(
|
|
24307
24564
|
mobbCliCommand.convertToSarif,
|
|
24308
|
-
|
|
24565
|
+
chalk13.bold("Convert an existing SAST report to SARIF format."),
|
|
24309
24566
|
convertToSarifBuilder,
|
|
24310
24567
|
convertToSarifHandler
|
|
24311
24568
|
).command(
|
|
24312
24569
|
mobbCliCommand.mcp,
|
|
24313
|
-
|
|
24570
|
+
chalk13.bold("Launch the MCP (Model Context Protocol) server."),
|
|
24314
24571
|
mcpBuilder,
|
|
24315
24572
|
mcpHandler
|
|
24316
24573
|
).command(
|
|
24317
24574
|
mobbCliCommand.uploadAiBlame,
|
|
24318
|
-
|
|
24575
|
+
chalk13.bold(
|
|
24319
24576
|
"Upload AI Blame inference artifacts (prompt + inference) and finalize them."
|
|
24320
24577
|
),
|
|
24321
24578
|
uploadAiBlameBuilder,
|
|
24322
24579
|
uploadAiBlameCommandHandler
|
|
24323
24580
|
).command(
|
|
24324
24581
|
mobbCliCommand.claudeCodeInstallHook,
|
|
24325
|
-
|
|
24582
|
+
chalk13.bold("Install Claude Code hooks for data collection."),
|
|
24326
24583
|
claudeCodeInstallHookBuilder,
|
|
24327
24584
|
claudeCodeInstallHookHandler
|
|
24328
24585
|
).command(
|
|
24329
24586
|
mobbCliCommand.claudeCodeProcessHook,
|
|
24330
|
-
|
|
24587
|
+
chalk13.bold("Process Claude Code hook data and upload to backend."),
|
|
24331
24588
|
claudeCodeProcessHookBuilder,
|
|
24332
24589
|
claudeCodeProcessHookHandler
|
|
24333
24590
|
).command(
|
|
24334
|
-
mobbCliCommand.
|
|
24335
|
-
|
|
24336
|
-
|
|
24337
|
-
|
|
24591
|
+
mobbCliCommand.windsurfIntellijInstallHook,
|
|
24592
|
+
chalk13.bold("Install Windsurf IntelliJ hooks for data collection."),
|
|
24593
|
+
windsurfIntellijInstallHookBuilder,
|
|
24594
|
+
windsurfIntellijInstallHookHandler
|
|
24595
|
+
).command(
|
|
24596
|
+
mobbCliCommand.windsurfIntellijProcessHook,
|
|
24597
|
+
chalk13.bold("Process Windsurf IntelliJ hook data and upload to backend."),
|
|
24598
|
+
windsurfIntellijProcessHookBuilder,
|
|
24599
|
+
windsurfIntellijProcessHookHandler
|
|
24338
24600
|
).example(
|
|
24339
24601
|
"npx mobbdev@latest scan -r https://github.com/WebGoat/WebGoat",
|
|
24340
24602
|
"Scan an existing repository"
|
|
@@ -24343,7 +24605,7 @@ var parseArgs = async (args) => {
|
|
|
24343
24605
|
handler() {
|
|
24344
24606
|
yargsInstance.showHelp();
|
|
24345
24607
|
}
|
|
24346
|
-
}).strictOptions().help("h").alias("h", "help").epilog(
|
|
24608
|
+
}).strictOptions().help("h").alias("h", "help").epilog(chalk13.bgBlue("Made with \u2764\uFE0F by Mobb")).showHelpOnFail(true).wrap(Math.min(120, yargsInstance.terminalWidth())).parse();
|
|
24347
24609
|
};
|
|
24348
24610
|
|
|
24349
24611
|
// src/index.ts
|