mobbdev 1.2.19 → 1.2.22

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 CHANGED
@@ -120,10 +120,13 @@ function getSdk(client, withWrapper = defaultWrapper) {
120
120
  },
121
121
  streamCommitBlameRequests(variables, requestHeaders, signal) {
122
122
  return withWrapper((wrappedRequestHeaders) => client.request({ document: StreamCommitBlameRequestsDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "streamCommitBlameRequests", "subscription", variables);
123
+ },
124
+ ScanSkill(variables, requestHeaders, signal) {
125
+ return withWrapper((wrappedRequestHeaders) => client.request({ document: ScanSkillDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "ScanSkill", "mutation", variables);
123
126
  }
124
127
  };
125
128
  }
126
- var AiBlameInferenceType, FixQuestionInputType, Language, ManifestAction, Effort_To_Apply_Fix_Enum, Fix_Rating_Tag_Enum, Fix_Report_State_Enum, Fix_State_Enum, IssueLanguage_Enum, IssueType_Enum, Pr_Status_Enum, Project_Role_Type_Enum, Vulnerability_Report_Issue_Category_Enum, Vulnerability_Report_Issue_State_Enum, Vulnerability_Report_Issue_Tag_Enum, Vulnerability_Report_Vendor_Enum, Vulnerability_Severity_Enum, FixDetailsFragmentDoc, FixReportSummaryFieldsFragmentDoc, MeDocument, GetLastOrgAndNamedProjectDocument, GetLastOrgDocument, GetEncryptedApiTokenDocument, FixReportStateDocument, GetVulnerabilityReportPathsDocument, GetAnalysisSubscriptionDocument, GetAnalysisDocument, GetFixesDocument, GetVulByNodesMetadataDocument, GetFalsePositiveDocument, UpdateScmTokenDocument, UploadS3BucketInfoDocument, GetTracyDiffUploadUrlDocument, AnalyzeCommitForExtensionAiBlameDocument, GetAiBlameInferenceDocument, GetAiBlameAttributionPromptDocument, GetPromptSummaryDocument, UploadAiBlameInferencesInitDocument, FinalizeAiBlameInferencesUploadDocument, DigestVulnerabilityReportDocument, SubmitVulnerabilityReportDocument, CreateCommunityUserDocument, CreateCliLoginDocument, PerformCliLoginDocument, CreateProjectDocument, ValidateRepoUrlDocument, GitReferenceDocument, AutoPrAnalysisDocument, GetFixReportsByRepoUrlDocument, GetReportFixesDocument, GetLatestReportByRepoUrlDocument, UpdateDownloadedFixDataDocument, GetUserMvsAutoFixDocument, StreamBlameAiAnalysisRequestsDocument, StreamCommitBlameRequestsDocument, defaultWrapper;
129
+ var AiBlameInferenceType, FixQuestionInputType, Language, ManifestAction, Effort_To_Apply_Fix_Enum, Fix_Rating_Tag_Enum, Fix_Report_State_Enum, Fix_State_Enum, IssueLanguage_Enum, IssueType_Enum, Pr_Status_Enum, Project_Role_Type_Enum, Vulnerability_Report_Issue_Category_Enum, Vulnerability_Report_Issue_State_Enum, Vulnerability_Report_Issue_Tag_Enum, Vulnerability_Report_Vendor_Enum, Vulnerability_Severity_Enum, FixDetailsFragmentDoc, FixReportSummaryFieldsFragmentDoc, MeDocument, GetLastOrgAndNamedProjectDocument, GetLastOrgDocument, GetEncryptedApiTokenDocument, FixReportStateDocument, GetVulnerabilityReportPathsDocument, GetAnalysisSubscriptionDocument, GetAnalysisDocument, GetFixesDocument, GetVulByNodesMetadataDocument, GetFalsePositiveDocument, UpdateScmTokenDocument, UploadS3BucketInfoDocument, GetTracyDiffUploadUrlDocument, AnalyzeCommitForExtensionAiBlameDocument, GetAiBlameInferenceDocument, GetAiBlameAttributionPromptDocument, GetPromptSummaryDocument, UploadAiBlameInferencesInitDocument, FinalizeAiBlameInferencesUploadDocument, DigestVulnerabilityReportDocument, SubmitVulnerabilityReportDocument, CreateCommunityUserDocument, CreateCliLoginDocument, PerformCliLoginDocument, CreateProjectDocument, ValidateRepoUrlDocument, GitReferenceDocument, AutoPrAnalysisDocument, GetFixReportsByRepoUrlDocument, GetReportFixesDocument, GetLatestReportByRepoUrlDocument, UpdateDownloadedFixDataDocument, GetUserMvsAutoFixDocument, StreamBlameAiAnalysisRequestsDocument, StreamCommitBlameRequestsDocument, ScanSkillDocument, defaultWrapper;
127
130
  var init_client_generates = __esm({
128
131
  "src/features/analysis/scm/generates/client_generates.ts"() {
129
132
  "use strict";
@@ -1197,6 +1200,32 @@ var init_client_generates = __esm({
1197
1200
  completedOn
1198
1201
  error
1199
1202
  }
1203
+ }
1204
+ `;
1205
+ ScanSkillDocument = `
1206
+ mutation ScanSkill($skillUrl: String!) {
1207
+ scanSkill(skillUrl: $skillUrl) {
1208
+ skillName
1209
+ skillHash
1210
+ skillVersion
1211
+ verdict
1212
+ findingsCount
1213
+ findings {
1214
+ category
1215
+ severity
1216
+ ruleId
1217
+ explanation
1218
+ evidence
1219
+ filePath
1220
+ lineNumber
1221
+ confidence
1222
+ layer
1223
+ }
1224
+ scanDurationMs
1225
+ layersExecuted
1226
+ cached
1227
+ summary
1228
+ }
1200
1229
  }
1201
1230
  `;
1202
1231
  defaultWrapper = (action, _operationName, _operationType, _variables) => action();
@@ -3804,7 +3833,7 @@ ${rootContent}`;
3804
3833
  }
3805
3834
  }
3806
3835
  /**
3807
- * Gets local commit data including diff, timestamp, and parent commits.
3836
+ * Gets local commit data including diff and timestamp.
3808
3837
  * Used by Tracy extension to send commit data directly without requiring SCM token.
3809
3838
  * @param commitSha The commit SHA to get data for
3810
3839
  * @param maxDiffSizeBytes Maximum diff size in bytes (default 3MB). Returns null if exceeded.
@@ -3816,7 +3845,7 @@ ${rootContent}`;
3816
3845
  const DIFF_DELIMITER = "---MOBB_DIFF_START---";
3817
3846
  const output = await this.git.show([
3818
3847
  commitSha,
3819
- `--format=%cI%n%P%n${DIFF_DELIMITER}`,
3848
+ `--format=%cI%n${DIFF_DELIMITER}`,
3820
3849
  "--patch"
3821
3850
  ]);
3822
3851
  const delimiterIndex = output.indexOf(DIFF_DELIMITER);
@@ -3871,7 +3900,7 @@ import Debug19 from "debug";
3871
3900
  import { hideBin } from "yargs/helpers";
3872
3901
 
3873
3902
  // src/args/yargs.ts
3874
- import chalk13 from "chalk";
3903
+ import chalk15 from "chalk";
3875
3904
  import yargs from "yargs/yargs";
3876
3905
 
3877
3906
  // src/args/commands/convert_to_sarif.ts
@@ -6767,7 +6796,7 @@ async function getAdoSdk(params) {
6767
6796
  const url = new URL(repoUrl);
6768
6797
  const origin2 = url.origin.toLowerCase().endsWith(".visualstudio.com") ? DEFUALT_ADO_ORIGIN : url.origin.toLowerCase();
6769
6798
  const params2 = `path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=commit&versionDescriptor[version]=${branch}&resolveLfs=true&$format=zip&api-version=5.0&download=true`;
6770
- const path25 = [
6799
+ const path26 = [
6771
6800
  prefixPath,
6772
6801
  owner,
6773
6802
  projectName,
@@ -6778,7 +6807,7 @@ async function getAdoSdk(params) {
6778
6807
  "items",
6779
6808
  "items"
6780
6809
  ].filter(Boolean).join("/");
6781
- return new URL(`${path25}?${params2}`, origin2).toString();
6810
+ return new URL(`${path26}?${params2}`, origin2).toString();
6782
6811
  },
6783
6812
  async getAdoBranchList({ repoUrl }) {
6784
6813
  try {
@@ -8322,7 +8351,7 @@ function getGithubSdk(params = {}) {
8322
8351
  if (res.status === 204) {
8323
8352
  return true;
8324
8353
  }
8325
- } catch (collaboratorError) {
8354
+ } catch (_collaboratorError) {
8326
8355
  try {
8327
8356
  const permissionRes = await octokit.rest.repos.getCollaboratorPermissionLevel({
8328
8357
  owner,
@@ -8332,16 +8361,16 @@ function getGithubSdk(params = {}) {
8332
8361
  if (permissionRes.data.permission !== "none") {
8333
8362
  return true;
8334
8363
  }
8335
- } catch (permissionError) {
8364
+ } catch (_permissionError) {
8336
8365
  try {
8337
8366
  await octokit.rest.repos.get({ owner, repo });
8338
8367
  return true;
8339
- } catch (repoError) {
8368
+ } catch (_repoError) {
8340
8369
  return false;
8341
8370
  }
8342
8371
  }
8343
8372
  }
8344
- } catch (e) {
8373
+ } catch (_e) {
8345
8374
  return false;
8346
8375
  }
8347
8376
  return false;
@@ -8382,7 +8411,7 @@ function getGithubSdk(params = {}) {
8382
8411
  branch
8383
8412
  });
8384
8413
  return branch === res.data.name;
8385
- } catch (e) {
8414
+ } catch (_e) {
8386
8415
  return false;
8387
8416
  }
8388
8417
  },
@@ -8577,7 +8606,7 @@ function getGithubSdk(params = {}) {
8577
8606
  const sourceFileContentResponse = await octokit.rest.repos.getContent({
8578
8607
  owner: sourceOwner,
8579
8608
  repo: sourceRepo,
8580
- path: "/" + sourceFilePath
8609
+ path: `/${sourceFilePath}`
8581
8610
  });
8582
8611
  const { data: repository } = await octokit.rest.repos.get({ owner, repo });
8583
8612
  const defaultBranch = repository.default_branch;
@@ -8605,7 +8634,7 @@ function getGithubSdk(params = {}) {
8605
8634
  const secondFileContentResponse = await octokit.rest.repos.getContent({
8606
8635
  owner: sourceOwner,
8607
8636
  repo: sourceRepo,
8608
- path: "/" + secondFilePath
8637
+ path: `/${secondFilePath}`
8609
8638
  });
8610
8639
  const secondDecodedContent = Buffer.from(
8611
8640
  // Check if file content exists and handle different response types
@@ -10373,6 +10402,7 @@ async function getGitlabMergeRequestDiff({
10373
10402
  title: mr.title,
10374
10403
  description: mr.description || void 0,
10375
10404
  commits,
10405
+ headCommitSha: mr.sha,
10376
10406
  diffLines
10377
10407
  };
10378
10408
  }
@@ -11745,7 +11775,8 @@ var mobbCliCommand = {
11745
11775
  claudeCodeInstallHook: "claude-code-install-hook",
11746
11776
  claudeCodeProcessHook: "claude-code-process-hook",
11747
11777
  windsurfIntellijInstallHook: "windsurf-intellij-install-hook",
11748
- windsurfIntellijProcessHook: "windsurf-intellij-process-hook"
11778
+ windsurfIntellijProcessHook: "windsurf-intellij-process-hook",
11779
+ scanSkill: "scan-skill"
11749
11780
  };
11750
11781
  var ScanContext = {
11751
11782
  FULL_SCAN: "FULL_SCAN",
@@ -11756,10 +11787,11 @@ var ScanContext = {
11756
11787
  };
11757
11788
 
11758
11789
  // src/args/commands/analyze.ts
11759
- import fs11 from "fs";
11760
- import chalk8 from "chalk";
11790
+ import fs12 from "fs";
11791
+ import chalk9 from "chalk";
11761
11792
 
11762
11793
  // src/commands/index.ts
11794
+ import chalk7 from "chalk";
11763
11795
  import chalkAnimation from "chalk-animation";
11764
11796
 
11765
11797
  // src/features/analysis/index.ts
@@ -12545,6 +12577,9 @@ var GQLClient = class {
12545
12577
  async getTracyDiffUploadUrl(variables) {
12546
12578
  return await this._clientSdk.GetTracyDiffUploadUrl(variables);
12547
12579
  }
12580
+ async scanSkill(variables) {
12581
+ return await this._clientSdk.ScanSkill(variables);
12582
+ }
12548
12583
  };
12549
12584
 
12550
12585
  // src/mcp/services/types.ts
@@ -13150,7 +13185,7 @@ async function postIssueComment(params) {
13150
13185
  fpDescription
13151
13186
  } = params;
13152
13187
  const {
13153
- path: path25,
13188
+ path: path26,
13154
13189
  startLine,
13155
13190
  vulnerabilityReportIssue: {
13156
13191
  vulnerabilityReportIssueTags,
@@ -13165,7 +13200,7 @@ async function postIssueComment(params) {
13165
13200
  Refresh the page in order to see the changes.`,
13166
13201
  pull_number: pullRequest,
13167
13202
  commit_id: commitSha,
13168
- path: path25,
13203
+ path: path26,
13169
13204
  line: startLine
13170
13205
  });
13171
13206
  const commentId = commentRes.data.id;
@@ -13199,7 +13234,7 @@ async function postFixComment(params) {
13199
13234
  scanner
13200
13235
  } = params;
13201
13236
  const {
13202
- path: path25,
13237
+ path: path26,
13203
13238
  startLine,
13204
13239
  vulnerabilityReportIssue: { fixId, vulnerabilityReportIssueTags, category },
13205
13240
  vulnerabilityReportIssueId
@@ -13217,7 +13252,7 @@ async function postFixComment(params) {
13217
13252
  Refresh the page in order to see the changes.`,
13218
13253
  pull_number: pullRequest,
13219
13254
  commit_id: commitSha,
13220
- path: path25,
13255
+ path: path26,
13221
13256
  line: startLine
13222
13257
  });
13223
13258
  const commentId = commentRes.data.id;
@@ -14780,6 +14815,85 @@ async function waitForAnaysisAndReviewPr({
14780
14815
  }
14781
14816
  }
14782
14817
 
14818
+ // src/commands/scan_skill_input.ts
14819
+ import fs11 from "fs";
14820
+ import path10 from "path";
14821
+ import AdmZip2 from "adm-zip";
14822
+ var LOCAL_SKILL_ZIP_DATA_URL_PREFIX = "data:application/zip;base64,";
14823
+ var MAX_LOCAL_SKILL_ARCHIVE_BYTES = 2 * 1024 * 1024;
14824
+ async function resolveSkillScanInput(skillInput) {
14825
+ const resolvedPath = path10.resolve(skillInput);
14826
+ if (!fs11.existsSync(resolvedPath)) {
14827
+ return skillInput;
14828
+ }
14829
+ const stat = fs11.statSync(resolvedPath);
14830
+ if (!stat.isDirectory()) {
14831
+ throw new CliError(
14832
+ "Local skill input must be a directory containing SKILL.md"
14833
+ );
14834
+ }
14835
+ return packageLocalSkillDirectory(resolvedPath);
14836
+ }
14837
+ function packageLocalSkillDirectory(directoryPath) {
14838
+ const zip = new AdmZip2();
14839
+ const rootPath = path10.resolve(directoryPath);
14840
+ const filePaths = listDirectoryFiles(rootPath);
14841
+ let hasSkillMd = false;
14842
+ for (const relativePath of filePaths) {
14843
+ const fullPath = path10.join(rootPath, relativePath);
14844
+ const normalizedFullPath = path10.resolve(fullPath);
14845
+ if (normalizedFullPath !== rootPath && !normalizedFullPath.startsWith(rootPath + path10.sep)) {
14846
+ continue;
14847
+ }
14848
+ const fileContent = fs11.readFileSync(normalizedFullPath);
14849
+ zip.addFile(relativePath, fileContent);
14850
+ if (path10.basename(relativePath).toLowerCase() === "skill.md") {
14851
+ hasSkillMd = true;
14852
+ }
14853
+ }
14854
+ if (!hasSkillMd) {
14855
+ throw new CliError("Local skill directory must contain a SKILL.md file");
14856
+ }
14857
+ const zipBuffer = zip.toBuffer();
14858
+ if (zipBuffer.length > MAX_LOCAL_SKILL_ARCHIVE_BYTES) {
14859
+ throw new CliError(
14860
+ `Local skill directory is too large to scan via CLI (${zipBuffer.length} bytes > ${MAX_LOCAL_SKILL_ARCHIVE_BYTES} bytes)`
14861
+ );
14862
+ }
14863
+ return `${LOCAL_SKILL_ZIP_DATA_URL_PREFIX}${zipBuffer.toString("base64")}`;
14864
+ }
14865
+ function listDirectoryFiles(rootPath) {
14866
+ const files = [];
14867
+ function walk(relativeDir) {
14868
+ const absoluteDir = path10.join(rootPath, relativeDir);
14869
+ const entries = fs11.readdirSync(absoluteDir, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
14870
+ for (const entry of entries) {
14871
+ const safeEntryName = path10.basename(entry.name).replace(/\0/g, "");
14872
+ if (!safeEntryName) {
14873
+ continue;
14874
+ }
14875
+ const relativePath = relativeDir ? path10.posix.join(relativeDir, safeEntryName) : safeEntryName;
14876
+ const absolutePath = path10.join(rootPath, relativePath);
14877
+ const normalizedAbsolutePath = path10.resolve(absolutePath);
14878
+ if (normalizedAbsolutePath !== rootPath && !normalizedAbsolutePath.startsWith(rootPath + path10.sep)) {
14879
+ continue;
14880
+ }
14881
+ if (entry.isSymbolicLink()) {
14882
+ continue;
14883
+ }
14884
+ if (entry.isDirectory()) {
14885
+ walk(relativePath);
14886
+ continue;
14887
+ }
14888
+ if (entry.isFile()) {
14889
+ files.push(relativePath);
14890
+ }
14891
+ }
14892
+ }
14893
+ walk("");
14894
+ return files;
14895
+ }
14896
+
14783
14897
  // src/commands/index.ts
14784
14898
  async function review(params, { skipPrompts = true } = {}) {
14785
14899
  const {
@@ -14905,10 +15019,80 @@ async function showWelcomeMessage(skipPrompts = false) {
14905
15019
  skipPrompts ? await sleep(100) : await sleep(2e3);
14906
15020
  welcome.stop();
14907
15021
  }
15022
+ var VERDICT_COLORS = {
15023
+ BENIGN: "green",
15024
+ WARNING: "yellow",
15025
+ SUSPICIOUS: "magenta",
15026
+ MALICIOUS: "red"
15027
+ };
15028
+ var SEVERITY_COLORS = {
15029
+ CRITICAL: "red",
15030
+ HIGH: "magenta",
15031
+ MEDIUM: "yellow",
15032
+ LOW: "cyan"
15033
+ };
15034
+ async function scanSkill(options) {
15035
+ const { url, apiKey, ci } = options;
15036
+ const gqlClient = await getAuthenticatedGQLClient({
15037
+ inputApiKey: apiKey,
15038
+ isSkipPrompts: ci
15039
+ });
15040
+ console.log(chalk7.dim(`Scanning skill: ${url}`));
15041
+ console.log();
15042
+ const skillUrl = await resolveSkillScanInput(url);
15043
+ const result = await gqlClient.scanSkill({ skillUrl });
15044
+ const scan2 = result.scanSkill;
15045
+ const verdictColor = VERDICT_COLORS[scan2.verdict] ?? "white";
15046
+ console.log(
15047
+ chalk7.bold(`Verdict: `) + chalk7[verdictColor](
15048
+ scan2.verdict
15049
+ )
15050
+ );
15051
+ console.log(`Skill: ${scan2.skillName}`);
15052
+ if (scan2.skillVersion) {
15053
+ console.log(`Version: ${scan2.skillVersion}`);
15054
+ }
15055
+ console.log(`Hash: ${scan2.skillHash ?? "N/A"}`);
15056
+ console.log(`Findings: ${scan2.findingsCount}`);
15057
+ console.log(`Duration: ${scan2.scanDurationMs}ms`);
15058
+ if (scan2.cached) {
15059
+ console.log(chalk7.dim("(cached result)"));
15060
+ }
15061
+ console.log();
15062
+ if (scan2.findings.length > 0) {
15063
+ console.log(chalk7.bold("Findings:"));
15064
+ console.log();
15065
+ for (const f of scan2.findings) {
15066
+ const sevColor = SEVERITY_COLORS[f.severity] ?? "white";
15067
+ const location = [f.filePath, f.lineNumber].filter(Boolean).join(":");
15068
+ console.log(
15069
+ ` ${chalk7[sevColor](f.severity)} [${f.layer}] ${f.category}${f.ruleId ? ` (${f.ruleId})` : ""}`
15070
+ );
15071
+ if (location) {
15072
+ console.log(` ${chalk7.dim(location)}`);
15073
+ }
15074
+ console.log(` ${f.explanation}`);
15075
+ if (f.evidence) {
15076
+ console.log(
15077
+ ` ${String(chalk7.dim("Evidence: " + f.evidence.slice(0, 120))).replace(/\n|\r/g, "")}`
15078
+ );
15079
+ }
15080
+ console.log();
15081
+ }
15082
+ }
15083
+ if (scan2.summary) {
15084
+ console.log(chalk7.bold("Analysis:"));
15085
+ console.log(` ${scan2.summary}`);
15086
+ console.log();
15087
+ }
15088
+ if (scan2.verdict === "MALICIOUS" || scan2.verdict === "SUSPICIOUS") {
15089
+ process.exit(2);
15090
+ }
15091
+ }
14908
15092
 
14909
15093
  // src/args/validation.ts
14910
- import chalk7 from "chalk";
14911
- import path10 from "path";
15094
+ import chalk8 from "chalk";
15095
+ import path11 from "path";
14912
15096
  import { z as z30 } from "zod";
14913
15097
  function throwRepoUrlErrorMessage({
14914
15098
  error,
@@ -14917,11 +15101,11 @@ function throwRepoUrlErrorMessage({
14917
15101
  }) {
14918
15102
  const errorMessage = error.issues[error.issues.length - 1]?.message;
14919
15103
  const formattedErrorMessage = `
14920
- Error: ${chalk7.bold(
15104
+ Error: ${chalk8.bold(
14921
15105
  repoUrl
14922
15106
  )} is ${errorMessage}
14923
15107
  Example:
14924
- mobbdev ${command} -r ${chalk7.bold(
15108
+ mobbdev ${command} -r ${chalk8.bold(
14925
15109
  "https://github.com/WebGoat/WebGoat"
14926
15110
  )}`;
14927
15111
  throw new CliError(formattedErrorMessage);
@@ -14952,12 +15136,12 @@ function validateRepoUrl(args) {
14952
15136
  }
14953
15137
  var supportExtensions = [".json", ".xml", ".fpr", ".sarif", ".zip"];
14954
15138
  function validateReportFileFormat(reportFile) {
14955
- if (!supportExtensions.includes(path10.extname(reportFile))) {
15139
+ if (!supportExtensions.includes(path11.extname(reportFile))) {
14956
15140
  throw new CliError(
14957
15141
  `
14958
- ${chalk7.bold(
15142
+ ${chalk8.bold(
14959
15143
  reportFile
14960
- )} is not a supported file extension. Supported extensions are: ${chalk7.bold(
15144
+ )} is not a supported file extension. Supported extensions are: ${chalk8.bold(
14961
15145
  supportExtensions.join(", ")
14962
15146
  )}
14963
15147
  `
@@ -14970,22 +15154,22 @@ function analyzeBuilder(yargs2) {
14970
15154
  return yargs2.option("f", {
14971
15155
  alias: "scan-file",
14972
15156
  type: "string",
14973
- describe: chalk8.bold(
15157
+ describe: chalk9.bold(
14974
15158
  "Select the vulnerability report to analyze (Checkmarx, Snyk, Fortify, CodeQL, Sonarqube, Semgrep, Datadog)"
14975
15159
  )
14976
15160
  }).option("repo", repoOption).option("p", {
14977
15161
  alias: "src-path",
14978
- describe: chalk8.bold(
15162
+ describe: chalk9.bold(
14979
15163
  "Path to the repository folder with the source code; alternatively, you can specify the Fortify FPR file to extract source code out of it"
14980
15164
  ),
14981
15165
  type: "string"
14982
15166
  }).option("ref", refOption).option("ch", {
14983
15167
  alias: "commit-hash",
14984
- describe: chalk8.bold("Hash of the commit"),
15168
+ describe: chalk9.bold("Hash of the commit"),
14985
15169
  type: "string"
14986
15170
  }).option("mobb-project-name", mobbProjectNameOption).option("y", yesOption).option("ci", ciOption).option("org", organizationIdOptions).option("api-key", apiKeyOption).option("commit-hash", commitHashOption).option("auto-pr", autoPrOption).option("create-one-pr", createOnePrOption).option("commit-directly", commitDirectlyOption).option("pull-request", {
14987
15171
  alias: ["pr", "pr-number", "pr-id"],
14988
- describe: chalk8.bold("Number of the pull request"),
15172
+ describe: chalk9.bold("Number of the pull request"),
14989
15173
  type: "number",
14990
15174
  demandOption: false
14991
15175
  }).option("polling", pollingOption).example(
@@ -14994,9 +15178,9 @@ function analyzeBuilder(yargs2) {
14994
15178
  ).help();
14995
15179
  }
14996
15180
  function validateAnalyzeOptions(argv) {
14997
- if (argv.f && !fs11.existsSync(argv.f)) {
15181
+ if (argv.f && !fs12.existsSync(argv.f)) {
14998
15182
  throw new CliError(`
14999
- Can't access ${chalk8.bold(argv.f)}`);
15183
+ Can't access ${chalk9.bold(argv.f)}`);
15000
15184
  }
15001
15185
  validateOrganizationId(argv.organizationId);
15002
15186
  if (!argv.srcPath && !argv.repo) {
@@ -15043,8 +15227,8 @@ import { z as z32 } from "zod";
15043
15227
  // src/args/commands/upload_ai_blame.ts
15044
15228
  import fsPromises3 from "fs/promises";
15045
15229
  import * as os3 from "os";
15046
- import path11 from "path";
15047
- import chalk9 from "chalk";
15230
+ import path12 from "path";
15231
+ import chalk10 from "chalk";
15048
15232
  import { withFile } from "tmp-promise";
15049
15233
  import z31 from "zod";
15050
15234
  init_client_generates();
@@ -15364,33 +15548,33 @@ function uploadAiBlameBuilder(args) {
15364
15548
  type: "string",
15365
15549
  array: true,
15366
15550
  demandOption: true,
15367
- describe: chalk9.bold("Path(s) to prompt artifact(s) (one per session)")
15551
+ describe: chalk10.bold("Path(s) to prompt artifact(s) (one per session)")
15368
15552
  }).option("inference", {
15369
15553
  type: "string",
15370
15554
  array: true,
15371
15555
  demandOption: true,
15372
- describe: chalk9.bold(
15556
+ describe: chalk10.bold(
15373
15557
  "Path(s) to inference artifact(s) (one per session)"
15374
15558
  )
15375
15559
  }).option("ai-response-at", {
15376
15560
  type: "string",
15377
15561
  array: true,
15378
- describe: chalk9.bold(
15562
+ describe: chalk10.bold(
15379
15563
  "ISO timestamp(s) for AI response (one per session, defaults to now)"
15380
15564
  )
15381
15565
  }).option("model", {
15382
15566
  type: "string",
15383
15567
  array: true,
15384
- describe: chalk9.bold("AI model name(s) (optional, one per session)")
15568
+ describe: chalk10.bold("AI model name(s) (optional, one per session)")
15385
15569
  }).option("tool-name", {
15386
15570
  type: "string",
15387
15571
  array: true,
15388
- describe: chalk9.bold("Tool/IDE name(s) (optional, one per session)")
15572
+ describe: chalk10.bold("Tool/IDE name(s) (optional, one per session)")
15389
15573
  }).option("blame-type", {
15390
15574
  type: "string",
15391
15575
  array: true,
15392
15576
  choices: Object.values(AiBlameInferenceType),
15393
- describe: chalk9.bold(
15577
+ describe: chalk10.bold(
15394
15578
  "Blame type(s) (optional, one per session, defaults to CHAT)"
15395
15579
  )
15396
15580
  }).strict();
@@ -15412,7 +15596,7 @@ async function uploadAiBlameHandlerFromExtension(args) {
15412
15596
  await withFile(async (promptFile) => {
15413
15597
  const promptsResult = await sanitizeDataWithCounts(args.prompts);
15414
15598
  promptsCounts = promptsResult.counts;
15415
- promptsUUID = path11.basename(promptFile.path, path11.extname(promptFile.path));
15599
+ promptsUUID = path12.basename(promptFile.path, path12.extname(promptFile.path));
15416
15600
  await fsPromises3.writeFile(
15417
15601
  promptFile.path,
15418
15602
  JSON.stringify(promptsResult.sanitizedData, null, 2),
@@ -15422,9 +15606,9 @@ async function uploadAiBlameHandlerFromExtension(args) {
15422
15606
  await withFile(async (inferenceFile) => {
15423
15607
  const inferenceResult = await sanitizeDataWithCounts(args.inference);
15424
15608
  inferenceCounts = inferenceResult.counts;
15425
- inferenceUUID = path11.basename(
15609
+ inferenceUUID = path12.basename(
15426
15610
  inferenceFile.path,
15427
- path11.extname(inferenceFile.path)
15611
+ path12.extname(inferenceFile.path)
15428
15612
  );
15429
15613
  await fsPromises3.writeFile(
15430
15614
  inferenceFile.path,
@@ -15472,7 +15656,7 @@ async function uploadAiBlameHandler(options) {
15472
15656
  const sessionIds = args.sessionId || args["session-id"] || [];
15473
15657
  if (prompts.length !== inferences.length) {
15474
15658
  const errorMsg = "prompt and inference must have the same number of entries";
15475
- logger2.error(chalk9.red(errorMsg));
15659
+ logger2.error(chalk10.red(errorMsg));
15476
15660
  if (exitOnError) {
15477
15661
  process.exit(1);
15478
15662
  }
@@ -15492,15 +15676,15 @@ async function uploadAiBlameHandler(options) {
15492
15676
  ]);
15493
15677
  } catch {
15494
15678
  const errorMsg = `File not found for session ${i + 1}`;
15495
- logger2.error(chalk9.red(errorMsg));
15679
+ logger2.error(chalk10.red(errorMsg));
15496
15680
  if (exitOnError) {
15497
15681
  process.exit(1);
15498
15682
  }
15499
15683
  throw new Error(errorMsg);
15500
15684
  }
15501
15685
  sessions.push({
15502
- promptFileName: path11.basename(promptPath),
15503
- inferenceFileName: path11.basename(inferencePath),
15686
+ promptFileName: path12.basename(promptPath),
15687
+ inferenceFileName: path12.basename(inferencePath),
15504
15688
  aiResponseAt: responseTimes[i] || nowIso,
15505
15689
  model: models[i],
15506
15690
  toolName: tools[i],
@@ -15525,7 +15709,7 @@ async function uploadAiBlameHandler(options) {
15525
15709
  const uploadSessions = initRes.uploadAIBlameInferencesInit?.uploadSessions ?? [];
15526
15710
  if (uploadSessions.length !== sessions.length) {
15527
15711
  const errorMsg = "Init failed to return expected number of sessions";
15528
- logger2.error(chalk9.red(errorMsg));
15712
+ logger2.error(chalk10.red(errorMsg));
15529
15713
  if (exitOnError) {
15530
15714
  process.exit(1);
15531
15715
  }
@@ -15582,7 +15766,7 @@ async function uploadAiBlameHandler(options) {
15582
15766
  if (status !== "OK") {
15583
15767
  const errorMsg = finRes?.finalizeAIBlameInferencesUpload?.error || "unknown error";
15584
15768
  logger2.error(
15585
- chalk9.red(
15769
+ chalk10.red(
15586
15770
  `[UPLOAD] Finalize failed with status: ${status}, error: ${errorMsg}`
15587
15771
  )
15588
15772
  );
@@ -15591,7 +15775,7 @@ async function uploadAiBlameHandler(options) {
15591
15775
  }
15592
15776
  throw new Error(errorMsg);
15593
15777
  }
15594
- logger2.info(chalk9.green("[UPLOAD] AI Blame uploads finalized successfully"));
15778
+ logger2.info(chalk10.green("[UPLOAD] AI Blame uploads finalized successfully"));
15595
15779
  } catch (error) {
15596
15780
  logger2.error("[UPLOAD] Finalize threw error:", error);
15597
15781
  throw error;
@@ -15603,6 +15787,8 @@ async function uploadAiBlameCommandHandler(args) {
15603
15787
 
15604
15788
  // src/features/claude_code/data_collector.ts
15605
15789
  init_client_generates();
15790
+ init_GitService();
15791
+ init_urlParser2();
15606
15792
 
15607
15793
  // src/features/claude_code/transcript_parser.ts
15608
15794
  import fsPromises4 from "fs/promises";
@@ -15849,8 +16035,23 @@ async function collectHookData() {
15849
16035
  tracePayload
15850
16036
  };
15851
16037
  }
16038
+ async function getRepositoryUrl2(cwd) {
16039
+ try {
16040
+ const gitService = new GitService(cwd);
16041
+ const isRepo = await gitService.isGitRepository();
16042
+ if (!isRepo) {
16043
+ return null;
16044
+ }
16045
+ const remoteUrl = await gitService.getRemoteUrl();
16046
+ const parsed = parseScmURL(remoteUrl);
16047
+ return parsed?.scmType === "GitHub" /* GitHub */ || parsed?.scmType === "GitLab" /* GitLab */ ? remoteUrl : null;
16048
+ } catch {
16049
+ return null;
16050
+ }
16051
+ }
15852
16052
  async function processAndUploadHookData() {
15853
16053
  const result = await collectHookData();
16054
+ const repositoryUrl = await getRepositoryUrl2(result.hookData.cwd);
15854
16055
  let uploadSuccess;
15855
16056
  try {
15856
16057
  await uploadAiBlameHandlerFromExtension({
@@ -15860,7 +16061,8 @@ async function processAndUploadHookData() {
15860
16061
  tool: result.tracePayload.tool,
15861
16062
  responseTime: result.tracePayload.responseTime,
15862
16063
  blameType: "CHAT" /* Chat */,
15863
- sessionId: result.hookData.session_id
16064
+ sessionId: result.hookData.session_id,
16065
+ repositoryUrl
15864
16066
  });
15865
16067
  uploadSuccess = true;
15866
16068
  } catch (error) {
@@ -15879,9 +16081,9 @@ async function processAndUploadHookData() {
15879
16081
  // src/features/claude_code/install_hook.ts
15880
16082
  import fsPromises5 from "fs/promises";
15881
16083
  import os4 from "os";
15882
- import path12 from "path";
15883
- import chalk10 from "chalk";
15884
- var CLAUDE_SETTINGS_PATH = path12.join(os4.homedir(), ".claude", "settings.json");
16084
+ import path13 from "path";
16085
+ import chalk11 from "chalk";
16086
+ var CLAUDE_SETTINGS_PATH = path13.join(os4.homedir(), ".claude", "settings.json");
15885
16087
  async function claudeSettingsExists() {
15886
16088
  try {
15887
16089
  await fsPromises5.access(CLAUDE_SETTINGS_PATH);
@@ -15905,12 +16107,12 @@ async function writeClaudeSettings(settings) {
15905
16107
  );
15906
16108
  }
15907
16109
  async function installMobbHooks(options = {}) {
15908
- console.log(chalk10.blue("Installing Mobb hooks in Claude Code settings..."));
16110
+ console.log(chalk11.blue("Installing Mobb hooks in Claude Code settings..."));
15909
16111
  if (!await claudeSettingsExists()) {
15910
- console.log(chalk10.red("\u274C Claude Code settings file not found"));
15911
- console.log(chalk10.yellow(`Expected location: ${CLAUDE_SETTINGS_PATH}`));
15912
- console.log(chalk10.yellow("Is Claude Code installed on your system?"));
15913
- console.log(chalk10.yellow("Please install Claude Code and try again."));
16112
+ console.log(chalk11.red("\u274C Claude Code settings file not found"));
16113
+ console.log(chalk11.yellow(`Expected location: ${CLAUDE_SETTINGS_PATH}`));
16114
+ console.log(chalk11.yellow("Is Claude Code installed on your system?"));
16115
+ console.log(chalk11.yellow("Please install Claude Code and try again."));
15914
16116
  throw new Error(
15915
16117
  "Claude Code settings file not found. Is Claude Code installed?"
15916
16118
  );
@@ -15934,7 +16136,7 @@ async function installMobbHooks(options = {}) {
15934
16136
  if (envVars.length > 0) {
15935
16137
  command = `${envVars.join(" ")} ${command}`;
15936
16138
  console.log(
15937
- chalk10.blue(
16139
+ chalk11.blue(
15938
16140
  `Adding environment variables to hook command: ${envVars.join(", ")}`
15939
16141
  )
15940
16142
  );
@@ -15955,15 +16157,15 @@ async function installMobbHooks(options = {}) {
15955
16157
  )
15956
16158
  );
15957
16159
  if (existingHookIndex >= 0) {
15958
- console.log(chalk10.yellow("Mobb hook already exists, updating..."));
16160
+ console.log(chalk11.yellow("Mobb hook already exists, updating..."));
15959
16161
  settings.hooks.PostToolUse[existingHookIndex] = mobbHookConfig;
15960
16162
  } else {
15961
- console.log(chalk10.green("Adding new Mobb hook..."));
16163
+ console.log(chalk11.green("Adding new Mobb hook..."));
15962
16164
  settings.hooks.PostToolUse.push(mobbHookConfig);
15963
16165
  }
15964
16166
  await writeClaudeSettings(settings);
15965
16167
  console.log(
15966
- chalk10.green(
16168
+ chalk11.green(
15967
16169
  `\u2705 Mobb hooks ${options.saveEnv ? "and environment variables " : ""}installed successfully in ${CLAUDE_SETTINGS_PATH}`
15968
16170
  )
15969
16171
  );
@@ -16066,8 +16268,8 @@ var WorkspaceService = class {
16066
16268
  * Sets a known workspace path that was discovered through successful validation
16067
16269
  * @param path The validated workspace path to store
16068
16270
  */
16069
- static setKnownWorkspacePath(path25) {
16070
- this.knownWorkspacePath = path25;
16271
+ static setKnownWorkspacePath(path26) {
16272
+ this.knownWorkspacePath = path26;
16071
16273
  }
16072
16274
  /**
16073
16275
  * Gets the known workspace path that was previously validated
@@ -17097,9 +17299,9 @@ async function createAuthenticatedMcpGQLClient({
17097
17299
 
17098
17300
  // src/mcp/services/McpUsageService/host.ts
17099
17301
  import { execSync as execSync2 } from "child_process";
17100
- import fs12 from "fs";
17302
+ import fs13 from "fs";
17101
17303
  import os6 from "os";
17102
- import path13 from "path";
17304
+ import path14 from "path";
17103
17305
  var IDEs = ["cursor", "windsurf", "webstorm", "vscode", "claude"];
17104
17306
  var runCommand = (cmd) => {
17105
17307
  try {
@@ -17114,17 +17316,17 @@ var gitInfo = {
17114
17316
  };
17115
17317
  var getClaudeWorkspacePaths = () => {
17116
17318
  const home = os6.homedir();
17117
- const claudeIdePath = path13.join(home, ".claude", "ide");
17319
+ const claudeIdePath = path14.join(home, ".claude", "ide");
17118
17320
  const workspacePaths = [];
17119
- if (!fs12.existsSync(claudeIdePath)) {
17321
+ if (!fs13.existsSync(claudeIdePath)) {
17120
17322
  return workspacePaths;
17121
17323
  }
17122
17324
  try {
17123
- const lockFiles = fs12.readdirSync(claudeIdePath).filter((file) => file.endsWith(".lock"));
17325
+ const lockFiles = fs13.readdirSync(claudeIdePath).filter((file) => file.endsWith(".lock"));
17124
17326
  for (const lockFile of lockFiles) {
17125
- const lockFilePath = path13.join(claudeIdePath, lockFile);
17327
+ const lockFilePath = path14.join(claudeIdePath, lockFile);
17126
17328
  try {
17127
- const lockContent = JSON.parse(fs12.readFileSync(lockFilePath, "utf8"));
17329
+ const lockContent = JSON.parse(fs13.readFileSync(lockFilePath, "utf8"));
17128
17330
  if (lockContent.workspaceFolders && Array.isArray(lockContent.workspaceFolders)) {
17129
17331
  workspacePaths.push(...lockContent.workspaceFolders);
17130
17332
  }
@@ -17147,24 +17349,24 @@ var getMCPConfigPaths = (hostName) => {
17147
17349
  switch (hostName.toLowerCase()) {
17148
17350
  case "cursor":
17149
17351
  return [
17150
- path13.join(currentDir, ".cursor", "mcp.json"),
17352
+ path14.join(currentDir, ".cursor", "mcp.json"),
17151
17353
  // local first
17152
- path13.join(home, ".cursor", "mcp.json")
17354
+ path14.join(home, ".cursor", "mcp.json")
17153
17355
  ];
17154
17356
  case "windsurf":
17155
17357
  return [
17156
- path13.join(currentDir, ".codeium", "mcp_config.json"),
17358
+ path14.join(currentDir, ".codeium", "mcp_config.json"),
17157
17359
  // local first
17158
- path13.join(home, ".codeium", "windsurf", "mcp_config.json")
17360
+ path14.join(home, ".codeium", "windsurf", "mcp_config.json")
17159
17361
  ];
17160
17362
  case "webstorm":
17161
17363
  return [];
17162
17364
  case "visualstudiocode":
17163
17365
  case "vscode":
17164
17366
  return [
17165
- path13.join(currentDir, ".vscode", "mcp.json"),
17367
+ path14.join(currentDir, ".vscode", "mcp.json"),
17166
17368
  // local first
17167
- process.platform === "win32" ? path13.join(home, "AppData", "Roaming", "Code", "User", "mcp.json") : path13.join(
17369
+ process.platform === "win32" ? path14.join(home, "AppData", "Roaming", "Code", "User", "mcp.json") : path14.join(
17168
17370
  home,
17169
17371
  "Library",
17170
17372
  "Application Support",
@@ -17175,13 +17377,13 @@ var getMCPConfigPaths = (hostName) => {
17175
17377
  ];
17176
17378
  case "claude": {
17177
17379
  const claudePaths = [
17178
- path13.join(currentDir, ".claude.json"),
17380
+ path14.join(currentDir, ".claude.json"),
17179
17381
  // local first
17180
- path13.join(home, ".claude.json")
17382
+ path14.join(home, ".claude.json")
17181
17383
  ];
17182
17384
  const workspacePaths = getClaudeWorkspacePaths();
17183
17385
  for (const workspacePath of workspacePaths) {
17184
- claudePaths.push(path13.join(workspacePath, ".mcp.json"));
17386
+ claudePaths.push(path14.join(workspacePath, ".mcp.json"));
17185
17387
  }
17186
17388
  return claudePaths;
17187
17389
  }
@@ -17190,9 +17392,9 @@ var getMCPConfigPaths = (hostName) => {
17190
17392
  }
17191
17393
  };
17192
17394
  var readConfigFile = (filePath) => {
17193
- if (!fs12.existsSync(filePath)) return null;
17395
+ if (!fs13.existsSync(filePath)) return null;
17194
17396
  try {
17195
- return JSON.parse(fs12.readFileSync(filePath, "utf8"));
17397
+ return JSON.parse(fs13.readFileSync(filePath, "utf8"));
17196
17398
  } catch (error) {
17197
17399
  logWarn(`[UsageService] Failed to read MCP config: ${filePath}`);
17198
17400
  return null;
@@ -17342,10 +17544,10 @@ var getHostInfo = (additionalMcpList) => {
17342
17544
  const ideConfigPaths = /* @__PURE__ */ new Set();
17343
17545
  for (const ide of IDEs) {
17344
17546
  const configPaths = getMCPConfigPaths(ide);
17345
- configPaths.forEach((path25) => ideConfigPaths.add(path25));
17547
+ configPaths.forEach((path26) => ideConfigPaths.add(path26));
17346
17548
  }
17347
17549
  const uniqueAdditionalPaths = additionalMcpList.filter(
17348
- (path25) => !ideConfigPaths.has(path25)
17550
+ (path26) => !ideConfigPaths.has(path26)
17349
17551
  );
17350
17552
  for (const ide of IDEs) {
17351
17553
  const cfg = readMCPConfig(ide);
@@ -17465,9 +17667,9 @@ init_configs();
17465
17667
 
17466
17668
  // src/mcp/services/McpUsageService/system.ts
17467
17669
  init_configs();
17468
- import fs13 from "fs";
17670
+ import fs14 from "fs";
17469
17671
  import os7 from "os";
17470
- import path14 from "path";
17672
+ import path15 from "path";
17471
17673
  var MAX_DEPTH = 2;
17472
17674
  var patterns = ["mcp", "claude"];
17473
17675
  var isFileMatch = (fileName) => {
@@ -17476,7 +17678,7 @@ var isFileMatch = (fileName) => {
17476
17678
  };
17477
17679
  var safeAccess = async (filePath) => {
17478
17680
  try {
17479
- await fs13.promises.access(filePath, fs13.constants.R_OK);
17681
+ await fs14.promises.access(filePath, fs14.constants.R_OK);
17480
17682
  return true;
17481
17683
  } catch {
17482
17684
  return false;
@@ -17485,9 +17687,9 @@ var safeAccess = async (filePath) => {
17485
17687
  var searchDir = async (dir, depth = 0) => {
17486
17688
  const results = [];
17487
17689
  if (depth > MAX_DEPTH) return results;
17488
- const entries = await fs13.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
17690
+ const entries = await fs14.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
17489
17691
  for (const entry of entries) {
17490
- const fullPath = path14.join(dir, entry.name);
17692
+ const fullPath = path15.join(dir, entry.name);
17491
17693
  if (entry.isFile() && isFileMatch(entry.name)) {
17492
17694
  results.push(fullPath);
17493
17695
  } else if (entry.isDirectory()) {
@@ -17504,14 +17706,14 @@ var findSystemMCPConfigs = async () => {
17504
17706
  const home = os7.homedir();
17505
17707
  const platform2 = os7.platform();
17506
17708
  const knownDirs = platform2 === "win32" ? [
17507
- path14.join(home, ".cursor"),
17508
- path14.join(home, "Documents"),
17509
- path14.join(home, "Downloads")
17709
+ path15.join(home, ".cursor"),
17710
+ path15.join(home, "Documents"),
17711
+ path15.join(home, "Downloads")
17510
17712
  ] : [
17511
- path14.join(home, ".cursor"),
17512
- process.env["XDG_CONFIG_HOME"] || path14.join(home, ".config"),
17513
- path14.join(home, "Documents"),
17514
- path14.join(home, "Downloads")
17713
+ path15.join(home, ".cursor"),
17714
+ process.env["XDG_CONFIG_HOME"] || path15.join(home, ".config"),
17715
+ path15.join(home, "Documents"),
17716
+ path15.join(home, "Downloads")
17515
17717
  ];
17516
17718
  const timeoutPromise = new Promise(
17517
17719
  (resolve) => setTimeout(() => {
@@ -17523,7 +17725,7 @@ var findSystemMCPConfigs = async () => {
17523
17725
  );
17524
17726
  const searchPromise = Promise.all(
17525
17727
  knownDirs.map(
17526
- (dir) => fs13.existsSync(dir) ? searchDir(dir) : Promise.resolve([])
17728
+ (dir) => fs14.existsSync(dir) ? searchDir(dir) : Promise.resolve([])
17527
17729
  )
17528
17730
  ).then((results) => results.flat());
17529
17731
  return await Promise.race([timeoutPromise, searchPromise]);
@@ -19925,31 +20127,31 @@ For a complete security audit workflow, use the \`full-security-audit\` prompt.
19925
20127
  };
19926
20128
 
19927
20129
  // src/mcp/services/McpDetectionService/CursorMcpDetectionService.ts
19928
- import * as fs16 from "fs";
20130
+ import * as fs17 from "fs";
19929
20131
  import * as os10 from "os";
19930
- import * as path16 from "path";
20132
+ import * as path17 from "path";
19931
20133
 
19932
20134
  // src/mcp/services/McpDetectionService/BaseMcpDetectionService.ts
19933
20135
  init_configs();
19934
- import * as fs15 from "fs";
20136
+ import * as fs16 from "fs";
19935
20137
  import fetch6 from "node-fetch";
19936
- import * as path15 from "path";
20138
+ import * as path16 from "path";
19937
20139
 
19938
20140
  // src/mcp/services/McpDetectionService/McpDetectionServiceUtils.ts
19939
- import * as fs14 from "fs";
20141
+ import * as fs15 from "fs";
19940
20142
  import * as os9 from "os";
19941
20143
 
19942
20144
  // src/mcp/services/McpDetectionService/VscodeMcpDetectionService.ts
19943
- import * as fs17 from "fs";
20145
+ import * as fs18 from "fs";
19944
20146
  import * as os11 from "os";
19945
- import * as path17 from "path";
20147
+ import * as path18 from "path";
19946
20148
 
19947
20149
  // src/mcp/tools/checkForNewAvailableFixes/CheckForNewAvailableFixesTool.ts
19948
20150
  import { z as z42 } from "zod";
19949
20151
 
19950
20152
  // src/mcp/services/PathValidation.ts
19951
- import fs18 from "fs";
19952
- import path18 from "path";
20153
+ import fs19 from "fs";
20154
+ import path19 from "path";
19953
20155
  async function validatePath(inputPath) {
19954
20156
  logDebug("Validating MCP path", { inputPath });
19955
20157
  if (/^\/[a-zA-Z]:\//.test(inputPath)) {
@@ -19981,7 +20183,7 @@ async function validatePath(inputPath) {
19981
20183
  logError(error);
19982
20184
  return { isValid: false, error, path: inputPath };
19983
20185
  }
19984
- const normalizedPath = path18.normalize(inputPath);
20186
+ const normalizedPath = path19.normalize(inputPath);
19985
20187
  if (normalizedPath.includes("..")) {
19986
20188
  const error = `Normalized path contains path traversal patterns: ${inputPath}`;
19987
20189
  logError(error);
@@ -20008,7 +20210,7 @@ async function validatePath(inputPath) {
20008
20210
  logDebug("Path validation successful", { inputPath });
20009
20211
  logDebug("Checking path existence", { inputPath });
20010
20212
  try {
20011
- await fs18.promises.access(inputPath);
20213
+ await fs19.promises.access(inputPath);
20012
20214
  logDebug("Path exists and is accessible", { inputPath });
20013
20215
  WorkspaceService.setKnownWorkspacePath(inputPath);
20014
20216
  logDebug("Stored validated path in WorkspaceService", { inputPath });
@@ -20636,10 +20838,10 @@ If you wish to scan files that were recently changed in your git history call th
20636
20838
  init_FileUtils();
20637
20839
  init_GitService();
20638
20840
  init_configs();
20639
- import fs19 from "fs/promises";
20841
+ import fs20 from "fs/promises";
20640
20842
  import nodePath from "path";
20641
20843
  var getLocalFiles = async ({
20642
- path: path25,
20844
+ path: path26,
20643
20845
  maxFileSize = MCP_MAX_FILE_SIZE,
20644
20846
  maxFiles,
20645
20847
  isAllFilesScan,
@@ -20647,17 +20849,17 @@ var getLocalFiles = async ({
20647
20849
  scanRecentlyChangedFiles
20648
20850
  }) => {
20649
20851
  logDebug(`[${scanContext}] Starting getLocalFiles`, {
20650
- path: path25,
20852
+ path: path26,
20651
20853
  maxFileSize,
20652
20854
  maxFiles,
20653
20855
  isAllFilesScan,
20654
20856
  scanRecentlyChangedFiles
20655
20857
  });
20656
20858
  try {
20657
- const resolvedRepoPath = await fs19.realpath(path25);
20859
+ const resolvedRepoPath = await fs20.realpath(path26);
20658
20860
  logDebug(`[${scanContext}] Resolved repository path`, {
20659
20861
  resolvedRepoPath,
20660
- originalPath: path25
20862
+ originalPath: path26
20661
20863
  });
20662
20864
  const gitService = new GitService(resolvedRepoPath, log);
20663
20865
  const gitValidation = await gitService.validateRepository();
@@ -20670,7 +20872,7 @@ var getLocalFiles = async ({
20670
20872
  if (!gitValidation.isValid || isAllFilesScan) {
20671
20873
  try {
20672
20874
  files = await FileUtils.getLastChangedFiles({
20673
- dir: path25,
20875
+ dir: path26,
20674
20876
  maxFileSize,
20675
20877
  maxFiles,
20676
20878
  isAllFilesScan
@@ -20734,7 +20936,7 @@ var getLocalFiles = async ({
20734
20936
  absoluteFilePath
20735
20937
  );
20736
20938
  try {
20737
- const fileStat = await fs19.stat(absoluteFilePath);
20939
+ const fileStat = await fs20.stat(absoluteFilePath);
20738
20940
  return {
20739
20941
  filename: nodePath.basename(absoluteFilePath),
20740
20942
  relativePath,
@@ -20762,7 +20964,7 @@ var getLocalFiles = async ({
20762
20964
  logError(`${scanContext}Unexpected error in getLocalFiles`, {
20763
20965
  error: error instanceof Error ? error.message : String(error),
20764
20966
  stack: error instanceof Error ? error.stack : void 0,
20765
- path: path25
20967
+ path: path26
20766
20968
  });
20767
20969
  throw error;
20768
20970
  }
@@ -20771,8 +20973,8 @@ var getLocalFiles = async ({
20771
20973
  // src/mcp/services/LocalMobbFolderService.ts
20772
20974
  init_client_generates();
20773
20975
  init_GitService();
20774
- import fs20 from "fs";
20775
- import path19 from "path";
20976
+ import fs21 from "fs";
20977
+ import path20 from "path";
20776
20978
  import { z as z41 } from "zod";
20777
20979
  function extractPathFromPatch(patch) {
20778
20980
  const match = patch?.match(/diff --git a\/([^\s]+) b\//);
@@ -20858,19 +21060,19 @@ var LocalMobbFolderService = class {
20858
21060
  "[LocalMobbFolderService] Non-git repository detected, skipping .gitignore operations"
20859
21061
  );
20860
21062
  }
20861
- const mobbFolderPath = path19.join(
21063
+ const mobbFolderPath = path20.join(
20862
21064
  this.repoPath,
20863
21065
  this.defaultMobbFolderName
20864
21066
  );
20865
- if (!fs20.existsSync(mobbFolderPath)) {
21067
+ if (!fs21.existsSync(mobbFolderPath)) {
20866
21068
  logInfo("[LocalMobbFolderService] Creating .mobb folder", {
20867
21069
  mobbFolderPath
20868
21070
  });
20869
- fs20.mkdirSync(mobbFolderPath, { recursive: true });
21071
+ fs21.mkdirSync(mobbFolderPath, { recursive: true });
20870
21072
  } else {
20871
21073
  logDebug("[LocalMobbFolderService] .mobb folder already exists");
20872
21074
  }
20873
- const stats = fs20.statSync(mobbFolderPath);
21075
+ const stats = fs21.statSync(mobbFolderPath);
20874
21076
  if (!stats.isDirectory()) {
20875
21077
  throw new Error(`Path exists but is not a directory: ${mobbFolderPath}`);
20876
21078
  }
@@ -20911,13 +21113,13 @@ var LocalMobbFolderService = class {
20911
21113
  logDebug("[LocalMobbFolderService] Git repository validated successfully");
20912
21114
  } else {
20913
21115
  try {
20914
- const stats = fs20.statSync(this.repoPath);
21116
+ const stats = fs21.statSync(this.repoPath);
20915
21117
  if (!stats.isDirectory()) {
20916
21118
  throw new Error(
20917
21119
  `Path exists but is not a directory: ${this.repoPath}`
20918
21120
  );
20919
21121
  }
20920
- fs20.accessSync(this.repoPath, fs20.constants.R_OK | fs20.constants.W_OK);
21122
+ fs21.accessSync(this.repoPath, fs21.constants.R_OK | fs21.constants.W_OK);
20921
21123
  logDebug(
20922
21124
  "[LocalMobbFolderService] Non-git directory validated successfully"
20923
21125
  );
@@ -21030,8 +21232,8 @@ var LocalMobbFolderService = class {
21030
21232
  mobbFolderPath,
21031
21233
  baseFileName
21032
21234
  );
21033
- const filePath = path19.join(mobbFolderPath, uniqueFileName);
21034
- await fs20.promises.writeFile(filePath, patch, "utf8");
21235
+ const filePath = path20.join(mobbFolderPath, uniqueFileName);
21236
+ await fs21.promises.writeFile(filePath, patch, "utf8");
21035
21237
  logInfo("[LocalMobbFolderService] Patch saved successfully", {
21036
21238
  filePath,
21037
21239
  fileName: uniqueFileName,
@@ -21088,11 +21290,11 @@ var LocalMobbFolderService = class {
21088
21290
  * @returns Unique filename that doesn't conflict with existing files
21089
21291
  */
21090
21292
  getUniqueFileName(folderPath, baseFileName) {
21091
- const baseName = path19.parse(baseFileName).name;
21092
- const extension = path19.parse(baseFileName).ext;
21293
+ const baseName = path20.parse(baseFileName).name;
21294
+ const extension = path20.parse(baseFileName).ext;
21093
21295
  let uniqueFileName = baseFileName;
21094
21296
  let index = 1;
21095
- while (fs20.existsSync(path19.join(folderPath, uniqueFileName))) {
21297
+ while (fs21.existsSync(path20.join(folderPath, uniqueFileName))) {
21096
21298
  uniqueFileName = `${baseName}-${index}${extension}`;
21097
21299
  index++;
21098
21300
  if (index > 1e3) {
@@ -21123,18 +21325,18 @@ var LocalMobbFolderService = class {
21123
21325
  logDebug("[LocalMobbFolderService] Logging patch info", { fixId: fix.id });
21124
21326
  try {
21125
21327
  const mobbFolderPath = await this.getFolder();
21126
- const patchInfoPath = path19.join(mobbFolderPath, "patchInfo.md");
21328
+ const patchInfoPath = path20.join(mobbFolderPath, "patchInfo.md");
21127
21329
  const markdownContent = this.generateFixMarkdown(fix, savedPatchFileName);
21128
21330
  let existingContent = "";
21129
- if (fs20.existsSync(patchInfoPath)) {
21130
- existingContent = await fs20.promises.readFile(patchInfoPath, "utf8");
21331
+ if (fs21.existsSync(patchInfoPath)) {
21332
+ existingContent = await fs21.promises.readFile(patchInfoPath, "utf8");
21131
21333
  logDebug("[LocalMobbFolderService] Existing patchInfo.md found");
21132
21334
  } else {
21133
21335
  logDebug("[LocalMobbFolderService] Creating new patchInfo.md file");
21134
21336
  }
21135
21337
  const separator = existingContent ? "\n\n================================================================================\n\n" : "";
21136
21338
  const updatedContent = `${markdownContent}${separator}${existingContent}`;
21137
- await fs20.promises.writeFile(patchInfoPath, updatedContent, "utf8");
21339
+ await fs21.promises.writeFile(patchInfoPath, updatedContent, "utf8");
21138
21340
  logInfo("[LocalMobbFolderService] Patch info logged successfully", {
21139
21341
  patchInfoPath,
21140
21342
  fixId: fix.id,
@@ -21165,7 +21367,7 @@ var LocalMobbFolderService = class {
21165
21367
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
21166
21368
  const patch = this.extractPatchFromFix(fix);
21167
21369
  const relativePatchedFilePath = patch ? extractPathFromPatch(patch) : null;
21168
- const patchedFilePath = relativePatchedFilePath ? path19.resolve(this.repoPath, relativePatchedFilePath) : null;
21370
+ const patchedFilePath = relativePatchedFilePath ? path20.resolve(this.repoPath, relativePatchedFilePath) : null;
21169
21371
  const fixIdentifier = savedPatchFileName ? savedPatchFileName.replace(".patch", "") : fix.id;
21170
21372
  let markdown = `# Fix ${fixIdentifier}
21171
21373
 
@@ -21507,16 +21709,16 @@ import {
21507
21709
  unlinkSync,
21508
21710
  writeFileSync
21509
21711
  } from "fs";
21510
- import fs21 from "fs/promises";
21712
+ import fs22 from "fs/promises";
21511
21713
  import parseDiff3 from "parse-diff";
21512
- import path20 from "path";
21714
+ import path21 from "path";
21513
21715
  var PatchApplicationService = class {
21514
21716
  /**
21515
21717
  * Gets the appropriate comment syntax for a file based on its extension
21516
21718
  */
21517
21719
  static getCommentSyntax(filePath) {
21518
- const ext = path20.extname(filePath).toLowerCase();
21519
- const basename2 = path20.basename(filePath);
21720
+ const ext = path21.extname(filePath).toLowerCase();
21721
+ const basename2 = path21.basename(filePath);
21520
21722
  const commentMap = {
21521
21723
  // C-style languages (single line comments)
21522
21724
  ".js": "//",
@@ -21724,7 +21926,7 @@ var PatchApplicationService = class {
21724
21926
  }
21725
21927
  );
21726
21928
  }
21727
- const dirPath = path20.dirname(normalizedFilePath);
21929
+ const dirPath = path21.dirname(normalizedFilePath);
21728
21930
  mkdirSync(dirPath, { recursive: true });
21729
21931
  writeFileSync(normalizedFilePath, finalContent, "utf8");
21730
21932
  return normalizedFilePath;
@@ -21733,9 +21935,9 @@ var PatchApplicationService = class {
21733
21935
  repositoryPath,
21734
21936
  targetPath
21735
21937
  }) {
21736
- const repoRoot = path20.resolve(repositoryPath);
21737
- const normalizedPath = path20.resolve(repoRoot, targetPath);
21738
- const repoRootWithSep = repoRoot.endsWith(path20.sep) ? repoRoot : `${repoRoot}${path20.sep}`;
21938
+ const repoRoot = path21.resolve(repositoryPath);
21939
+ const normalizedPath = path21.resolve(repoRoot, targetPath);
21940
+ const repoRootWithSep = repoRoot.endsWith(path21.sep) ? repoRoot : `${repoRoot}${path21.sep}`;
21739
21941
  if (normalizedPath !== repoRoot && !normalizedPath.startsWith(repoRootWithSep)) {
21740
21942
  throw new Error(
21741
21943
  `Security violation: target path ${targetPath} resolves outside repository`
@@ -21744,7 +21946,7 @@ var PatchApplicationService = class {
21744
21946
  return {
21745
21947
  repoRoot,
21746
21948
  normalizedPath,
21747
- relativePath: path20.relative(repoRoot, normalizedPath)
21949
+ relativePath: path21.relative(repoRoot, normalizedPath)
21748
21950
  };
21749
21951
  }
21750
21952
  /**
@@ -22026,9 +22228,9 @@ var PatchApplicationService = class {
22026
22228
  continue;
22027
22229
  }
22028
22230
  try {
22029
- const absolutePath = path20.resolve(repositoryPath, targetFile);
22231
+ const absolutePath = path21.resolve(repositoryPath, targetFile);
22030
22232
  if (existsSync6(absolutePath)) {
22031
- const stats = await fs21.stat(absolutePath);
22233
+ const stats = await fs22.stat(absolutePath);
22032
22234
  const fileModTime = stats.mtime.getTime();
22033
22235
  if (fileModTime > scanStartTime) {
22034
22236
  logError(
@@ -22069,7 +22271,7 @@ var PatchApplicationService = class {
22069
22271
  const appliedFixes = [];
22070
22272
  const failedFixes = [];
22071
22273
  const skippedFixes = [];
22072
- const resolvedRepoPath = await fs21.realpath(repositoryPath);
22274
+ const resolvedRepoPath = await fs22.realpath(repositoryPath);
22073
22275
  logInfo(
22074
22276
  `[${scanContext}] Starting patch application for ${fixes.length} fixes`,
22075
22277
  {
@@ -22252,7 +22454,7 @@ var PatchApplicationService = class {
22252
22454
  fix,
22253
22455
  scanContext
22254
22456
  });
22255
- appliedFiles.push(path20.relative(repositoryPath, actualPath));
22457
+ appliedFiles.push(path21.relative(repositoryPath, actualPath));
22256
22458
  logDebug(`[${scanContext}] Created new file: ${relativePath}`);
22257
22459
  }
22258
22460
  /**
@@ -22301,7 +22503,7 @@ var PatchApplicationService = class {
22301
22503
  fix,
22302
22504
  scanContext
22303
22505
  });
22304
- appliedFiles.push(path20.relative(repositoryPath, actualPath));
22506
+ appliedFiles.push(path21.relative(repositoryPath, actualPath));
22305
22507
  logDebug(`[${scanContext}] Modified file: ${relativePath}`);
22306
22508
  }
22307
22509
  }
@@ -22497,9 +22699,9 @@ init_configs();
22497
22699
 
22498
22700
  // src/mcp/services/FileOperations.ts
22499
22701
  init_FileUtils();
22500
- import fs22 from "fs";
22501
- import path21 from "path";
22502
- import AdmZip2 from "adm-zip";
22702
+ import fs23 from "fs";
22703
+ import path22 from "path";
22704
+ import AdmZip3 from "adm-zip";
22503
22705
  var FileOperations = class {
22504
22706
  /**
22505
22707
  * Creates a ZIP archive containing the specified source files
@@ -22514,14 +22716,14 @@ var FileOperations = class {
22514
22716
  maxFileSize
22515
22717
  }) {
22516
22718
  logDebug("[FileOperations] Packing files");
22517
- const zip = new AdmZip2();
22719
+ const zip = new AdmZip3();
22518
22720
  let packedFilesCount = 0;
22519
22721
  const packedFiles = [];
22520
22722
  const excludedFiles = [];
22521
- const resolvedRepoPath = path21.resolve(repositoryPath);
22723
+ const resolvedRepoPath = path22.resolve(repositoryPath);
22522
22724
  for (const filepath of fileList) {
22523
- const absoluteFilepath = path21.join(repositoryPath, filepath);
22524
- const resolvedFilePath = path21.resolve(absoluteFilepath);
22725
+ const absoluteFilepath = path22.join(repositoryPath, filepath);
22726
+ const resolvedFilePath = path22.resolve(absoluteFilepath);
22525
22727
  if (!resolvedFilePath.startsWith(resolvedRepoPath)) {
22526
22728
  const reason = "potential path traversal security risk";
22527
22729
  logDebug(`[FileOperations] Skipping ${filepath} due to ${reason}`);
@@ -22568,11 +22770,11 @@ var FileOperations = class {
22568
22770
  fileList,
22569
22771
  repositoryPath
22570
22772
  }) {
22571
- const resolvedRepoPath = path21.resolve(repositoryPath);
22773
+ const resolvedRepoPath = path22.resolve(repositoryPath);
22572
22774
  const validatedPaths = [];
22573
22775
  for (const filepath of fileList) {
22574
- const absoluteFilepath = path21.join(repositoryPath, filepath);
22575
- const resolvedFilePath = path21.resolve(absoluteFilepath);
22776
+ const absoluteFilepath = path22.join(repositoryPath, filepath);
22777
+ const resolvedFilePath = path22.resolve(absoluteFilepath);
22576
22778
  if (!resolvedFilePath.startsWith(resolvedRepoPath)) {
22577
22779
  logDebug(
22578
22780
  `[FileOperations] Rejecting ${filepath} - path traversal attempt detected`
@@ -22580,7 +22782,7 @@ var FileOperations = class {
22580
22782
  continue;
22581
22783
  }
22582
22784
  try {
22583
- await fs22.promises.access(absoluteFilepath, fs22.constants.R_OK);
22785
+ await fs23.promises.access(absoluteFilepath, fs23.constants.R_OK);
22584
22786
  validatedPaths.push(filepath);
22585
22787
  } catch (error) {
22586
22788
  logDebug(
@@ -22599,8 +22801,8 @@ var FileOperations = class {
22599
22801
  const fileDataArray = [];
22600
22802
  for (const absolutePath of filePaths) {
22601
22803
  try {
22602
- const content = await fs22.promises.readFile(absolutePath);
22603
- const relativePath = path21.basename(absolutePath);
22804
+ const content = await fs23.promises.readFile(absolutePath);
22805
+ const relativePath = path22.basename(absolutePath);
22604
22806
  fileDataArray.push({
22605
22807
  relativePath,
22606
22808
  absolutePath,
@@ -22625,7 +22827,7 @@ var FileOperations = class {
22625
22827
  relativeFilepath
22626
22828
  }) {
22627
22829
  try {
22628
- return await fs22.promises.readFile(absoluteFilepath);
22830
+ return await fs23.promises.readFile(absoluteFilepath);
22629
22831
  } catch (fsError) {
22630
22832
  logError(
22631
22833
  `[FileOperations] Failed to read ${relativeFilepath} from filesystem: ${fsError}`
@@ -22912,14 +23114,14 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
22912
23114
  * since the last scan.
22913
23115
  */
22914
23116
  async scanForSecurityVulnerabilities({
22915
- path: path25,
23117
+ path: path26,
22916
23118
  isAllDetectionRulesScan,
22917
23119
  isAllFilesScan,
22918
23120
  scanContext
22919
23121
  }) {
22920
23122
  this.hasAuthenticationFailed = false;
22921
23123
  logDebug(`[${scanContext}] Scanning for new security vulnerabilities`, {
22922
- path: path25
23124
+ path: path26
22923
23125
  });
22924
23126
  if (!this.gqlClient) {
22925
23127
  logInfo(`[${scanContext}] No GQL client found, skipping scan`);
@@ -22935,11 +23137,11 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
22935
23137
  }
22936
23138
  logDebug(
22937
23139
  `[${scanContext}] Connected to the API, assembling list of files to scan`,
22938
- { path: path25 }
23140
+ { path: path26 }
22939
23141
  );
22940
23142
  const isBackgroundScan = scanContext === ScanContext.BACKGROUND_INITIAL || scanContext === ScanContext.BACKGROUND_PERIODIC;
22941
23143
  const files = await getLocalFiles({
22942
- path: path25,
23144
+ path: path26,
22943
23145
  isAllFilesScan,
22944
23146
  scanContext,
22945
23147
  scanRecentlyChangedFiles: !isBackgroundScan
@@ -22965,13 +23167,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
22965
23167
  });
22966
23168
  const { fixReportId, projectId } = await scanFiles({
22967
23169
  fileList: filesToScan.map((file) => file.relativePath),
22968
- repositoryPath: path25,
23170
+ repositoryPath: path26,
22969
23171
  gqlClient: this.gqlClient,
22970
23172
  isAllDetectionRulesScan,
22971
23173
  scanContext
22972
23174
  });
22973
23175
  logInfo(
22974
- `[${scanContext}] Security scan completed for ${path25} reportId: ${fixReportId} projectId: ${projectId}`
23176
+ `[${scanContext}] Security scan completed for ${path26} reportId: ${fixReportId} projectId: ${projectId}`
22975
23177
  );
22976
23178
  if (isAllFilesScan) {
22977
23179
  return;
@@ -23265,13 +23467,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
23265
23467
  });
23266
23468
  return scannedFiles.some((file) => file.relativePath === fixFile);
23267
23469
  }
23268
- async getFreshFixes({ path: path25 }) {
23470
+ async getFreshFixes({ path: path26 }) {
23269
23471
  const scanContext = ScanContext.USER_REQUEST;
23270
- logDebug(`[${scanContext}] Getting fresh fixes`, { path: path25 });
23271
- if (this.path !== path25) {
23272
- this.path = path25;
23472
+ logDebug(`[${scanContext}] Getting fresh fixes`, { path: path26 });
23473
+ if (this.path !== path26) {
23474
+ this.path = path26;
23273
23475
  this.reset();
23274
- logInfo(`[${scanContext}] Reset service state for new path`, { path: path25 });
23476
+ logInfo(`[${scanContext}] Reset service state for new path`, { path: path26 });
23275
23477
  }
23276
23478
  try {
23277
23479
  const loginContext = createMcpLoginContext("check_new_fixes");
@@ -23290,7 +23492,7 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
23290
23492
  }
23291
23493
  throw error;
23292
23494
  }
23293
- this.triggerScan({ path: path25, gqlClient: this.gqlClient });
23495
+ this.triggerScan({ path: path26, gqlClient: this.gqlClient });
23294
23496
  let isMvsAutoFixEnabled = null;
23295
23497
  try {
23296
23498
  isMvsAutoFixEnabled = await this.gqlClient.getMvsAutoFixSettings();
@@ -23324,33 +23526,33 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
23324
23526
  return noFreshFixesPrompt;
23325
23527
  }
23326
23528
  triggerScan({
23327
- path: path25,
23529
+ path: path26,
23328
23530
  gqlClient
23329
23531
  }) {
23330
- if (this.path !== path25) {
23331
- this.path = path25;
23532
+ if (this.path !== path26) {
23533
+ this.path = path26;
23332
23534
  this.reset();
23333
- logInfo(`Reset service state for new path in triggerScan`, { path: path25 });
23535
+ logInfo(`Reset service state for new path in triggerScan`, { path: path26 });
23334
23536
  }
23335
23537
  this.gqlClient = gqlClient;
23336
23538
  if (!this.intervalId) {
23337
- this.startPeriodicScanning(path25);
23338
- this.executeInitialScan(path25);
23339
- void this.executeInitialFullScan(path25);
23539
+ this.startPeriodicScanning(path26);
23540
+ this.executeInitialScan(path26);
23541
+ void this.executeInitialFullScan(path26);
23340
23542
  }
23341
23543
  }
23342
- startPeriodicScanning(path25) {
23544
+ startPeriodicScanning(path26) {
23343
23545
  const scanContext = ScanContext.BACKGROUND_PERIODIC;
23344
23546
  logDebug(
23345
23547
  `[${scanContext}] Starting periodic scan for new security vulnerabilities`,
23346
23548
  {
23347
- path: path25
23549
+ path: path26
23348
23550
  }
23349
23551
  );
23350
23552
  this.intervalId = setInterval(() => {
23351
- logDebug(`[${scanContext}] Triggering periodic security scan`, { path: path25 });
23553
+ logDebug(`[${scanContext}] Triggering periodic security scan`, { path: path26 });
23352
23554
  this.scanForSecurityVulnerabilities({
23353
- path: path25,
23555
+ path: path26,
23354
23556
  scanContext
23355
23557
  }).catch((error) => {
23356
23558
  logError(`[${scanContext}] Error during periodic security scan`, {
@@ -23359,45 +23561,45 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
23359
23561
  });
23360
23562
  }, MCP_PERIODIC_CHECK_INTERVAL);
23361
23563
  }
23362
- async executeInitialFullScan(path25) {
23564
+ async executeInitialFullScan(path26) {
23363
23565
  const scanContext = ScanContext.FULL_SCAN;
23364
- logDebug(`[${scanContext}] Triggering initial full security scan`, { path: path25 });
23566
+ logDebug(`[${scanContext}] Triggering initial full security scan`, { path: path26 });
23365
23567
  logDebug(`[${scanContext}] Full scan paths scanned`, {
23366
23568
  fullScanPathsScanned: this.fullScanPathsScanned
23367
23569
  });
23368
- if (this.fullScanPathsScanned.includes(path25)) {
23570
+ if (this.fullScanPathsScanned.includes(path26)) {
23369
23571
  logDebug(`[${scanContext}] Full scan already executed for this path`, {
23370
- path: path25
23572
+ path: path26
23371
23573
  });
23372
23574
  return;
23373
23575
  }
23374
23576
  configStore.set("fullScanPathsScanned", [
23375
23577
  ...this.fullScanPathsScanned,
23376
- path25
23578
+ path26
23377
23579
  ]);
23378
23580
  try {
23379
23581
  await this.scanForSecurityVulnerabilities({
23380
- path: path25,
23582
+ path: path26,
23381
23583
  isAllFilesScan: true,
23382
23584
  isAllDetectionRulesScan: true,
23383
23585
  scanContext: ScanContext.FULL_SCAN
23384
23586
  });
23385
- if (!this.fullScanPathsScanned.includes(path25)) {
23386
- this.fullScanPathsScanned.push(path25);
23587
+ if (!this.fullScanPathsScanned.includes(path26)) {
23588
+ this.fullScanPathsScanned.push(path26);
23387
23589
  configStore.set("fullScanPathsScanned", this.fullScanPathsScanned);
23388
23590
  }
23389
- logInfo(`[${scanContext}] Full scan completed`, { path: path25 });
23591
+ logInfo(`[${scanContext}] Full scan completed`, { path: path26 });
23390
23592
  } catch (error) {
23391
23593
  logError(`[${scanContext}] Error during initial full security scan`, {
23392
23594
  error
23393
23595
  });
23394
23596
  }
23395
23597
  }
23396
- executeInitialScan(path25) {
23598
+ executeInitialScan(path26) {
23397
23599
  const scanContext = ScanContext.BACKGROUND_INITIAL;
23398
- logDebug(`[${scanContext}] Triggering initial security scan`, { path: path25 });
23600
+ logDebug(`[${scanContext}] Triggering initial security scan`, { path: path26 });
23399
23601
  this.scanForSecurityVulnerabilities({
23400
- path: path25,
23602
+ path: path26,
23401
23603
  scanContext: ScanContext.BACKGROUND_INITIAL
23402
23604
  }).catch((error) => {
23403
23605
  logError(`[${scanContext}] Error during initial security scan`, { error });
@@ -23494,9 +23696,9 @@ Example payload:
23494
23696
  `Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
23495
23697
  );
23496
23698
  }
23497
- const path25 = pathValidationResult.path;
23699
+ const path26 = pathValidationResult.path;
23498
23700
  const resultText = await this.newFixesService.getFreshFixes({
23499
- path: path25
23701
+ path: path26
23500
23702
  });
23501
23703
  logInfo("CheckForNewAvailableFixesTool execution completed", {
23502
23704
  resultText
@@ -23674,8 +23876,8 @@ Call this tool instead of ${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES} when you only
23674
23876
  `Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
23675
23877
  );
23676
23878
  }
23677
- const path25 = pathValidationResult.path;
23678
- const gitService = new GitService(path25, log);
23879
+ const path26 = pathValidationResult.path;
23880
+ const gitService = new GitService(path26, log);
23679
23881
  const gitValidation = await gitService.validateRepository();
23680
23882
  if (!gitValidation.isValid) {
23681
23883
  throw new Error(`Invalid git repository: ${gitValidation.error}`);
@@ -24060,9 +24262,9 @@ Example payload:
24060
24262
  `Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
24061
24263
  );
24062
24264
  }
24063
- const path25 = pathValidationResult.path;
24265
+ const path26 = pathValidationResult.path;
24064
24266
  const files = await getLocalFiles({
24065
- path: path25,
24267
+ path: path26,
24066
24268
  maxFileSize: MCP_MAX_FILE_SIZE,
24067
24269
  maxFiles: args.maxFiles,
24068
24270
  scanContext: ScanContext.USER_REQUEST,
@@ -24082,7 +24284,7 @@ Example payload:
24082
24284
  try {
24083
24285
  const fixResult = await this.vulnerabilityFixService.processVulnerabilities({
24084
24286
  fileList: files.map((file) => file.relativePath),
24085
- repositoryPath: path25,
24287
+ repositoryPath: path26,
24086
24288
  offset: args.offset,
24087
24289
  limit: args.limit,
24088
24290
  isRescan: args.rescan || !!args.maxFiles
@@ -24186,33 +24388,33 @@ var mcpHandler = async (_args) => {
24186
24388
  };
24187
24389
 
24188
24390
  // src/args/commands/review.ts
24189
- import fs23 from "fs";
24190
- import chalk11 from "chalk";
24391
+ import fs24 from "fs";
24392
+ import chalk12 from "chalk";
24191
24393
  function reviewBuilder(yargs2) {
24192
24394
  return yargs2.option("f", {
24193
24395
  alias: "scan-file",
24194
24396
  demandOption: true,
24195
24397
  type: "string",
24196
- describe: chalk11.bold(
24398
+ describe: chalk12.bold(
24197
24399
  "Select the vulnerability report to analyze (Checkmarx, Snyk, Fortify, CodeQL, Sonarqube, Semgrep)"
24198
24400
  )
24199
24401
  }).option("repo", { ...repoOption, demandOption: true }).option("scanner", { ...scannerOptions, demandOption: true }).option("ref", { ...refOption, demandOption: true }).option("ch", {
24200
24402
  alias: "commit-hash",
24201
- describe: chalk11.bold("Hash of the commit"),
24403
+ describe: chalk12.bold("Hash of the commit"),
24202
24404
  type: "string",
24203
24405
  demandOption: true
24204
24406
  }).option("mobb-project-name", mobbProjectNameOption).option("api-key", { ...apiKeyOption, demandOption: true }).option("commit-hash", { ...commitHashOption, demandOption: true }).option("github-token", {
24205
- describe: chalk11.bold("Github action token"),
24407
+ describe: chalk12.bold("Github action token"),
24206
24408
  type: "string",
24207
24409
  demandOption: true
24208
24410
  }).option("pull-request", {
24209
24411
  alias: ["pr", "pr-number", "pr-id"],
24210
- describe: chalk11.bold("Number of the pull request"),
24412
+ describe: chalk12.bold("Number of the pull request"),
24211
24413
  type: "number",
24212
24414
  demandOption: true
24213
24415
  }).option("p", {
24214
24416
  alias: "src-path",
24215
- describe: chalk11.bold(
24417
+ describe: chalk12.bold(
24216
24418
  "Path to the repository folder with the source code"
24217
24419
  ),
24218
24420
  type: "string",
@@ -24223,9 +24425,9 @@ function reviewBuilder(yargs2) {
24223
24425
  ).help();
24224
24426
  }
24225
24427
  function validateReviewOptions(argv) {
24226
- if (!fs23.existsSync(argv.f)) {
24428
+ if (!fs24.existsSync(argv.f)) {
24227
24429
  throw new CliError(`
24228
- Can't access ${chalk11.bold(argv.f)}`);
24430
+ Can't access ${chalk12.bold(argv.f)}`);
24229
24431
  }
24230
24432
  validateRepoUrl(argv);
24231
24433
  validateReportFileFormat(argv.f);
@@ -24260,6 +24462,27 @@ async function scanHandler(args) {
24260
24462
  await scan(args, { skipPrompts: args.yes });
24261
24463
  }
24262
24464
 
24465
+ // src/args/commands/scan_skill.ts
24466
+ import chalk13 from "chalk";
24467
+ function scanSkillBuilder(args) {
24468
+ return args.option("url", {
24469
+ demandOption: true,
24470
+ type: "string",
24471
+ describe: chalk13.bold(
24472
+ "URL or local directory of the skill to scan (GitHub repo, ZIP archive, raw SKILL.md, or folder containing SKILL.md)"
24473
+ )
24474
+ }).option("api-key", apiKeyOption).option("ci", ciOption).example(
24475
+ "npx mobbdev@latest scan-skill --url https://github.com/user/my-skill",
24476
+ "Scan an OpenClaw/ClawHub skill for security threats"
24477
+ ).example(
24478
+ "npx mobbdev@latest scan-skill --url ./my-skill-folder",
24479
+ "Scan a local skill directory that contains SKILL.md"
24480
+ ).help();
24481
+ }
24482
+ async function scanSkillHandler(args) {
24483
+ await scanSkill(args);
24484
+ }
24485
+
24263
24486
  // src/args/commands/token.ts
24264
24487
  function addScmTokenBuilder(args) {
24265
24488
  return args.option("scm-type", scmTypeOption).option("url", urlOption).option("token", scmTokenOption).option("organization", scmOrgOption).option("refresh-token", scmRefreshTokenOption).option("api-key", apiKeyOption).option("ci", ciOption).example(
@@ -24301,10 +24524,10 @@ init_client_generates();
24301
24524
  init_urlParser2();
24302
24525
 
24303
24526
  // src/features/codeium_intellij/codeium_language_server_grpc_client.ts
24304
- import path22 from "path";
24527
+ import path23 from "path";
24305
24528
  import * as grpc from "@grpc/grpc-js";
24306
24529
  import * as protoLoader from "@grpc/proto-loader";
24307
- var PROTO_PATH = path22.join(
24530
+ var PROTO_PATH = path23.join(
24308
24531
  getModuleRootDir(),
24309
24532
  "src/features/codeium_intellij/proto/exa/language_server_pb/language_server.proto"
24310
24533
  );
@@ -24316,7 +24539,7 @@ function loadProto() {
24316
24539
  defaults: true,
24317
24540
  oneofs: true,
24318
24541
  includeDirs: [
24319
- path22.join(getModuleRootDir(), "src/features/codeium_intellij/proto")
24542
+ path23.join(getModuleRootDir(), "src/features/codeium_intellij/proto")
24320
24543
  ]
24321
24544
  });
24322
24545
  return grpc.loadPackageDefinition(
@@ -24370,30 +24593,30 @@ async function getGrpcClient(port, csrf3) {
24370
24593
  }
24371
24594
 
24372
24595
  // src/features/codeium_intellij/parse_intellij_logs.ts
24373
- import fs24 from "fs";
24596
+ import fs25 from "fs";
24374
24597
  import os12 from "os";
24375
- import path23 from "path";
24598
+ import path24 from "path";
24376
24599
  function getLogsDir() {
24377
24600
  if (process.platform === "darwin") {
24378
- return path23.join(os12.homedir(), "Library/Logs/JetBrains");
24601
+ return path24.join(os12.homedir(), "Library/Logs/JetBrains");
24379
24602
  } else if (process.platform === "win32") {
24380
- return path23.join(
24381
- process.env["LOCALAPPDATA"] || path23.join(os12.homedir(), "AppData/Local"),
24603
+ return path24.join(
24604
+ process.env["LOCALAPPDATA"] || path24.join(os12.homedir(), "AppData/Local"),
24382
24605
  "JetBrains"
24383
24606
  );
24384
24607
  } else {
24385
- return path23.join(os12.homedir(), ".cache/JetBrains");
24608
+ return path24.join(os12.homedir(), ".cache/JetBrains");
24386
24609
  }
24387
24610
  }
24388
24611
  function parseIdeLogDir(ideLogDir) {
24389
- const logFiles = fs24.readdirSync(ideLogDir).filter((f) => /^idea(\.\d+)?\.log$/.test(f)).map((f) => ({
24612
+ const logFiles = fs25.readdirSync(ideLogDir).filter((f) => /^idea(\.\d+)?\.log$/.test(f)).map((f) => ({
24390
24613
  name: f,
24391
- mtime: fs24.statSync(path23.join(ideLogDir, f)).mtimeMs
24614
+ mtime: fs25.statSync(path24.join(ideLogDir, f)).mtimeMs
24392
24615
  })).sort((a, b) => a.mtime - b.mtime).map((f) => f.name);
24393
24616
  let latestCsrf = null;
24394
24617
  let latestPort = null;
24395
24618
  for (const logFile of logFiles) {
24396
- const lines = fs24.readFileSync(path23.join(ideLogDir, logFile), "utf-8").split("\n");
24619
+ const lines = fs25.readFileSync(path24.join(ideLogDir, logFile), "utf-8").split("\n");
24397
24620
  for (const line of lines) {
24398
24621
  if (!line.includes(
24399
24622
  "com.codeium.intellij.language_server.LanguageServerProcessHandler"
@@ -24419,13 +24642,13 @@ function parseIdeLogDir(ideLogDir) {
24419
24642
  function findRunningCodeiumLanguageServers() {
24420
24643
  const results = [];
24421
24644
  const logsDir = getLogsDir();
24422
- if (!fs24.existsSync(logsDir)) return results;
24423
- for (const ide of fs24.readdirSync(logsDir)) {
24424
- let ideLogDir = path23.join(logsDir, ide);
24645
+ if (!fs25.existsSync(logsDir)) return results;
24646
+ for (const ide of fs25.readdirSync(logsDir)) {
24647
+ let ideLogDir = path24.join(logsDir, ide);
24425
24648
  if (process.platform !== "darwin") {
24426
- ideLogDir = path23.join(ideLogDir, "log");
24649
+ ideLogDir = path24.join(ideLogDir, "log");
24427
24650
  }
24428
- if (!fs24.existsSync(ideLogDir) || !fs24.statSync(ideLogDir).isDirectory()) {
24651
+ if (!fs25.existsSync(ideLogDir) || !fs25.statSync(ideLogDir).isDirectory()) {
24429
24652
  continue;
24430
24653
  }
24431
24654
  const result = parseIdeLogDir(ideLogDir);
@@ -24606,10 +24829,10 @@ function processChatStepCodeAction(step) {
24606
24829
  // src/features/codeium_intellij/install_hook.ts
24607
24830
  import fsPromises6 from "fs/promises";
24608
24831
  import os13 from "os";
24609
- import path24 from "path";
24610
- import chalk12 from "chalk";
24832
+ import path25 from "path";
24833
+ import chalk14 from "chalk";
24611
24834
  function getCodeiumHooksPath() {
24612
- return path24.join(os13.homedir(), ".codeium", "hooks.json");
24835
+ return path25.join(os13.homedir(), ".codeium", "hooks.json");
24613
24836
  }
24614
24837
  async function readCodeiumHooks() {
24615
24838
  const hooksPath = getCodeiumHooksPath();
@@ -24622,7 +24845,7 @@ async function readCodeiumHooks() {
24622
24845
  }
24623
24846
  async function writeCodeiumHooks(config2) {
24624
24847
  const hooksPath = getCodeiumHooksPath();
24625
- const dir = path24.dirname(hooksPath);
24848
+ const dir = path25.dirname(hooksPath);
24626
24849
  await fsPromises6.mkdir(dir, { recursive: true });
24627
24850
  await fsPromises6.writeFile(
24628
24851
  hooksPath,
@@ -24632,7 +24855,7 @@ async function writeCodeiumHooks(config2) {
24632
24855
  }
24633
24856
  async function installWindsurfHooks(options = {}) {
24634
24857
  const hooksPath = getCodeiumHooksPath();
24635
- console.log(chalk12.blue("Installing Mobb hooks in Windsurf IntelliJ..."));
24858
+ console.log(chalk14.blue("Installing Mobb hooks in Windsurf IntelliJ..."));
24636
24859
  const config2 = await readCodeiumHooks();
24637
24860
  if (!config2.hooks) {
24638
24861
  config2.hooks = {};
@@ -24652,7 +24875,7 @@ async function installWindsurfHooks(options = {}) {
24652
24875
  if (envVars.length > 0) {
24653
24876
  command = `${envVars.join(" ")} ${command}`;
24654
24877
  console.log(
24655
- chalk12.blue(
24878
+ chalk14.blue(
24656
24879
  `Adding environment variables to hook command: ${envVars.join(", ")}`
24657
24880
  )
24658
24881
  );
@@ -24666,15 +24889,15 @@ async function installWindsurfHooks(options = {}) {
24666
24889
  (hook) => hook.command?.includes("mobbdev@latest windsurf-intellij-process-hook")
24667
24890
  );
24668
24891
  if (existingHookIndex >= 0) {
24669
- console.log(chalk12.yellow("Mobb hook already exists, updating..."));
24892
+ console.log(chalk14.yellow("Mobb hook already exists, updating..."));
24670
24893
  config2.hooks.post_write_code[existingHookIndex] = mobbHook;
24671
24894
  } else {
24672
- console.log(chalk12.green("Adding new Mobb hook..."));
24895
+ console.log(chalk14.green("Adding new Mobb hook..."));
24673
24896
  config2.hooks.post_write_code.push(mobbHook);
24674
24897
  }
24675
24898
  await writeCodeiumHooks(config2);
24676
24899
  console.log(
24677
- chalk12.green(
24900
+ chalk14.green(
24678
24901
  `\u2705 Mobb hooks ${options.saveEnv ? "and environment variables " : ""}installed successfully in ${hooksPath}`
24679
24902
  )
24680
24903
  );
@@ -24724,81 +24947,86 @@ var windsurfIntellijProcessHookHandler = async () => {
24724
24947
  var parseArgs = async (args) => {
24725
24948
  const yargsInstance = yargs(args);
24726
24949
  return yargsInstance.updateStrings({
24727
- "Commands:": chalk13.yellow.underline.bold("Commands:"),
24728
- "Options:": chalk13.yellow.underline.bold("Options:"),
24729
- "Examples:": chalk13.yellow.underline.bold("Examples:"),
24730
- "Show help": chalk13.bold("Show help")
24950
+ "Commands:": chalk15.yellow.underline.bold("Commands:"),
24951
+ "Options:": chalk15.yellow.underline.bold("Options:"),
24952
+ "Examples:": chalk15.yellow.underline.bold("Examples:"),
24953
+ "Show help": chalk15.bold("Show help")
24731
24954
  }).usage(
24732
- `${chalk13.bold(
24955
+ `${chalk15.bold(
24733
24956
  "\n Bugsy - Trusted, Automatic Vulnerability Fixer \u{1F575}\uFE0F\u200D\u2642\uFE0F\n\n"
24734
- )} ${chalk13.yellow.underline.bold("Usage:")}
24735
- $0 ${chalk13.green(
24957
+ )} ${chalk15.yellow.underline.bold("Usage:")}
24958
+ $0 ${chalk15.green(
24736
24959
  "<command>"
24737
- )} ${chalk13.dim("[options]")}
24960
+ )} ${chalk15.dim("[options]")}
24738
24961
  `
24739
24962
  ).version(false).command(
24740
24963
  mobbCliCommand.scan,
24741
- chalk13.bold(
24964
+ chalk15.bold(
24742
24965
  "Scan your code for vulnerabilities, get automated fixes right away."
24743
24966
  ),
24744
24967
  scanBuilder,
24745
24968
  scanHandler
24746
24969
  ).command(
24747
24970
  mobbCliCommand.analyze,
24748
- chalk13.bold(
24971
+ chalk15.bold(
24749
24972
  "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."
24750
24973
  ),
24751
24974
  analyzeBuilder,
24752
24975
  analyzeHandler
24753
24976
  ).command(
24754
24977
  mobbCliCommand.review,
24755
- chalk13.bold(
24978
+ chalk15.bold(
24756
24979
  "Mobb will review your github pull requests and provide comments with fixes "
24757
24980
  ),
24758
24981
  reviewBuilder,
24759
24982
  reviewHandler
24760
24983
  ).command(
24761
24984
  mobbCliCommand.addScmToken,
24762
- chalk13.bold(
24985
+ chalk15.bold(
24763
24986
  "Add your SCM (Github, Gitlab, Azure DevOps) token to Mobb to enable automated fixes."
24764
24987
  ),
24765
24988
  addScmTokenBuilder,
24766
24989
  addScmTokenHandler
24990
+ ).command(
24991
+ mobbCliCommand.scanSkill,
24992
+ chalk15.bold("Scan an OpenClaw/ClawHub skill for security threats."),
24993
+ scanSkillBuilder,
24994
+ scanSkillHandler
24767
24995
  ).command(
24768
24996
  mobbCliCommand.convertToSarif,
24769
- chalk13.bold("Convert an existing SAST report to SARIF format."),
24997
+ chalk15.bold("Convert an existing SAST report to SARIF format."),
24770
24998
  convertToSarifBuilder,
24771
24999
  convertToSarifHandler
24772
25000
  ).command(
24773
25001
  mobbCliCommand.mcp,
24774
- chalk13.bold("Launch the MCP (Model Context Protocol) server."),
25002
+ chalk15.bold("Launch the MCP (Model Context Protocol) server."),
24775
25003
  mcpBuilder,
24776
25004
  mcpHandler
24777
25005
  ).command(
24778
25006
  mobbCliCommand.uploadAiBlame,
24779
- chalk13.bold(
25007
+ chalk15.bold(
24780
25008
  "Upload AI Blame inference artifacts (prompt + inference) and finalize them."
24781
25009
  ),
24782
25010
  uploadAiBlameBuilder,
24783
25011
  uploadAiBlameCommandHandler
24784
25012
  ).command(
24785
25013
  mobbCliCommand.claudeCodeInstallHook,
24786
- chalk13.bold("Install Claude Code hooks for data collection."),
25014
+ chalk15.bold("Install Claude Code hooks for data collection."),
24787
25015
  claudeCodeInstallHookBuilder,
24788
25016
  claudeCodeInstallHookHandler
24789
25017
  ).command(
24790
25018
  mobbCliCommand.claudeCodeProcessHook,
24791
- chalk13.bold("Process Claude Code hook data and upload to backend."),
25019
+ chalk15.bold("Process Claude Code hook data and upload to backend."),
24792
25020
  claudeCodeProcessHookBuilder,
24793
25021
  claudeCodeProcessHookHandler
24794
25022
  ).command(
24795
25023
  mobbCliCommand.windsurfIntellijInstallHook,
24796
- chalk13.bold("Install Windsurf IntelliJ hooks for data collection."),
25024
+ chalk15.bold("Install Windsurf IntelliJ hooks for data collection."),
24797
25025
  windsurfIntellijInstallHookBuilder,
24798
25026
  windsurfIntellijInstallHookHandler
24799
25027
  ).command(
24800
25028
  mobbCliCommand.windsurfIntellijProcessHook,
24801
- chalk13.bold("Process Windsurf IntelliJ hook data and upload to backend."),
25029
+ chalk15.bold("Process Windsurf IntelliJ hook data and upload to backend."),
24802
25030
  windsurfIntellijProcessHookBuilder,
24803
25031
  windsurfIntellijProcessHookHandler
24804
25032
  ).example(
@@ -24809,7 +25037,7 @@ var parseArgs = async (args) => {
24809
25037
  handler() {
24810
25038
  yargsInstance.showHelp();
24811
25039
  }
24812
- }).strictOptions().help("h").alias("h", "help").epilog(chalk13.bgBlue("Made with \u2764\uFE0F by Mobb")).showHelpOnFail(true).wrap(Math.min(120, yargsInstance.terminalWidth())).parse();
25040
+ }).strictOptions().help("h").alias("h", "help").epilog(chalk15.bgBlue("Made with \u2764\uFE0F by Mobb")).showHelpOnFail(true).wrap(Math.min(120, yargsInstance.terminalWidth())).parse();
24813
25041
  };
24814
25042
 
24815
25043
  // src/index.ts