mobbdev 1.1.30 → 1.1.33

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.
@@ -62,7 +62,7 @@ var init_FilePatterns = __esm({
62
62
  });
63
63
 
64
64
  // src/features/analysis/scm/services/FileUtils.ts
65
- import fs3 from "fs";
65
+ import fs4 from "fs";
66
66
  import { promises as fsPromises } from "fs";
67
67
  import { isBinary } from "istextorbinary";
68
68
  import path4 from "path";
@@ -76,7 +76,7 @@ var init_FileUtils = __esm({
76
76
  });
77
77
 
78
78
  // src/features/analysis/scm/services/GitService.ts
79
- import fs4 from "fs";
79
+ import fs5 from "fs";
80
80
  import ignore from "ignore";
81
81
  import * as path5 from "path";
82
82
  import { simpleGit as simpleGit2 } from "simple-git";
@@ -92,7 +92,7 @@ var init_GitService = __esm({
92
92
 
93
93
  // src/args/commands/upload_ai_blame.ts
94
94
  import fsPromises2 from "fs/promises";
95
- import * as os2 from "os";
95
+ import * as os3 from "os";
96
96
  import path6 from "path";
97
97
  import chalk3 from "chalk";
98
98
  import { withFile } from "tmp-promise";
@@ -106,6 +106,7 @@ import Debug6 from "debug";
106
106
  import open from "open";
107
107
 
108
108
  // src/constants.ts
109
+ import fs2 from "fs";
109
110
  import path2 from "path";
110
111
  import chalk from "chalk";
111
112
  import Debug from "debug";
@@ -818,13 +819,25 @@ var UploadS3BucketInfoDocument = `
818
819
  }
819
820
  }
820
821
  `;
822
+ var GetTracyDiffUploadUrlDocument = `
823
+ mutation GetTracyDiffUploadUrl($commitSha: String!) {
824
+ getTracyDiffUploadUrl(commitSha: $commitSha) {
825
+ status
826
+ error
827
+ uploadInfo {
828
+ url
829
+ uploadFieldsJSON
830
+ uploadKey
831
+ }
832
+ }
833
+ }
834
+ `;
821
835
  var AnalyzeCommitForExtensionAiBlameDocument = `
822
- mutation AnalyzeCommitForExtensionAIBlame($repositoryURL: String!, $commitSha: String!, $organizationId: String!, $commitDiff: String, $commitTimestamp: Timestamp, $parentCommits: [ParentCommitInput!]) {
836
+ mutation AnalyzeCommitForExtensionAIBlame($repositoryURL: String!, $commitSha: String!, $organizationId: String!, $commitTimestamp: Timestamp, $parentCommits: [ParentCommitInput!]) {
823
837
  analyzeCommitForAIBlame(
824
838
  repositoryURL: $repositoryURL
825
839
  commitSha: $commitSha
826
840
  organizationId: $organizationId
827
- commitDiff: $commitDiff
828
841
  commitTimestamp: $commitTimestamp
829
842
  parentCommits: $parentCommits
830
843
  ) {
@@ -1214,6 +1227,9 @@ function getSdk(client, withWrapper = defaultWrapper) {
1214
1227
  uploadS3BucketInfo(variables, requestHeaders, signal) {
1215
1228
  return withWrapper((wrappedRequestHeaders) => client.request({ document: UploadS3BucketInfoDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "uploadS3BucketInfo", "mutation", variables);
1216
1229
  },
1230
+ GetTracyDiffUploadUrl(variables, requestHeaders, signal) {
1231
+ return withWrapper((wrappedRequestHeaders) => client.request({ document: GetTracyDiffUploadUrlDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "GetTracyDiffUploadUrl", "mutation", variables);
1232
+ },
1217
1233
  AnalyzeCommitForExtensionAIBlame(variables, requestHeaders, signal) {
1218
1234
  return withWrapper((wrappedRequestHeaders) => client.request({ document: AnalyzeCommitForExtensionAiBlameDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "AnalyzeCommitForExtensionAIBlame", "mutation", variables);
1219
1235
  },
@@ -2233,6 +2249,22 @@ function getDirName() {
2233
2249
 
2234
2250
  // src/constants.ts
2235
2251
  var debug = Debug("mobbdev:constants");
2252
+ var runtimeConfigPath = path2.join(
2253
+ getModuleRootDir(),
2254
+ "out",
2255
+ "runtime.config.json"
2256
+ );
2257
+ if (fs2.existsSync(runtimeConfigPath)) {
2258
+ try {
2259
+ const runtimeConfig = JSON.parse(
2260
+ fs2.readFileSync(runtimeConfigPath, "utf-8")
2261
+ );
2262
+ Object.assign(process.env, runtimeConfig);
2263
+ debug("Loaded runtime config from %s", runtimeConfigPath);
2264
+ } catch (e) {
2265
+ debug("Failed to load runtime config: %o", e);
2266
+ }
2267
+ }
2236
2268
  dotenv.config({ path: path2.join(getModuleRootDir(), ".env") });
2237
2269
  var DEFAULT_API_URL = "https://api.mobb.ai/v1/graphql";
2238
2270
  var DEFAULT_WEB_APP_URL = "https://app.mobb.ai";
@@ -2390,12 +2422,12 @@ function Spinner({ ci = false } = {}) {
2390
2422
  }
2391
2423
 
2392
2424
  // src/utils/check_node_version.ts
2393
- import fs2 from "fs";
2425
+ import fs3 from "fs";
2394
2426
  import path3 from "path";
2395
2427
  import semver from "semver";
2396
2428
  function getPackageJson() {
2397
2429
  return JSON.parse(
2398
- fs2.readFileSync(path3.join(getModuleRootDir(), "package.json"), "utf8")
2430
+ fs3.readFileSync(path3.join(getModuleRootDir(), "package.json"), "utf8")
2399
2431
  );
2400
2432
  }
2401
2433
  var packageJson = getPackageJson();
@@ -4375,8 +4407,8 @@ var IssueTypeAndLanguageZ = z12.object({
4375
4407
  import { z as z13 } from "zod";
4376
4408
  var ADO_PREFIX_PATH = "tfs";
4377
4409
  function detectAdoUrl(args) {
4378
- const { pathname, hostname: hostname2, scmType } = args;
4379
- const hostnameParts = hostname2.split(".");
4410
+ const { pathname, hostname, scmType } = args;
4411
+ const hostnameParts = hostname.split(".");
4380
4412
  const adoCloudHostname = new URL(scmCloudUrl.Ado).hostname;
4381
4413
  const prefixPath = pathname.at(0)?.toLowerCase() === ADO_PREFIX_PATH ? ADO_PREFIX_PATH : "";
4382
4414
  const normalizedPath = prefixPath ? pathname.slice(1) : pathname;
@@ -4405,7 +4437,7 @@ function detectAdoUrl(args) {
4405
4437
  };
4406
4438
  }
4407
4439
  }
4408
- if (hostname2 === adoCloudHostname || scmType === "Ado" /* Ado */) {
4440
+ if (hostname === adoCloudHostname || scmType === "Ado" /* Ado */) {
4409
4441
  if (normalizedPath[normalizedPath.length - 2] === "_git") {
4410
4442
  if (normalizedPath.length === 3) {
4411
4443
  const [organization, _git, repoName] = normalizedPath;
@@ -4433,9 +4465,9 @@ function detectAdoUrl(args) {
4433
4465
  return null;
4434
4466
  }
4435
4467
  function detectGithubUrl(args) {
4436
- const { pathname, hostname: hostname2, scmType } = args;
4468
+ const { pathname, hostname, scmType } = args;
4437
4469
  const githubHostname = new URL(scmCloudUrl.GitHub).hostname;
4438
- if (hostname2 === githubHostname || scmType === "GitHub" /* GitHub */) {
4470
+ if (hostname === githubHostname || scmType === "GitHub" /* GitHub */) {
4439
4471
  if (pathname.length === 2) {
4440
4472
  return {
4441
4473
  scmType: "GitHub" /* GitHub */,
@@ -4447,9 +4479,9 @@ function detectGithubUrl(args) {
4447
4479
  return null;
4448
4480
  }
4449
4481
  function detectGitlabUrl(args) {
4450
- const { pathname, hostname: hostname2, scmType } = args;
4482
+ const { pathname, hostname, scmType } = args;
4451
4483
  const gitlabHostname = new URL(scmCloudUrl.GitLab).hostname;
4452
- if (hostname2 === gitlabHostname || scmType === "GitLab" /* GitLab */) {
4484
+ if (hostname === gitlabHostname || scmType === "GitLab" /* GitLab */) {
4453
4485
  if (pathname.length >= 2) {
4454
4486
  return {
4455
4487
  scmType: "GitLab" /* GitLab */,
@@ -4461,9 +4493,9 @@ function detectGitlabUrl(args) {
4461
4493
  return null;
4462
4494
  }
4463
4495
  function detectBitbucketUrl(args) {
4464
- const { pathname, hostname: hostname2, scmType } = args;
4496
+ const { pathname, hostname, scmType } = args;
4465
4497
  const bitbucketHostname = new URL(scmCloudUrl.Bitbucket).hostname;
4466
- if (hostname2 === bitbucketHostname || scmType === "Bitbucket" /* Bitbucket */) {
4498
+ if (hostname === bitbucketHostname || scmType === "Bitbucket" /* Bitbucket */) {
4467
4499
  if (pathname.length === 2) {
4468
4500
  return {
4469
4501
  scmType: "Bitbucket" /* Bitbucket */,
@@ -4612,6 +4644,7 @@ var REPORT_DEFAULT_FILE_NAME = "report.json";
4612
4644
  init_env();
4613
4645
 
4614
4646
  // src/features/analysis/scm/github/GithubSCMLib.ts
4647
+ import pLimit from "p-limit";
4615
4648
  import { z as z22 } from "zod";
4616
4649
 
4617
4650
  // src/features/analysis/scm/github/github.ts
@@ -4624,6 +4657,9 @@ import sodium from "libsodium-wrappers";
4624
4657
  import { Octokit } from "octokit";
4625
4658
  import { fetch as fetch2, ProxyAgent } from "undici";
4626
4659
 
4660
+ // src/features/analysis/scm/github/GithubSCMLib.ts
4661
+ var GITHUB_COMMIT_FETCH_CONCURRENCY = parseInt(process.env["GITHUB_COMMIT_CONCURRENCY"] || "10", 10) || 10;
4662
+
4627
4663
  // src/features/analysis/scm/gitlab/gitlab.ts
4628
4664
  import querystring3 from "querystring";
4629
4665
  import {
@@ -4729,6 +4765,19 @@ var REPORT_STATE_CHECK_DELAY = 5 * 1e3;
4729
4765
  function getProxyAgent(url) {
4730
4766
  try {
4731
4767
  const parsedUrl = new URL(url);
4768
+ const hostname = parsedUrl.hostname.toLowerCase();
4769
+ if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname === "[::1]") {
4770
+ debug6("Skipping proxy for localhost URL: %s", url);
4771
+ return void 0;
4772
+ }
4773
+ const noProxy = process.env["NO_PROXY"] || process.env["no_proxy"];
4774
+ if (noProxy) {
4775
+ const noProxyList = noProxy.split(",").map((h) => h.trim().toLowerCase());
4776
+ if (noProxyList.includes(hostname) || noProxyList.includes("*")) {
4777
+ debug6("Skipping proxy due to NO_PROXY for: %s", url);
4778
+ return void 0;
4779
+ }
4780
+ }
4732
4781
  const isHttp = parsedUrl.protocol === "http:";
4733
4782
  const isHttps = parsedUrl.protocol === "https:";
4734
4783
  const proxy = isHttps ? HTTPS_PROXY || HTTP_PROXY : isHttp ? HTTP_PROXY : null;
@@ -5138,12 +5187,15 @@ var GQLClient = class {
5138
5187
  async getAIBlameAttributionPromptSummary(variables) {
5139
5188
  return await this._clientSdk.GetPromptSummary(variables);
5140
5189
  }
5190
+ async getTracyDiffUploadUrl(variables) {
5191
+ return await this._clientSdk.GetTracyDiffUploadUrl(variables);
5192
+ }
5141
5193
  };
5142
5194
 
5143
5195
  // src/mcp/services/types.ts
5144
- function buildLoginUrl(baseUrl, loginId, hostname2, context) {
5196
+ function buildLoginUrl(baseUrl, loginId, hostname, context) {
5145
5197
  const url = new URL(`${baseUrl}/${loginId}`);
5146
- url.searchParams.set("hostname", hostname2);
5198
+ url.searchParams.set("hostname", hostname);
5147
5199
  url.searchParams.set("trigger", context.trigger);
5148
5200
  url.searchParams.set("source", context.source);
5149
5201
  if (context.ide) {
@@ -5357,6 +5409,95 @@ async function uploadFile({
5357
5409
  logInfo(`FileUpload: upload file done`);
5358
5410
  }
5359
5411
 
5412
+ // src/utils/computerName.ts
5413
+ import { execSync } from "child_process";
5414
+ import os2 from "os";
5415
+ var STABLE_COMPUTER_NAME_CONFIG_KEY = "stableComputerName";
5416
+ var HOSTNAME_SUFFIXES = [
5417
+ // Cloud providers (must be first - most specific)
5418
+ ".ec2.internal",
5419
+ ".compute.internal",
5420
+ ".cloudapp.net",
5421
+ // mDNS/Bonjour
5422
+ ".local",
5423
+ ".localhost",
5424
+ ".localdomain",
5425
+ // Home networks
5426
+ ".lan",
5427
+ ".home",
5428
+ ".homelan",
5429
+ // Corporate networks
5430
+ ".corp",
5431
+ ".internal",
5432
+ ".intranet",
5433
+ ".domain",
5434
+ ".work",
5435
+ ".office",
5436
+ // Container environments
5437
+ ".docker",
5438
+ ".kubernetes",
5439
+ ".k8s"
5440
+ ];
5441
+ function getOsSpecificComputerName() {
5442
+ const platform = os2.platform();
5443
+ try {
5444
+ if (platform === "darwin") {
5445
+ const result = execSync("scutil --get LocalHostName", {
5446
+ encoding: "utf-8",
5447
+ timeout: 1e3
5448
+ });
5449
+ return result.trim();
5450
+ } else if (platform === "win32") {
5451
+ return process.env["COMPUTERNAME"] || null;
5452
+ } else {
5453
+ try {
5454
+ const result2 = execSync("hostnamectl --static", {
5455
+ encoding: "utf-8",
5456
+ timeout: 1e3
5457
+ });
5458
+ const hostname = result2.trim();
5459
+ if (hostname) return hostname;
5460
+ } catch {
5461
+ }
5462
+ const result = execSync("cat /etc/hostname", {
5463
+ encoding: "utf-8",
5464
+ timeout: 1e3
5465
+ });
5466
+ return result.trim();
5467
+ }
5468
+ } catch (error) {
5469
+ return null;
5470
+ }
5471
+ }
5472
+ function stripHostnameSuffixes(hostname) {
5473
+ if (!hostname) return hostname;
5474
+ let normalized = hostname;
5475
+ for (const suffix of HOSTNAME_SUFFIXES) {
5476
+ if (normalized.endsWith(suffix)) {
5477
+ normalized = normalized.slice(0, -suffix.length);
5478
+ break;
5479
+ }
5480
+ }
5481
+ return normalized;
5482
+ }
5483
+ function generateStableComputerName() {
5484
+ const osSpecificName = getOsSpecificComputerName();
5485
+ if (osSpecificName) {
5486
+ return osSpecificName;
5487
+ }
5488
+ const currentHostname = os2.hostname();
5489
+ return stripHostnameSuffixes(currentHostname);
5490
+ }
5491
+ function getStableComputerName() {
5492
+ const cached = configStore.get(STABLE_COMPUTER_NAME_CONFIG_KEY);
5493
+ if (cached) {
5494
+ return cached;
5495
+ }
5496
+ const currentName = generateStableComputerName();
5497
+ configStore.set(STABLE_COMPUTER_NAME_CONFIG_KEY, currentName);
5498
+ return currentName;
5499
+ }
5500
+
5360
5501
  // src/utils/sanitize-sensitive-data.ts
5361
5502
  import { OpenRedaction } from "@openredaction/openredaction";
5362
5503
  var openRedaction = new OpenRedaction({
@@ -5541,12 +5682,12 @@ var PromptItemArrayZ = z26.array(PromptItemZ);
5541
5682
  function getSystemInfo() {
5542
5683
  let userName;
5543
5684
  try {
5544
- userName = os2.userInfo().username;
5685
+ userName = os3.userInfo().username;
5545
5686
  } catch {
5546
5687
  userName = void 0;
5547
5688
  }
5548
5689
  return {
5549
- computerName: os2.hostname(),
5690
+ computerName: getStableComputerName(),
5550
5691
  userName
5551
5692
  };
5552
5693
  }
package/dist/index.mjs CHANGED
@@ -1412,7 +1412,7 @@ import chalk12 from "chalk";
1412
1412
  import yargs from "yargs/yargs";
1413
1413
 
1414
1414
  // src/args/commands/convert_to_sarif.ts
1415
- import fs7 from "fs";
1415
+ import fs8 from "fs";
1416
1416
 
1417
1417
  // src/commands/convert_to_sarif.ts
1418
1418
  import fs6 from "fs";
@@ -2161,13 +2161,25 @@ var UploadS3BucketInfoDocument = `
2161
2161
  }
2162
2162
  }
