mobbdev 1.0.211 → 1.0.212

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