2163
2163
  `;
2164
+ var GetTracyDiffUploadUrlDocument = `
2165
+ mutation GetTracyDiffUploadUrl($commitSha: String!) {
2166
+ getTracyDiffUploadUrl(commitSha: $commitSha) {
2167
+ status
2168
+ error
2169
+ uploadInfo {
2170
+ url
2171
+ uploadFieldsJSON
2172
+ uploadKey
2173
+ }
2174
+ }
2175
+ }
2176
+ `;
2164
2177
  var AnalyzeCommitForExtensionAiBlameDocument = `
2165
- mutation AnalyzeCommitForExtensionAIBlame($repositoryURL: String!, $commitSha: String!, $organizationId: String!, $commitDiff: String, $commitTimestamp: Timestamp, $parentCommits: [ParentCommitInput!]) {
2178
+ mutation AnalyzeCommitForExtensionAIBlame($repositoryURL: String!, $commitSha: String!, $organizationId: String!, $commitTimestamp: Timestamp, $parentCommits: [ParentCommitInput!]) {
2166
2179
  analyzeCommitForAIBlame(
2167
2180
  repositoryURL: $repositoryURL
2168
2181
  commitSha: $commitSha
2169
2182
  organizationId: $organizationId
2170
- commitDiff: $commitDiff
2171
2183
  commitTimestamp: $commitTimestamp
2172
2184
  parentCommits: $parentCommits
2173
2185
  ) {
@@ -2557,6 +2569,9 @@ function getSdk(client, withWrapper = defaultWrapper) {
2557
2569
  uploadS3BucketInfo(variables, requestHeaders, signal) {
2558
2570
  return withWrapper((wrappedRequestHeaders) => client.request({ document: UploadS3BucketInfoDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "uploadS3BucketInfo", "mutation", variables);
2559
2571
  },
2572
+ GetTracyDiffUploadUrl(variables, requestHeaders, signal) {
2573
+ return withWrapper((wrappedRequestHeaders) => client.request({ document: GetTracyDiffUploadUrlDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "GetTracyDiffUploadUrl", "mutation", variables);
2574
+ },
2560
2575
  AnalyzeCommitForExtensionAIBlame(variables, requestHeaders, signal) {
2561
2576
  return withWrapper((wrappedRequestHeaders) => client.request({ document: AnalyzeCommitForExtensionAiBlameDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "AnalyzeCommitForExtensionAIBlame", "mutation", variables);
2562
2577
  },
@@ -5613,8 +5628,8 @@ import { z as z12 } from "zod";
5613
5628
  var ADO_PREFIX_PATH = "tfs";
5614
5629
  var NAME_REGEX = /[a-z0-9\-_.+]+/i;
5615
5630
  function detectAdoUrl(args) {
5616
- const { pathname, hostname: hostname2, scmType } = args;
5617
- const hostnameParts = hostname2.split(".");
5631
+ const { pathname, hostname, scmType } = args;
5632
+ const hostnameParts = hostname.split(".");
5618
5633
  const adoCloudHostname = new URL(scmCloudUrl.Ado).hostname;
5619
5634
  const prefixPath = pathname.at(0)?.toLowerCase() === ADO_PREFIX_PATH ? ADO_PREFIX_PATH : "";
5620
5635
  const normalizedPath = prefixPath ? pathname.slice(1) : pathname;
@@ -5643,7 +5658,7 @@ function detectAdoUrl(args) {
5643
5658
  };
5644
5659
  }
5645
5660
  }
5646
- if (hostname2 === adoCloudHostname || scmType === "Ado" /* Ado */) {
5661
+ if (hostname === adoCloudHostname || scmType === "Ado" /* Ado */) {
5647
5662
  if (normalizedPath[normalizedPath.length - 2] === "_git") {
5648
5663
  if (normalizedPath.length === 3) {
5649
5664
  const [organization, _git, repoName] = normalizedPath;
@@ -5671,9 +5686,9 @@ function detectAdoUrl(args) {
5671
5686
  return null;
5672
5687
  }
5673
5688
  function detectGithubUrl(args) {
5674
- const { pathname, hostname: hostname2, scmType } = args;
5689
+ const { pathname, hostname, scmType } = args;
5675
5690
  const githubHostname = new URL(scmCloudUrl.GitHub).hostname;
5676
- if (hostname2 === githubHostname || scmType === "GitHub" /* GitHub */) {
5691
+ if (hostname === githubHostname || scmType === "GitHub" /* GitHub */) {
5677
5692
  if (pathname.length === 2) {
5678
5693
  return {
5679
5694
  scmType: "GitHub" /* GitHub */,
@@ -5685,9 +5700,9 @@ function detectGithubUrl(args) {
5685
5700
  return null;
5686
5701
  }
5687
5702
  function detectGitlabUrl(args) {
5688
- const { pathname, hostname: hostname2, scmType } = args;
5703
+ const { pathname, hostname, scmType } = args;
5689
5704
  const gitlabHostname = new URL(scmCloudUrl.GitLab).hostname;
5690
- if (hostname2 === gitlabHostname || scmType === "GitLab" /* GitLab */) {
5705
+ if (hostname === gitlabHostname || scmType === "GitLab" /* GitLab */) {
5691
5706
  if (pathname.length >= 2) {
5692
5707
  return {
5693
5708
  scmType: "GitLab" /* GitLab */,
@@ -5699,9 +5714,9 @@ function detectGitlabUrl(args) {
5699
5714
  return null;
5700
5715
  }
5701
5716
  function detectBitbucketUrl(args) {
5702
- const { pathname, hostname: hostname2, scmType } = args;
5717
+ const { pathname, hostname, scmType } = args;
5703
5718
  const bitbucketHostname = new URL(scmCloudUrl.Bitbucket).hostname;
5704
- if (hostname2 === bitbucketHostname || scmType === "Bitbucket" /* Bitbucket */) {
5719
+ if (hostname === bitbucketHostname || scmType === "Bitbucket" /* Bitbucket */) {
5705
5720
  if (pathname.length === 2) {
5706
5721
  return {
5707
5722
  scmType: "Bitbucket" /* Bitbucket */,
@@ -5730,10 +5745,10 @@ function getRepoInfo(args) {
5730
5745
  function parseSshUrl(scmURL, scmType) {
5731
5746
  const sshMatch = scmURL.match(/^git@([^:]+):(.+?)(?:\.git)?$/);
5732
5747
  if (!sshMatch) return null;
5733
- const hostname2 = sshMatch[1];
5748
+ const hostname = sshMatch[1];
5734
5749
  const pathPart = sshMatch[2];
5735
- if (!hostname2 || !pathPart) return null;
5736
- const normalizedHostname = hostname2.toLowerCase();
5750
+ if (!hostname || !pathPart) return null;
5751
+ const normalizedHostname = hostname.toLowerCase();
5737
5752
  let projectPath = pathPart;
5738
5753
  if (normalizedHostname === "ssh.dev.azure.com" && projectPath.startsWith("v3/")) {
5739
5754
  projectPath = projectPath.substring(3);
@@ -5821,11 +5836,11 @@ var parseScmURL = (scmURL, scmType) => {
5821
5836
  if (sshResult) return sshResult;
5822
5837
  try {
5823
5838
  const url = new URL(scmURL);
5824
- const hostname2 = url.hostname.toLowerCase();
5839
+ const hostname = url.hostname.toLowerCase();
5825
5840
  const projectPath = url.pathname.substring(1).replace(/.git$/i, "");
5826
5841
  const repo = getRepoInfo({
5827
5842
  pathname: projectPath.split("/"),
5828
- hostname: hostname2,
5843
+ hostname,
5829
5844
  scmType
5830
5845
  });
5831
5846
  if (!repo) {
@@ -5835,7 +5850,7 @@ var parseScmURL = (scmURL, scmType) => {
5835
5850
  new URL(scmCloudUrl.Bitbucket).hostname,
5836
5851
  new URL(scmCloudUrl.Ado).hostname
5837
5852
  ];
5838
- if (knownHosts2.includes(hostname2)) {
5853
+ if (knownHosts2.includes(hostname)) {
5839
5854
  return null;
5840
5855
  }
5841
5856
  const pathElements = projectPath.split("/").filter(Boolean);
@@ -5846,7 +5861,7 @@ var parseScmURL = (scmURL, scmType) => {
5846
5861
  const repoName2 = pathElements[pathElements.length - 1] || "";
5847
5862
  return {
5848
5863
  scmType: "Unknown",
5849
- hostname: hostname2,
5864
+ hostname,
5850
5865
  organization: organization2,
5851
5866
  projectPath,
5852
5867
  repoName: repoName2,
@@ -5859,7 +5874,7 @@ var parseScmURL = (scmURL, scmType) => {
5859
5874
  if (!organization.match(NAME_REGEX) || !repoName.match(NAME_REGEX))
5860
5875
  return null;
5861
5876
  const res = {
5862
- hostname: hostname2,
5877
+ hostname,
5863
5878
  organization,
5864
5879
  projectPath,
5865
5880
  repoName,
@@ -6048,8 +6063,8 @@ function normalizeUrl(repoUrl) {
6048
6063
  }
6049
6064
  const sshMatch = trimmedUrl.match(sshPattern);
6050
6065
  if (sshMatch) {
6051
- const [_all, hostname2, reporPath] = sshMatch;
6052
- trimmedUrl = `https://${hostname2}/${reporPath}`;
6066
+ const [_all, hostname, reporPath] = sshMatch;
6067
+ trimmedUrl = `https://${hostname}/${reporPath}`;
6053
6068
  }
6054
6069
  return trimmedUrl;
6055
6070
  }
@@ -6080,17 +6095,17 @@ function getCloudScmLibTypeFromUrl(url) {
6080
6095
  return void 0;
6081
6096
  }
6082
6097
  const urlObject = new URL(url);
6083
- const hostname2 = urlObject.hostname.toLowerCase();
6084
- if (hostname2 === scmCloudHostname.GitLab) {
6098
+ const hostname = urlObject.hostname.toLowerCase();
6099
+ if (hostname === scmCloudHostname.GitLab) {
6085
6100
  return "GITLAB" /* GITLAB */;
6086
6101
  }
6087
- if (hostname2 === scmCloudHostname.GitHub) {
6102
+ if (hostname === scmCloudHostname.GitHub) {
6088
6103
  return "GITHUB" /* GITHUB */;
6089
6104
  }
6090
- if (hostname2 === scmCloudHostname.Ado || hostname2.endsWith(".visualstudio.com")) {
6105
+ if (hostname === scmCloudHostname.Ado || hostname.endsWith(".visualstudio.com")) {
6091
6106
  return "ADO" /* ADO */;
6092
6107
  }
6093
- if (hostname2 === scmCloudHostname.Bitbucket) {
6108
+ if (hostname === scmCloudHostname.Bitbucket) {
6094
6109
  return "BITBUCKET" /* BITBUCKET */;
6095
6110
  }
6096
6111
  return void 0;
@@ -6246,7 +6261,7 @@ function parseAdoOwnerAndRepo(adoUrl) {
6246
6261
  projectName,
6247
6262
  projectPath,
6248
6263
  pathElements,
6249
- hostname: hostname2,
6264
+ hostname,
6250
6265
  protocol
6251
6266
  } = parsingResult;
6252
6267
  return {
@@ -6256,7 +6271,7 @@ function parseAdoOwnerAndRepo(adoUrl) {
6256
6271
  projectPath,
6257
6272
  pathElements,
6258
6273
  prefixPath: parsingResult.prefixPath,
6259
- origin: `${protocol}//${hostname2}`
6274
+ origin: `${protocol}//${hostname}`
6260
6275
  };
6261
6276
  }
6262
6277
  function isValidAdoRepo(url) {
@@ -7467,8 +7482,8 @@ var BitbucketSCMLib = class extends SCMLib {
7467
7482
  if (!parseScmURLRes) {
7468
7483
  throw new InvalidRepoUrlError("invalid repo url");
7469
7484
  }
7470
- const { protocol, hostname: hostname2, organization, repoName } = parseScmURLRes;
7471
- const url = `${protocol}//${hostname2}/${organization}/${repoName}`;
7485
+ const { protocol, hostname, organization, repoName } = parseScmURLRes;
7486
+ const url = `${protocol}//${hostname}/${organization}/${repoName}`;
7472
7487
  switch (authData.authType) {
7473
7488
  case "public": {
7474
7489
  return trimmedUrl;
@@ -7685,6 +7700,7 @@ var REPORT_DEFAULT_FILE_NAME = "report.json";
7685
7700
  init_env();
7686
7701
 
7687
7702
  // src/features/analysis/scm/github/GithubSCMLib.ts
7703
+ import pLimit from "p-limit";
7688
7704
  import { z as z21 } from "zod";
7689
7705
 
7690
7706
  // src/features/analysis/scm/github/github.ts
@@ -8610,6 +8626,7 @@ function getGithubSdk(params = {}) {
8610
8626
  }
8611
8627
 
8612
8628
  // src/features/analysis/scm/github/GithubSCMLib.ts
8629
+ var GITHUB_COMMIT_FETCH_CONCURRENCY = parseInt(process.env["GITHUB_COMMIT_CONCURRENCY"] || "10", 10) || 10;
8613
8630
  function determinePrStatus(state, isDraft) {
8614
8631
  switch (state) {
8615
8632
  case "CLOSED":
@@ -8754,8 +8771,8 @@ var GithubSCMLib = class extends SCMLib {
8754
8771
  if (!res) {
8755
8772
  throw new InvalidRepoUrlError("invalid repo url");
8756
8773
  }
8757
- const { protocol, hostname: hostname2, organization, repoName } = res;
8758
- const downloadUrl = isGithubOnPrem(this.url) ? `${protocol}//${hostname2}/api/v3/repos/${organization}/${repoName}/zipball/${sha}` : `https://api.${hostname2}/repos/${organization}/${repoName}/zipball/${sha}`;
8774
+ const { protocol, hostname, organization, repoName } = res;
8775
+ const downloadUrl = isGithubOnPrem(this.url) ? `${protocol}//${hostname}/api/v3/repos/${organization}/${repoName}/zipball/${sha}` : `https://api.${hostname}/repos/${organization}/${repoName}/zipball/${sha}`;
8759
8776
  return Promise.resolve(downloadUrl);
8760
8777
  }
8761
8778
  async _getUsernameForAuthUrl() {
@@ -8976,12 +8993,15 @@ var GithubSCMLib = class extends SCMLib {
8976
8993
  }),
8977
8994
  this.getPrDiff({ pull_number: prNumber })
8978
8995
  ]);
8996
+ const limit = pLimit(GITHUB_COMMIT_FETCH_CONCURRENCY);
8979
8997
  const commits = await Promise.all(
8980
8998
  commitsRes.data.map(
8981
- (commit) => this.getCommitDiff(commit.sha, {
8982
- repositoryCreatedAt,
8983
- parentCommitTimestamps
8984
- })
8999
+ (commit) => limit(
9000
+ () => this.getCommitDiff(commit.sha, {
9001
+ repositoryCreatedAt,
9002
+ parentCommitTimestamps
9003
+ })
9004
+ )
8985
9005
  )
8986
9006
  );
8987
9007
  const diffLines = filesRes ? await this._attributeLinesViaBlame(pr.head.ref, filesRes.data, commits) : [];
@@ -10552,12 +10572,29 @@ function fortifyNodesToSarifLocations(nodes, unifiedNodePoolParser) {
10552
10572
  import chalk2 from "chalk";
10553
10573
 
10554
10574
  // src/constants.ts
10575
+ import fs7 from "fs";
10555
10576
  import path6 from "path";
10556
10577
  import chalk from "chalk";
10557
10578
  import Debug4 from "debug";
10558
10579
  import * as dotenv from "dotenv";
10559
10580
  import { z as z24 } from "zod";
10560
10581
  var debug5 = Debug4("mobbdev:constants");
10582
+ var runtimeConfigPath = path6.join(
10583
+ getModuleRootDir(),
10584
+ "out",
10585
+ "runtime.config.json"
10586
+ );
10587
+ if (fs7.existsSync(runtimeConfigPath)) {
10588
+ try {
10589
+ const runtimeConfig = JSON.parse(
10590
+ fs7.readFileSync(runtimeConfigPath, "utf-8")
10591
+ );
10592
+ Object.assign(process.env, runtimeConfig);
10593
+ debug5("Loaded runtime config from %s", runtimeConfigPath);
10594
+ } catch (e) {
10595
+ debug5("Failed to load runtime config: %o", e);
10596
+ }
10597
+ }
10561
10598
  dotenv.config({ path: path6.join(getModuleRootDir(), ".env") });
10562
10599
  var DEFAULT_API_URL = "https://api.mobb.ai/v1/graphql";
10563
10600
  var DEFAULT_WEB_APP_URL = "https://app.mobb.ai";
@@ -10784,7 +10821,7 @@ function convertToSarifBuilder(args) {
10784
10821
  ).help().demandOption(["input-file-path", "input-file-format", "output-file-path"]);
10785
10822
  }
10786
10823
  async function validateConvertToSarifOptions(args) {
10787
- if (!fs7.existsSync(args.inputFilePath)) {
10824
+ if (!fs8.existsSync(args.inputFilePath)) {
10788
10825
  throw new CliError(
10789
10826
  "\nError: --input-file-path flag should point to an existing file"
10790
10827
  );
@@ -10816,14 +10853,14 @@ var ScanContext = {
10816
10853
  };
10817
10854
 
10818
10855
  // src/args/commands/analyze.ts
10819
- import fs10 from "fs";
10856
+ import fs11 from "fs";
10820
10857
  import chalk8 from "chalk";
10821
10858
 
10822
10859
  // src/commands/index.ts
10823
10860
  import chalkAnimation from "chalk-animation";
10824
10861
 
10825
10862
  // src/features/analysis/index.ts
10826
- import fs9 from "fs";
10863
+ import fs10 from "fs";
10827
10864
  import fsPromises2 from "fs/promises";
10828
10865
  import path9 from "path";
10829
10866
  import { env as env2 } from "process";
@@ -11119,6 +11156,19 @@ var REPORT_STATE_CHECK_DELAY = 5 * 1e3;
11119
11156
  function getProxyAgent(url) {
11120
11157
  try {
11121
11158
  const parsedUrl = new URL(url);
11159
+ const hostname = parsedUrl.hostname.toLowerCase();
11160
+ if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1" || hostname === "[::1]") {
11161
+ debug6("Skipping proxy for localhost URL: %s", url);
11162
+ return void 0;
11163
+ }
11164
+ const noProxy = process.env["NO_PROXY"] || process.env["no_proxy"];
11165
+ if (noProxy) {
11166
+ const noProxyList = noProxy.split(",").map((h) => h.trim().toLowerCase());
11167
+ if (noProxyList.includes(hostname) || noProxyList.includes("*")) {
11168
+ debug6("Skipping proxy due to NO_PROXY for: %s", url);
11169
+ return void 0;
11170
+ }
11171
+ }
11122
11172
  const isHttp = parsedUrl.protocol === "http:";
11123
11173
  const isHttps = parsedUrl.protocol === "https:";
11124
11174
  const proxy = isHttps ? HTTPS_PROXY || HTTP_PROXY : isHttp ? HTTP_PROXY : null;
@@ -11528,6 +11578,9 @@ var GQLClient = class {
11528
11578
  async getAIBlameAttributionPromptSummary(variables) {
11529
11579
  return await this._clientSdk.GetPromptSummary(variables);
11530
11580
  }
11581
+ async getTracyDiffUploadUrl(variables) {
11582
+ return await this._clientSdk.GetTracyDiffUploadUrl(variables);
11583
+ }
11531
11584
  };
11532
11585
 
11533
11586
  // src/mcp/services/types.ts
@@ -11551,9 +11604,9 @@ function createMcpLoginContext(trigger) {
11551
11604
  ide: detectIDE()
11552
11605
  };
11553
11606
  }
11554
- function buildLoginUrl(baseUrl, loginId, hostname2, context) {
11607
+ function buildLoginUrl(baseUrl, loginId, hostname, context) {
11555
11608
  const url = new URL(`${baseUrl}/${loginId}`);
11556
- url.searchParams.set("hostname", hostname2);
11609
+ url.searchParams.set("hostname", hostname);
11557
11610
  url.searchParams.set("trigger", context.trigger);
11558
11611
  url.searchParams.set("source", context.source);
11559
11612
  if (context.ide) {
@@ -12377,7 +12430,7 @@ async function getGitInfo(srcDirPath) {
12377
12430
 
12378
12431
  // src/features/analysis/pack.ts
12379
12432
  init_configs();
12380
- import fs8 from "fs";
12433
+ import fs9 from "fs";
12381
12434
  import path7 from "path";
12382
12435
  import AdmZip from "adm-zip";
12383
12436
  import Debug13 from "debug";
@@ -12454,7 +12507,7 @@ async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
12454
12507
  continue;
12455
12508
  }
12456
12509
  }
12457
- if (fs8.lstatSync(absFilepath).size > MCP_MAX_FILE_SIZE) {
12510
+ if (fs9.lstatSync(absFilepath).size > MCP_MAX_FILE_SIZE) {
12458
12511
  debug14("ignoring %s because the size is > 5MB", filepath);
12459
12512
  continue;
12460
12513
  }
@@ -12463,10 +12516,10 @@ async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
12463
12516
  try {
12464
12517
  data = await git.showBuffer([`HEAD:./${filepath}`]);
12465
12518
  } catch {
12466
- data = fs8.readFileSync(absFilepath);
12519
+ data = fs9.readFileSync(absFilepath);
12467
12520
  }
12468
12521
  } else {
12469
- data = fs8.readFileSync(absFilepath);
12522
+ data = fs9.readFileSync(absFilepath);
12470
12523
  }
12471
12524
  if (isBinary2(null, data)) {
12472
12525
  debug14("ignoring %s because is seems to be a binary file", filepath);
@@ -12645,8 +12698,8 @@ if (typeof __filename !== "undefined") {
12645
12698
  }
12646
12699
  var costumeRequire = createRequire(moduleUrl);
12647
12700
  var getCheckmarxPath = () => {
12648
- const os11 = type();
12649
- const cxFileName = os11 === "Windows_NT" ? "cx.exe" : "cx";
12701
+ const os12 = type();
12702
+ const cxFileName = os12 === "Windows_NT" ? "cx.exe" : "cx";
12650
12703
  try {
12651
12704
  return costumeRequire.resolve(`.bin/${cxFileName}`);
12652
12705
  } catch (e) {
@@ -12927,13 +12980,13 @@ async function downloadRepo({
12927
12980
  repoSpinner.error({ text: "\u{1F4BE} Repo download failed" });
12928
12981
  throw new Error(`Can't access ${chalk6.bold(repoUrl)}`);
12929
12982
  }
12930
- const fileWriterStream = fs9.createWriteStream(zipFilePath);
12983
+ const fileWriterStream = fs10.createWriteStream(zipFilePath);
12931
12984
  if (!response.body) {
12932
12985
  throw new Error("Response body is empty");
12933
12986
  }
12934
12987
  await pipeline(response.body, fileWriterStream);
12935
12988
  await extract(zipFilePath, { dir: dirname });
12936
- const repoRoot = fs9.readdirSync(dirname, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name)[0];
12989
+ const repoRoot = fs10.readdirSync(dirname, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name)[0];
12937
12990
  if (!repoRoot) {
12938
12991
  throw new Error("Repo root not found");
12939
12992
  }
@@ -13747,7 +13800,7 @@ function analyzeBuilder(yargs2) {
13747
13800
  ).help();
13748
13801
  }
13749
13802
  function validateAnalyzeOptions(argv) {
13750
- if (argv.f && !fs10.existsSync(argv.f)) {
13803
+ if (argv.f && !fs11.existsSync(argv.f)) {
13751
13804
  throw new CliError(`
13752
13805
  Can't access ${chalk8.bold(argv.f)}`);
13753
13806
  }
@@ -13795,12 +13848,101 @@ import { z as z32 } from "zod";
13795
13848
 
13796
13849
  // src/args/commands/upload_ai_blame.ts
13797
13850
  import fsPromises3 from "fs/promises";
13798
- import * as os2 from "os";
13851
+ import * as os3 from "os";
13799
13852
  import path11 from "path";
13800
13853
  import chalk9 from "chalk";
13801
13854
  import { withFile } from "tmp-promise";
13802
13855
  import z31 from "zod";
13803
13856
 
13857
+ // src/utils/computerName.ts
13858
+ import { execSync } from "child_process";
13859
+ import os2 from "os";
13860
+ var STABLE_COMPUTER_NAME_CONFIG_KEY = "stableComputerName";
13861
+ var HOSTNAME_SUFFIXES = [
13862
+ // Cloud providers (must be first - most specific)
13863
+ ".ec2.internal",
13864
+ ".compute.internal",
13865
+ ".cloudapp.net",
13866
+ // mDNS/Bonjour
13867
+ ".local",
13868
+ ".localhost",
13869
+ ".localdomain",
13870
+ // Home networks
13871
+ ".lan",
13872
+ ".home",
13873
+ ".homelan",
13874
+ // Corporate networks
13875
+ ".corp",
13876
+ ".internal",
13877
+ ".intranet",
13878
+ ".domain",
13879
+ ".work",
13880
+ ".office",
13881
+ // Container environments
13882
+ ".docker",
13883
+ ".kubernetes",
13884
+ ".k8s"
13885
+ ];
13886
+ function getOsSpecificComputerName() {
13887
+ const platform2 = os2.platform();
13888
+ try {
13889
+ if (platform2 === "darwin") {
13890
+ const result = execSync("scutil --get LocalHostName", {
13891
+ encoding: "utf-8",
13892
+ timeout: 1e3
13893
+ });
13894
+ return result.trim();
13895
+ } else if (platform2 === "win32") {
13896
+ return process.env["COMPUTERNAME"] || null;
13897
+ } else {
13898
+ try {
13899
+ const result2 = execSync("hostnamectl --static", {
13900
+ encoding: "utf-8",
13901
+ timeout: 1e3
13902
+ });
13903
+ const hostname = result2.trim();
13904
+ if (hostname) return hostname;
13905
+ } catch {
13906
+ }
13907
+ const result = execSync("cat /etc/hostname", {
13908
+ encoding: "utf-8",
13909
+ timeout: 1e3
13910
+ });
13911
+ return result.trim();
13912
+ }
13913
+ } catch (error) {
13914
+ return null;
13915
+ }
13916
+ }
13917
+ function stripHostnameSuffixes(hostname) {
13918
+ if (!hostname) return hostname;
13919
+ let normalized = hostname;
13920
+ for (const suffix of HOSTNAME_SUFFIXES) {
13921
+ if (normalized.endsWith(suffix)) {
13922
+ normalized = normalized.slice(0, -suffix.length);
13923
+ break;
13924
+ }
13925
+ }
13926
+ return normalized;
13927
+ }
13928
+ function generateStableComputerName() {
13929
+ const osSpecificName = getOsSpecificComputerName();
13930
+ if (osSpecificName) {
13931
+ return osSpecificName;
13932
+ }
13933
+ const currentHostname = os2.hostname();
13934
+ return stripHostnameSuffixes(currentHostname);
13935
+ }
13936
+ function getStableComputerName() {
13937
+ const cached = configStore.get(STABLE_COMPUTER_NAME_CONFIG_KEY);
13938
+ if (cached) {
13939
+ return cached;
13940
+ }
13941
+ const currentName = generateStableComputerName();
13942
+ configStore.set(STABLE_COMPUTER_NAME_CONFIG_KEY, currentName);
13943
+ return currentName;
13944
+ }
13945
+
13804
13946
  // src/utils/sanitize-sensitive-data.ts
13805
13947
  import { OpenRedaction } from "@openredaction/openredaction";
13806
13948
  var openRedaction = new OpenRedaction({
@@ -13985,12 +14127,12 @@ var PromptItemArrayZ = z31.array(PromptItemZ);
13985
14127
  function getSystemInfo() {
13986
14128
  let userName;
13987
14129
  try {
13988
- userName = os2.userInfo().username;
14130
+ userName = os3.userInfo().username;
13989
14131
  } catch {
13990
14132
  userName = void 0;
13991
14133
  }
13992
14134
  return {
13993
- computerName: os2.hostname(),
14135
+ computerName: getStableComputerName(),
13994
14136
  userName
13995
14137
  };
13996
14138
  }
@@ -14506,10 +14648,10 @@ async function processAndUploadHookData() {
14506
14648
 
14507
14649
  // src/features/claude_code/install_hook.ts
14508
14650
  import fsPromises5 from "fs/promises";
14509
- import os3 from "os";
14651
+ import os4 from "os";
14510
14652
  import path12 from "path";
14511
14653
  import chalk10 from "chalk";
14512
- var CLAUDE_SETTINGS_PATH = path12.join(os3.homedir(), ".claude", "settings.json");
14654
+ var CLAUDE_SETTINGS_PATH = path12.join(os4.homedir(), ".claude", "settings.json");
14513
14655
  async function claudeSettingsExists() {
14514
14656
  try {
14515
14657
  await fsPromises5.access(CLAUDE_SETTINGS_PATH);
@@ -14972,7 +15114,7 @@ var GetLatestReportByRepoUrlResponseSchema = z33.object({
14972
15114
 
14973
15115
  // src/mcp/services/McpAuthService.ts
14974
15116
  import crypto2 from "crypto";
14975
- import os4 from "os";
15117
+ import os5 from "os";
14976
15118
  import open4 from "open";
14977
15119
  init_configs();
14978
15120
  var McpAuthService = class {
@@ -15017,7 +15159,7 @@ var McpAuthService = class {
15017
15159
  }
15018
15160
  logDebug(`cli login created ${loginId}`);
15019
15161
  const webLoginUrl = `${WEB_APP_URL}/mvs-login`;
15020
- const browserUrl = loginContext ? buildLoginUrl(webLoginUrl, loginId, os4.hostname(), loginContext) : `${webLoginUrl}/${loginId}?hostname=${os4.hostname()}`;
15162
+ const browserUrl = loginContext ? buildLoginUrl(webLoginUrl, loginId, os5.hostname(), loginContext) : `${webLoginUrl}/${loginId}?hostname=${os5.hostname()}`;
15021
15163
  await this.openBrowser(browserUrl, isBackgoundCall);
15022
15164
  logDebug(`waiting for login to complete`);
15023
15165
  let newApiToken = null;
@@ -15722,14 +15864,14 @@ async function createAuthenticatedMcpGQLClient({
15722
15864
  }
15723
15865
 
15724
15866
  // src/mcp/services/McpUsageService/host.ts
15725
- import { execSync } from "child_process";
15726
- import fs11 from "fs";
15727
- import os5 from "os";
15867
+ import { execSync as execSync2 } from "child_process";
15868
+ import fs12 from "fs";
15869
+ import os6 from "os";
15728
15870
  import path13 from "path";
15729
15871
  var IDEs = ["cursor", "windsurf", "webstorm", "vscode", "claude"];
15730
15872
  var runCommand = (cmd) => {
15731
15873
  try {
15732
- return execSync(cmd, { encoding: "utf8" }).trim();
15874
+ return execSync2(cmd, { encoding: "utf8" }).trim();
15733
15875
  } catch {
15734
15876
  return "";
15735
15877
  }
@@ -15739,18 +15881,18 @@ var gitInfo = {
15739
15881
  email: runCommand("git config user.email")
15740
15882
  };
15741
15883
  var getClaudeWorkspacePaths = () => {
15742
- const home = os5.homedir();
15884
+ const home = os6.homedir();
15743
15885
  const claudeIdePath = path13.join(home, ".claude", "ide");
15744
15886
  const workspacePaths = [];
15745
- if (!fs11.existsSync(claudeIdePath)) {
15887
+ if (!fs12.existsSync(claudeIdePath)) {
15746
15888
  return workspacePaths;
15747
15889
  }
15748
15890
  try {
15749
- const lockFiles = fs11.readdirSync(claudeIdePath).filter((file) => file.endsWith(".lock"));
15891
+ const lockFiles = fs12.readdirSync(claudeIdePath).filter((file) => file.endsWith(".lock"));
15750
15892
  for (const lockFile of lockFiles) {
15751
15893
  const lockFilePath = path13.join(claudeIdePath, lockFile);
15752
15894
  try {
15753
- const lockContent = JSON.parse(fs11.readFileSync(lockFilePath, "utf8"));
15895
+ const lockContent = JSON.parse(fs12.readFileSync(lockFilePath, "utf8"));
15754
15896
  if (lockContent.workspaceFolders && Array.isArray(lockContent.workspaceFolders)) {
15755
15897
  workspacePaths.push(...lockContent.workspaceFolders);
15756
15898
  }
@@ -15768,7 +15910,7 @@ var getClaudeWorkspacePaths = () => {
15768
15910
  return workspacePaths;
15769
15911
  };
15770
15912
  var getMCPConfigPaths = (hostName) => {
15771
- const home = os5.homedir();
15913
+ const home = os6.homedir();
15772
15914
  const currentDir = process.env["WORKSPACE_FOLDER_PATHS"] || process.env["PWD"] || process.cwd();
15773
15915
  switch (hostName.toLowerCase()) {
15774
15916
  case "cursor":
@@ -15816,9 +15958,9 @@ var getMCPConfigPaths = (hostName) => {
15816
15958
  }
15817
15959
  };
15818
15960
  var readConfigFile = (filePath) => {
15819
- if (!fs11.existsSync(filePath)) return null;
15961
+ if (!fs12.existsSync(filePath)) return null;
15820
15962
  try {
15821
- return JSON.parse(fs11.readFileSync(filePath, "utf8"));
15963
+ return JSON.parse(fs12.readFileSync(filePath, "utf8"));
15822
15964
  } catch (error) {
15823
15965
  logWarn(`[UsageService] Failed to read MCP config: ${filePath}`);
15824
15966
  return null;
@@ -15858,14 +16000,14 @@ var readMCPConfig = (hostName) => {
15858
16000
  };
15859
16001
  var getRunningProcesses = () => {
15860
16002
  try {
15861
- return os5.platform() === "win32" ? execSync("tasklist", { encoding: "utf8" }) : execSync("ps aux", { encoding: "utf8" });
16003
+ return os6.platform() === "win32" ? execSync2("tasklist", { encoding: "utf8" }) : execSync2("ps aux", { encoding: "utf8" });
15862
16004
  } catch {
15863
16005
  return "";
15864
16006
  }
15865
16007
  };
15866
16008
  var checkUrlAccessibility = (url) => {
15867
16009
  try {
15868
- execSync(`curl -s --connect-timeout 5 --max-time 3 "${url}"`, {
16010
+ execSync2(`curl -s --connect-timeout 5 --max-time 3 "${url}"`, {
15869
16011
  encoding: "utf8",
15870
16012
  stdio: "ignore"
15871
16013
  });
@@ -15933,17 +16075,17 @@ var versionCommands = {
15933
16075
  }
15934
16076
  };
15935
16077
  var getProcessInfo = (pid) => {
15936
- const platform2 = os5.platform();
16078
+ const platform2 = os6.platform();
15937
16079
  try {
15938
16080
  if (platform2 === "linux" || platform2 === "darwin") {
15939
- const output = execSync(`ps -o pid=,ppid=,comm= -p ${pid}`, {
16081
+ const output = execSync2(`ps -o pid=,ppid=,comm= -p ${pid}`, {
15940
16082
  stdio: ["pipe", "pipe", "ignore"]
15941
16083
  }).toString().trim();
15942
16084
  if (!output) return null;
15943
16085
  const [pidStr, ppid, ...cmd] = output.trim().split(/\s+/);
15944
16086
  return { pid: pidStr ?? "", ppid: ppid ?? "", cmd: cmd.join(" ") };
15945
16087
  } else if (platform2 === "win32") {
15946
- const output = execSync(
16088
+ const output = execSync2(
15947
16089
  `powershell -Command "Get-CimInstance Win32_Process -Filter 'ProcessId=${pid}' | Select-Object ProcessId,ParentProcessId,Name | Format-Table -HideTableHeaders"`,
15948
16090
  { stdio: ["pipe", "pipe", "ignore"] }
15949
16091
  ).toString().trim();
@@ -16052,11 +16194,11 @@ var getHostInfo = (additionalMcpList) => {
16052
16194
  const config2 = allConfigs[ide] || null;
16053
16195
  const ideName = ide.charAt(0).toUpperCase() + ide.slice(1) || "Unknown";
16054
16196
  let ideVersion = "Unknown";
16055
- const platform2 = os5.platform();
16197
+ const platform2 = os6.platform();
16056
16198
  const cmds = versionCommands[ideName]?.[platform2] ?? [];
16057
16199
  for (const cmd of cmds) {
16058
16200
  try {
16059
- const versionOutput = cmd.includes("grep") || cmd.includes("--version") || cmd.includes("sed") ? execSync(cmd, { stdio: ["pipe", "pipe", "ignore"] }).toString().split("\n")[0] ?? "" : cmd;
16201
+ const versionOutput = cmd.includes("grep") || cmd.includes("--version") || cmd.includes("sed") ? execSync2(cmd, { stdio: ["pipe", "pipe", "ignore"] }).toString().split("\n")[0] ?? "" : cmd;
16060
16202
  if (versionOutput && versionOutput !== "Unknown") {
16061
16203
  ideVersion = versionOutput;
16062
16204
  break;
@@ -16085,14 +16227,14 @@ var getHostInfo = (additionalMcpList) => {
16085
16227
 
16086
16228
  // src/mcp/services/McpUsageService/McpUsageService.ts
16087
16229
  import fetch5 from "node-fetch";
16088
- import os7 from "os";
16230
+ import os8 from "os";
16089
16231
  import { v4 as uuidv43, v5 as uuidv5 } from "uuid";
16090
16232
  init_configs();
16091
16233
 
16092
16234
  // src/mcp/services/McpUsageService/system.ts
16093
16235
  init_configs();
16094
- import fs12 from "fs";
16095
- import os6 from "os";
16236
+ import fs13 from "fs";
16237
+ import os7 from "os";
16096
16238
  import path14 from "path";
16097
16239
  var MAX_DEPTH = 2;
16098
16240
  var patterns = ["mcp", "claude"];
@@ -16102,7 +16244,7 @@ var isFileMatch = (fileName) => {
16102
16244
  };
16103
16245
  var safeAccess = async (filePath) => {
16104
16246
  try {
16105
- await fs12.promises.access(filePath, fs12.constants.R_OK);
16247
+ await fs13.promises.access(filePath, fs13.constants.R_OK);
16106
16248
  return true;
16107
16249
  } catch {
16108
16250
  return false;
@@ -16111,7 +16253,7 @@ var safeAccess = async (filePath) => {
16111
16253
  var searchDir = async (dir, depth = 0) => {
16112
16254
  const results = [];
16113
16255
  if (depth > MAX_DEPTH) return results;
16114
- const entries = await fs12.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
16256
+ const entries = await fs13.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
16115
16257
  for (const entry of entries) {
16116
16258
  const fullPath = path14.join(dir, entry.name);
16117
16259
  if (entry.isFile() && isFileMatch(entry.name)) {
@@ -16127,8 +16269,8 @@ var searchDir = async (dir, depth = 0) => {
16127
16269
  };
16128
16270
  var findSystemMCPConfigs = async () => {
16129
16271
  try {
16130
- const home = os6.homedir();
16131
- const platform2 = os6.platform();
16272
+ const home = os7.homedir();
16273
+ const platform2 = os7.platform();
16132
16274
  const knownDirs = platform2 === "win32" ? [
16133
16275
  path14.join(home, ".cursor"),
16134
16276
  path14.join(home, "Documents"),
@@ -16149,7 +16291,7 @@ var findSystemMCPConfigs = async () => {
16149
16291
  );
16150
16292
  const searchPromise = Promise.all(
16151
16293
  knownDirs.map(
16152
- (dir) => fs12.existsSync(dir) ? searchDir(dir) : Promise.resolve([])
16294
+ (dir) => fs13.existsSync(dir) ? searchDir(dir) : Promise.resolve([])
16153
16295
  )
16154
16296
  ).then((results) => results.flat());
16155
16297
  return await Promise.race([timeoutPromise, searchPromise]);
@@ -16200,7 +16342,7 @@ var McpUsageService = class {
16200
16342
  generateHostId() {
16201
16343
  const stored = configStore.get(this.configKey);
16202
16344
  if (stored?.mcpHostId) return stored.mcpHostId;
16203
- const interfaces = os7.networkInterfaces();
16345
+ const interfaces = os8.networkInterfaces();
16204
16346
  const macs = [];
16205
16347
  for (const iface of Object.values(interfaces)) {
16206
16348
  if (!iface) continue;
@@ -16208,7 +16350,7 @@ var McpUsageService = class {
16208
16350
  if (net.mac && net.mac !== "00:00:00:00:00:00") macs.push(net.mac);
16209
16351
  }
16210
16352
  }
16211
- const macString = macs.length ? macs.sort().join(",") : `${os7.hostname()}-${uuidv43()}`;
16353
+ const macString = macs.length ? macs.sort().join(",") : `${os8.hostname()}-${uuidv43()}`;
16212
16354
  const hostId = uuidv5(macString, uuidv5.DNS);
16213
16355
  logDebug("[UsageService] Generated new host ID", { hostId });
16214
16356
  return hostId;
@@ -16231,7 +16373,7 @@ var McpUsageService = class {
16231
16373
  mcpHostId,
16232
16374
  organizationId,
16233
16375
  mcpVersion: packageJson.version,
16234
- mcpOsName: os7.platform(),
16376
+ mcpOsName: os8.platform(),
16235
16377
  mcps: JSON.stringify(mcps),
16236
16378
  status,
16237
16379
  userName: user.name,
@@ -18551,30 +18693,30 @@ For a complete security audit workflow, use the \`full-security-audit\` prompt.
18551
18693
  };
18552
18694
 
18553
18695
  // src/mcp/services/McpDetectionService/CursorMcpDetectionService.ts
18554
- import * as fs15 from "fs";
18555
- import * as os9 from "os";
18696
+ import * as fs16 from "fs";
18697
+ import * as os10 from "os";
18556
18698
  import * as path16 from "path";
18557
18699
 
18558
18700
  // src/mcp/services/McpDetectionService/BaseMcpDetectionService.ts
18559
18701
  init_configs();
18560
- import * as fs14 from "fs";
18702
+ import * as fs15 from "fs";
18561
18703
  import fetch6 from "node-fetch";
18562
18704
  import * as path15 from "path";
18563
18705
 
18564
18706
  // src/mcp/services/McpDetectionService/McpDetectionServiceUtils.ts
18565
- import * as fs13 from "fs";
18566
- import * as os8 from "os";
18707
+ import * as fs14 from "fs";
18708
+ import * as os9 from "os";
18567
18709
 
18568
18710
  // src/mcp/services/McpDetectionService/VscodeMcpDetectionService.ts
18569
- import * as fs16 from "fs";
18570
- import * as os10 from "os";
18711
+ import * as fs17 from "fs";
18712
+ import * as os11 from "os";
18571
18713
  import * as path17 from "path";
18572
18714
 
18573
18715
  // src/mcp/tools/checkForNewAvailableFixes/CheckForNewAvailableFixesTool.ts
18574
18716
  import { z as z42 } from "zod";
18575
18717
 
18576
18718
  // src/mcp/services/PathValidation.ts
18577
- import fs17 from "fs";
18719
+ import fs18 from "fs";
18578
18720
  import path18 from "path";
18579
18721
  async function validatePath(inputPath) {
18580
18722
  logDebug("Validating MCP path", { inputPath });
@@ -18634,7 +18776,7 @@ async function validatePath(inputPath) {
18634
18776
  logDebug("Path validation successful", { inputPath });
18635
18777
  logDebug("Checking path existence", { inputPath });
18636
18778
  try {
18637
- await fs17.promises.access(inputPath);
18779
+ await fs18.promises.access(inputPath);
18638
18780
  logDebug("Path exists and is accessible", { inputPath });
18639
18781
  WorkspaceService.setKnownWorkspacePath(inputPath);
18640
18782
  logDebug("Stored validated path in WorkspaceService", { inputPath });
@@ -19261,7 +19403,7 @@ If you wish to scan files that were recently changed in your git history call th
19261
19403
  init_FileUtils();
19262
19404
  init_GitService();
19263
19405
  init_configs();
19264
- import fs18 from "fs/promises";
19406
+ import fs19 from "fs/promises";
19265
19407
  import nodePath from "path";
19266
19408
  var getLocalFiles = async ({
19267
19409
  path: path22,
@@ -19279,7 +19421,7 @@ var getLocalFiles = async ({
19279
19421
  scanRecentlyChangedFiles
19280
19422
  });
19281
19423
  try {
19282
- const resolvedRepoPath = await fs18.realpath(path22);
19424
+ const resolvedRepoPath = await fs19.realpath(path22);
19283
19425
  logDebug(`[${scanContext}] Resolved repository path`, {
19284
19426
  resolvedRepoPath,
19285
19427
  originalPath: path22
@@ -19359,7 +19501,7 @@ var getLocalFiles = async ({
19359
19501
  absoluteFilePath
19360
19502
  );
19361
19503
  try {
19362
- const fileStat = await fs18.stat(absoluteFilePath);
19504
+ const fileStat = await fs19.stat(absoluteFilePath);
19363
19505
  return {
19364
19506
  filename: nodePath.basename(absoluteFilePath),
19365
19507
  relativePath,
@@ -19394,7 +19536,7 @@ var getLocalFiles = async ({
19394
19536
  };
19395
19537
 
19396
19538
  // src/mcp/services/LocalMobbFolderService.ts
19397
- import fs19 from "fs";
19539
+ import fs20 from "fs";
19398
19540
  import path19 from "path";
19399
19541
  import { z as z41 } from "zod";
19400
19542
  init_GitService();
@@ -19486,15 +19628,15 @@ var LocalMobbFolderService = class {
19486
19628
  this.repoPath,
19487
19629
  this.defaultMobbFolderName
19488
19630
  );
19489
- if (!fs19.existsSync(mobbFolderPath)) {
19631
+ if (!fs20.existsSync(mobbFolderPath)) {
19490
19632
  logInfo("[LocalMobbFolderService] Creating .mobb folder", {
19491
19633
  mobbFolderPath
19492
19634
  });
19493
- fs19.mkdirSync(mobbFolderPath, { recursive: true });
19635
+ fs20.mkdirSync(mobbFolderPath, { recursive: true });
19494
19636
  } else {
19495
19637
  logDebug("[LocalMobbFolderService] .mobb folder already exists");
19496
19638
  }
19497
- const stats = fs19.statSync(mobbFolderPath);
19639
+ const stats = fs20.statSync(mobbFolderPath);
19498
19640
  if (!stats.isDirectory()) {
19499
19641
  throw new Error(`Path exists but is not a directory: ${mobbFolderPath}`);
19500
19642
  }
@@ -19535,13 +19677,13 @@ var LocalMobbFolderService = class {
19535
19677
  logDebug("[LocalMobbFolderService] Git repository validated successfully");
19536
19678
  } else {
19537
19679
  try {
19538
- const stats = fs19.statSync(this.repoPath);
19680
+ const stats = fs20.statSync(this.repoPath);
19539
19681
  if (!stats.isDirectory()) {
19540
19682
  throw new Error(
19541
19683
  `Path exists but is not a directory: ${this.repoPath}`
19542
19684
  );
19543
19685
  }
19544
- fs19.accessSync(this.repoPath, fs19.constants.R_OK | fs19.constants.W_OK);
19686
+ fs20.accessSync(this.repoPath, fs20.constants.R_OK | fs20.constants.W_OK);
19545
19687
  logDebug(
19546
19688
  "[LocalMobbFolderService] Non-git directory validated successfully"
19547
19689
  );
@@ -19655,7 +19797,7 @@ var LocalMobbFolderService = class {
19655
19797
  baseFileName
19656
19798
  );
19657
19799
  const filePath = path19.join(mobbFolderPath, uniqueFileName);
19658
- await fs19.promises.writeFile(filePath, patch, "utf8");
19800
+ await fs20.promises.writeFile(filePath, patch, "utf8");
19659
19801
  logInfo("[LocalMobbFolderService] Patch saved successfully", {
19660
19802
  filePath,
19661
19803
  fileName: uniqueFileName,
@@ -19716,7 +19858,7 @@ var LocalMobbFolderService = class {
19716
19858
  const extension = path19.parse(baseFileName).ext;
19717
19859
  let uniqueFileName = baseFileName;
19718
19860
  let index = 1;
19719
- while (fs19.existsSync(path19.join(folderPath, uniqueFileName))) {
19861
+ while (fs20.existsSync(path19.join(folderPath, uniqueFileName))) {
19720
19862
  uniqueFileName = `${baseName}-${index}${extension}`;
19721
19863
  index++;
19722
19864
  if (index > 1e3) {
@@ -19750,15 +19892,15 @@ var LocalMobbFolderService = class {
19750
19892
  const patchInfoPath = path19.join(mobbFolderPath, "patchInfo.md");
19751
19893
  const markdownContent = this.generateFixMarkdown(fix, savedPatchFileName);
19752
19894
  let existingContent = "";
19753
- if (fs19.existsSync(patchInfoPath)) {
19754
- existingContent = await fs19.promises.readFile(patchInfoPath, "utf8");
19895
+ if (fs20.existsSync(patchInfoPath)) {
19896
+ existingContent = await fs20.promises.readFile(patchInfoPath, "utf8");
19755
19897
  logDebug("[LocalMobbFolderService] Existing patchInfo.md found");
19756
19898
  } else {
19757
19899
  logDebug("[LocalMobbFolderService] Creating new patchInfo.md file");
19758
19900
  }
19759
19901
  const separator = existingContent ? "\n\n================================================================================\n\n" : "";
19760
19902
  const updatedContent = `${markdownContent}${separator}${existingContent}`;
19761
- await fs19.promises.writeFile(patchInfoPath, updatedContent, "utf8");
19903
+ await fs20.promises.writeFile(patchInfoPath, updatedContent, "utf8");
19762
19904
  logInfo("[LocalMobbFolderService] Patch info logged successfully", {
19763
19905
  patchInfoPath,
19764
19906
  fixId: fix.id,
@@ -20131,7 +20273,7 @@ import {
20131
20273
  unlinkSync,
20132
20274
  writeFileSync
20133
20275
  } from "fs";
20134
- import fs20 from "fs/promises";
20276
+ import fs21 from "fs/promises";
20135
20277
  import parseDiff2 from "parse-diff";
20136
20278
  import path20 from "path";
20137
20279
  var PatchApplicationService = class {
@@ -20652,7 +20794,7 @@ var PatchApplicationService = class {
20652
20794
  try {
20653
20795
  const absolutePath = path20.resolve(repositoryPath, targetFile);
20654
20796
  if (existsSync6(absolutePath)) {
20655
- const stats = await fs20.stat(absolutePath);
20797
+ const stats = await fs21.stat(absolutePath);
20656
20798
  const fileModTime = stats.mtime.getTime();
20657
20799
  if (fileModTime > scanStartTime) {
20658
20800
  logError(
@@ -20693,7 +20835,7 @@ var PatchApplicationService = class {
20693
20835
  const appliedFixes = [];
20694
20836
  const failedFixes = [];
20695
20837
  const skippedFixes = [];
20696
- const resolvedRepoPath = await fs20.realpath(repositoryPath);
20838
+ const resolvedRepoPath = await fs21.realpath(repositoryPath);
20697
20839
  logInfo(
20698
20840
  `[${scanContext}] Starting patch application for ${fixes.length} fixes`,
20699
20841
  {
@@ -21120,7 +21262,7 @@ init_configs();
21120
21262
 
21121
21263
  // src/mcp/services/FileOperations.ts
21122
21264
  init_FileUtils();
21123
- import fs21 from "fs";
21265
+ import fs22 from "fs";
21124
21266
  import path21 from "path";
21125
21267
  import AdmZip2 from "adm-zip";
21126
21268
  var FileOperations = class {
@@ -21203,7 +21345,7 @@ var FileOperations = class {
21203
21345
  continue;
21204
21346
  }
21205
21347
  try {
21206
- await fs21.promises.access(absoluteFilepath, fs21.constants.R_OK);
21348
+ await fs22.promises.access(absoluteFilepath, fs22.constants.R_OK);
21207
21349
  validatedPaths.push(filepath);
21208
21350
  } catch (error) {
21209
21351
  logDebug(
@@ -21222,7 +21364,7 @@ var FileOperations = class {
21222
21364
  const fileDataArray = [];
21223
21365
  for (const absolutePath of filePaths) {
21224
21366
  try {
21225
- const content = await fs21.promises.readFile(absolutePath);
21367
+ const content = await fs22.promises.readFile(absolutePath);
21226
21368
  const relativePath = path21.basename(absolutePath);
21227
21369
  fileDataArray.push({
21228
21370
  relativePath,
@@ -21248,7 +21390,7 @@ var FileOperations = class {
21248
21390
  relativeFilepath
21249
21391
  }) {
21250
21392
  try {
21251
- return await fs21.promises.readFile(absoluteFilepath);
21393
+ return await fs22.promises.readFile(absoluteFilepath);
21252
21394
  } catch (fsError) {
21253
21395
  logError(
21254
21396
  `[FileOperations] Failed to read ${relativeFilepath} from filesystem: ${fsError}`
@@ -22813,7 +22955,7 @@ var mcpHandler = async (_args) => {
22813
22955
  };
22814
22956
 
22815
22957
  // src/args/commands/review.ts
22816
- import fs22 from "fs";
22958
+ import fs23 from "fs";
22817
22959
  import chalk11 from "chalk";
22818
22960
  function reviewBuilder(yargs2) {
22819
22961
  return yargs2.option("f", {
@@ -22850,7 +22992,7 @@ function reviewBuilder(yargs2) {
22850
22992
  ).help();
22851
22993
  }
22852
22994
  function validateReviewOptions(argv) {
22853
- if (!fs22.existsSync(argv.f)) {
22995
+ if (!fs23.existsSync(argv.f)) {
22854
22996
  throw new CliError(`
22855
22997
  Can't access ${chalk11.bold(argv.f)}`);
22856
22998
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mobbdev",
3
- "version": "1.1.30",
3
+ "version": "1.1.33",
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",
@@ -86,6 +86,7 @@
86
86
  "node-stream-zip": "1.15.0",
87
87
  "octokit": "3.2.1",
88
88
  "open": "8.4.2",
89
+ "p-limit": "3.1.0",
89
90
  "parse-diff": "0.11.1",
90
91
  "sax": "1.4.3",
91
92
  "semver": "7.7.3",