mobbdev 1.4.47 → 1.4.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -150,7 +150,7 @@ function getSdk(client, withWrapper = defaultWrapper) {
150
150
  }
151
151
  };
152
152
  }
153
- var AiBlameInferenceType, FixQuestionInputType, Language, ManifestAction, Effort_To_Apply_Fix_Enum, Fix_Rating_Tag_Enum, Fix_Report_State_Enum, Fix_State_Enum, IssueLanguage_Enum, Pr_Status_Enum, Project_Role_Type_Enum, Vulnerability_Report_Issue_Category_Enum, Vulnerability_Report_Issue_State_Enum, Vulnerability_Report_Issue_Tag_Enum, Vulnerability_Report_Vendor_Enum, Vulnerability_Severity_Enum, FixDetailsFragmentDoc, FixReportSummaryFieldsFragmentDoc, MeDocument, GetLastOrgAndNamedProjectDocument, GetLastOrgDocument, GetEncryptedApiTokenDocument, FixReportStateDocument, GetVulnerabilityReportPathsDocument, GetAnalysisSubscriptionDocument, GetAnalysisDocument, GetFixesDocument, GetVulByNodesMetadataDocument, GetFalsePositiveDocument, UpdateScmTokenDocument, UploadS3BucketInfoDocument, GetTracyDiffUploadUrlDocument, AnalyzeCommitForExtensionAiBlameDocument, GetAiBlameInferenceDocument, GetAiBlameAttributionPromptDocument, GetPromptSummaryDocument, UploadAiBlameInferencesInitDocument, FinalizeAiBlameInferencesUploadDocument, UploadTracyRecordsDocument, GetTracyRawDataUploadUrlDocument, DigestVulnerabilityReportDocument, SubmitVulnerabilityReportDocument, CreateCommunityUserDocument, CreateCliLoginDocument, PerformCliLoginDocument, SetQuarantineEnabledDocument, CreateProjectDocument, ValidateRepoUrlDocument, GitReferenceDocument, AutoPrAnalysisDocument, GetFixWithAnswersDocument, GetFixReportsByRepoUrlDocument, GetReportFixesDocument, GetLatestReportByRepoUrlDocument, UpdateDownloadedFixDataDocument, GetUserMvsAutoFixDocument, StreamBlameAiAnalysisRequestsDocument, StreamCommitBlameRequestsDocument, ScanSkillDocument, SkillVerdictsByMd5Document, LogMvsEventDocument, GetMvsProjectDocument, IssueTypesDocument, defaultWrapper;
153
+ var AiBlameInferenceType, FixQuestionInputType, Language, ManifestAction, Effort_To_Apply_Fix_Enum, Fix_Rating_Tag_Enum, Fix_Report_State_Enum, Fix_State_Enum, IssueLanguage_Enum, Pr_Status_Enum, Project_Role_Type_Enum, Scan_Source_Enum, Vulnerability_Report_Issue_Category_Enum, Vulnerability_Report_Issue_State_Enum, Vulnerability_Report_Issue_Tag_Enum, Vulnerability_Report_Vendor_Enum, Vulnerability_Severity_Enum, FixDetailsFragmentDoc, FixReportSummaryFieldsFragmentDoc, MeDocument, GetLastOrgAndNamedProjectDocument, GetLastOrgDocument, GetEncryptedApiTokenDocument, FixReportStateDocument, GetVulnerabilityReportPathsDocument, GetAnalysisSubscriptionDocument, GetAnalysisDocument, GetFixesDocument, GetVulByNodesMetadataDocument, GetFalsePositiveDocument, UpdateScmTokenDocument, UploadS3BucketInfoDocument, GetTracyDiffUploadUrlDocument, AnalyzeCommitForExtensionAiBlameDocument, GetAiBlameInferenceDocument, GetAiBlameAttributionPromptDocument, GetPromptSummaryDocument, UploadAiBlameInferencesInitDocument, FinalizeAiBlameInferencesUploadDocument, UploadTracyRecordsDocument, GetTracyRawDataUploadUrlDocument, DigestVulnerabilityReportDocument, SubmitVulnerabilityReportDocument, CreateCommunityUserDocument, CreateCliLoginDocument, PerformCliLoginDocument, SetQuarantineEnabledDocument, CreateProjectDocument, ValidateRepoUrlDocument, GitReferenceDocument, AutoPrAnalysisDocument, GetFixWithAnswersDocument, GetFixReportsByRepoUrlDocument, GetReportFixesDocument, GetLatestReportByRepoUrlDocument, UpdateDownloadedFixDataDocument, GetUserMvsAutoFixDocument, StreamBlameAiAnalysisRequestsDocument, StreamCommitBlameRequestsDocument, ScanSkillDocument, SkillVerdictsByMd5Document, LogMvsEventDocument, GetMvsProjectDocument, IssueTypesDocument, defaultWrapper;
154
154
  var init_client_generates = __esm({
155
155
  "src/features/analysis/scm/generates/client_generates.ts"() {
156
156
  "use strict";
@@ -250,6 +250,25 @@ var init_client_generates = __esm({
250
250
  Project_Role_Type_Enum2["Writer"] = "writer";
251
251
  return Project_Role_Type_Enum2;
252
252
  })(Project_Role_Type_Enum || {});
253
+ Scan_Source_Enum = /* @__PURE__ */ ((Scan_Source_Enum2) => {
254
+ Scan_Source_Enum2["Aspm"] = "ASPM";
255
+ Scan_Source_Enum2["AutoFixer"] = "AUTO_FIXER";
256
+ Scan_Source_Enum2["CiAzure"] = "CI_AZURE";
257
+ Scan_Source_Enum2["CiBamboo"] = "CI_BAMBOO";
258
+ Scan_Source_Enum2["CiCircleci"] = "CI_CIRCLECI";
259
+ Scan_Source_Enum2["CiGithub"] = "CI_GITHUB";
260
+ Scan_Source_Enum2["CiGitlab"] = "CI_GITLAB";
261
+ Scan_Source_Enum2["CiJenkins"] = "CI_JENKINS";
262
+ Scan_Source_Enum2["CiUnknown"] = "CI_UNKNOWN";
263
+ Scan_Source_Enum2["Cli"] = "CLI";
264
+ Scan_Source_Enum2["Mcp"] = "MCP";
265
+ Scan_Source_Enum2["WebUiCheckmarxIntegration"] = "WEB_UI_CHECKMARX_INTEGRATION";
266
+ Scan_Source_Enum2["WebUiFixOwnCode"] = "WEB_UI_FIX_OWN_CODE";
267
+ Scan_Source_Enum2["WebUiOnboarding"] = "WEB_UI_ONBOARDING";
268
+ Scan_Source_Enum2["WebUiRerunAnalysis"] = "WEB_UI_RERUN_ANALYSIS";
269
+ Scan_Source_Enum2["WebUiTryNow"] = "WEB_UI_TRY_NOW";
270
+ return Scan_Source_Enum2;
271
+ })(Scan_Source_Enum || {});
253
272
  Vulnerability_Report_Issue_Category_Enum = /* @__PURE__ */ ((Vulnerability_Report_Issue_Category_Enum2) => {
254
273
  Vulnerability_Report_Issue_Category_Enum2["FalsePositive"] = "FalsePositive";
255
274
  Vulnerability_Report_Issue_Category_Enum2["Filtered"] = "Filtered";
@@ -481,6 +500,7 @@ var init_client_generates = __esm({
481
500
  organization {
482
501
  id
483
502
  enableV2Fixes
503
+ isFixEnabled
484
504
  projects(where: {name: {_eq: $projectName}}) {
485
505
  name
486
506
  id
@@ -500,6 +520,7 @@ var init_client_generates = __esm({
500
520
  organization {
501
521
  id
502
522
  enableV2Fixes
523
+ isFixEnabled
503
524
  }
504
525
  }
505
526
  }
@@ -1940,6 +1961,8 @@ var init_types = __esm({
1940
1961
  reportSummaryUrl: z7.url().nullish(),
1941
1962
  computedVendor: z7.enum(Vulnerability_Report_Vendor_Enum).nullable(),
1942
1963
  vendor: z7.enum(Vulnerability_Report_Vendor_Enum).nullable(),
1964
+ // Lets the waiting screen distinguish a first scan from a rescan.
1965
+ scanSource: z7.enum(Scan_Source_Enum).nullable(),
1943
1966
  issuesWithKnownLanguage: z7.number().nullable(),
1944
1967
  scanDate: z7.string().nullable(),
1945
1968
  vendorReportId: z7.guid().nullable(),
@@ -5204,7 +5227,7 @@ async function getAdoSdk(params) {
5204
5227
  const url = new URL(repoUrl);
5205
5228
  const origin = url.origin.toLowerCase().endsWith(".visualstudio.com") ? DEFUALT_ADO_ORIGIN : url.origin.toLowerCase();
5206
5229
  const params2 = `path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=commit&versionDescriptor[version]=${branch}&resolveLfs=true&$format=zip&api-version=5.0&download=true`;
5207
- const path37 = [
5230
+ const path38 = [
5208
5231
  prefixPath,
5209
5232
  owner,
5210
5233
  projectName,
@@ -5215,7 +5238,7 @@ async function getAdoSdk(params) {
5215
5238
  "items",
5216
5239
  "items"
5217
5240
  ].filter(Boolean).join("/");
5218
- return new URL(`${path37}?${params2}`, origin).toString();
5241
+ return new URL(`${path38}?${params2}`, origin).toString();
5219
5242
  },
5220
5243
  async getAdoBranchList({ repoUrl }) {
5221
5244
  try {
@@ -5304,8 +5327,8 @@ async function getAdoSdk(params) {
5304
5327
  const changeType = entry.changeType;
5305
5328
  return changeType !== 16 && entry.item?.path;
5306
5329
  }).map((entry) => {
5307
- const path37 = entry.item.path;
5308
- return path37.startsWith("/") ? path37.slice(1) : path37;
5330
+ const path38 = entry.item.path;
5331
+ return path38.startsWith("/") ? path38.slice(1) : path38;
5309
5332
  });
5310
5333
  },
5311
5334
  async searchAdoPullRequests({
@@ -6242,7 +6265,6 @@ var AdoSCMLib = class extends SCMLib {
6242
6265
  // src/features/analysis/scm/bitbucket/bitbucket.ts
6243
6266
  import querystring2 from "querystring";
6244
6267
  import * as bitbucketPkgNode from "bitbucket";
6245
- import bitbucketPkg from "bitbucket";
6246
6268
  import Debug2 from "debug";
6247
6269
  import { z as z16 } from "zod";
6248
6270
 
@@ -6255,6 +6277,7 @@ var BitbucketAuthResultZ = z15.object({
6255
6277
  });
6256
6278
 
6257
6279
  // src/features/analysis/scm/bitbucket/bitbucket.ts
6280
+ var bitbucketPkg = bitbucketPkgNode.default;
6258
6281
  var debug3 = Debug2("scm:bitbucket");
6259
6282
  function isBitbucketPermissionDenied(e) {
6260
6283
  const status = e?.status;
@@ -10394,6 +10417,7 @@ __export(utils_exports, {
10394
10417
  getDirName: () => getDirName,
10395
10418
  getModuleRootDir: () => getModuleRootDir,
10396
10419
  getTopLevelDirName: () => getTopLevelDirName,
10420
+ isStandaloneBinary: () => isStandaloneBinary,
10397
10421
  keypress: () => keypress,
10398
10422
  packageJson: () => packageJson,
10399
10423
  sleep: () => sleep
@@ -10404,6 +10428,10 @@ import fs3 from "fs";
10404
10428
  import path3 from "path";
10405
10429
  import { fileURLToPath } from "url";
10406
10430
  function getModuleRootDir() {
10431
+ const seaRoot = process.env["MOBBDEV_MODULE_ROOT"];
10432
+ if (seaRoot) {
10433
+ return seaRoot;
10434
+ }
10407
10435
  let manifestDir = getDirName();
10408
10436
  for (let i = 0; i < 10; i++) {
10409
10437
  const manifestPath = path3.join(manifestDir, "package.json");
@@ -10500,6 +10528,16 @@ function Spinner({ ci = false } = {}) {
10500
10528
  };
10501
10529
  }
10502
10530
 
10531
+ // src/utils/standalone_binary.ts
10532
+ function isStandaloneBinary() {
10533
+ try {
10534
+ const getBuiltin = process.getBuiltinModule;
10535
+ return Boolean(getBuiltin?.("node:sea")?.isSea());
10536
+ } catch {
10537
+ return false;
10538
+ }
10539
+ }
10540
+
10503
10541
  // src/utils/check_node_version.ts
10504
10542
  import fs4 from "fs";
10505
10543
  import path4 from "path";
@@ -11283,7 +11321,7 @@ var ScanContext = {
11283
11321
  };
11284
11322
 
11285
11323
  // src/args/commands/analyze.ts
11286
- import fs12 from "fs";
11324
+ import fs13 from "fs";
11287
11325
  import chalk10 from "chalk";
11288
11326
 
11289
11327
  // src/commands/index.ts
@@ -11291,11 +11329,11 @@ import chalk8 from "chalk";
11291
11329
  import chalkAnimation from "chalk-animation";
11292
11330
 
11293
11331
  // src/features/analysis/index.ts
11294
- import fs10 from "fs";
11332
+ import fs11 from "fs";
11295
11333
  import fsPromises3 from "fs/promises";
11296
- import path10 from "path";
11334
+ import path11 from "path";
11297
11335
  import { env as env2 } from "process";
11298
- import { pipeline } from "stream/promises";
11336
+ import { pipeline as pipeline2 } from "stream/promises";
11299
11337
  import chalk7 from "chalk";
11300
11338
  import Debug22 from "debug";
11301
11339
  import extract from "extract-zip";
@@ -11847,7 +11885,10 @@ var GQLClient = class {
11847
11885
  return {
11848
11886
  organizationId: organization.id,
11849
11887
  projectId,
11850
- enableV2Fixes: organization.enableV2Fixes === true
11888
+ enableV2Fixes: organization.enableV2Fixes === true,
11889
+ // NULL means "unset" and keeps the fix-enabled behaviour; only an
11890
+ // explicit false puts the org in SAST-only mode.
11891
+ isFixEnabled: organization.isFixEnabled !== false
11851
11892
  };
11852
11893
  }
11853
11894
  async getEncryptedApiToken(variables) {
@@ -13993,7 +14034,7 @@ async function postIssueComment(params) {
13993
14034
  fpDescription
13994
14035
  } = params;
13995
14036
  const {
13996
- path: path37,
14037
+ path: path38,
13997
14038
  startLine,
13998
14039
  vulnerabilityReportIssue: {
13999
14040
  vulnerabilityReportIssueTags,
@@ -14008,7 +14049,7 @@ async function postIssueComment(params) {
14008
14049
  Refresh the page in order to see the changes.`,
14009
14050
  pull_number: pullRequest,
14010
14051
  commit_id: commitSha,
14011
- path: path37,
14052
+ path: path38,
14012
14053
  line: startLine
14013
14054
  });
14014
14055
  const commentId = commentRes.data.id;
@@ -14042,7 +14083,7 @@ async function postFixComment(params) {
14042
14083
  scanner
14043
14084
  } = params;
14044
14085
  const {
14045
- path: path37,
14086
+ path: path38,
14046
14087
  startLine,
14047
14088
  vulnerabilityReportIssue: { fixId, vulnerabilityReportIssueTags, category },
14048
14089
  vulnerabilityReportIssueId
@@ -14060,7 +14101,7 @@ async function postFixComment(params) {
14060
14101
  Refresh the page in order to see the changes.`,
14061
14102
  pull_number: pullRequest,
14062
14103
  commit_id: commitSha,
14063
- path: path37,
14104
+ path: path38,
14064
14105
  line: startLine
14065
14106
  });
14066
14107
  const commentId = commentRes.data.id;
@@ -14610,7 +14651,7 @@ function createFork({ args, processPath, name }, options) {
14610
14651
  }
14611
14652
  function createSpawn({ args, processPath, name, cwd, env: env3 }, options) {
14612
14653
  const child = cp.spawn(processPath, args, {
14613
- stdio: ["inherit", "pipe", "pipe", "ipc"],
14654
+ stdio: ["inherit", "pipe", "pipe"],
14614
14655
  env: { ...process2.env, ...env3 },
14615
14656
  cwd
14616
14657
  });
@@ -14668,11 +14709,16 @@ if (typeof __filename !== "undefined") {
14668
14709
  }
14669
14710
  var costumeRequire = createRequire(moduleUrl);
14670
14711
  var getCheckmarxPath = () => {
14671
- const os19 = type();
14672
- const cxFileName = os19 === "Windows_NT" ? "cx.exe" : "cx";
14712
+ const os20 = type();
14713
+ const cxFileName = os20 === "Windows_NT" ? "cx.exe" : "cx";
14673
14714
  try {
14674
14715
  return costumeRequire.resolve(`.bin/${cxFileName}`);
14675
14716
  } catch (e) {
14717
+ if (isStandaloneBinary()) {
14718
+ throw new CliError(
14719
+ "The Checkmarx scanner is not available in the standalone mobbdev binary yet. Use the npm package instead: npx mobbdev@latest"
14720
+ );
14721
+ }
14676
14722
  throw new CliError(cxOperatingSystemSupportMessage);
14677
14723
  }
14678
14724
  };
@@ -14779,7 +14825,13 @@ async function validateCheckamxCredentials() {
14779
14825
  }
14780
14826
 
14781
14827
  // src/features/analysis/scanners/snyk.ts
14828
+ import crypto2 from "crypto";
14829
+ import fs10 from "fs";
14782
14830
  import { createRequire as createRequire2 } from "module";
14831
+ import os4 from "os";
14832
+ import path10 from "path";
14833
+ import { Readable } from "stream";
14834
+ import { pipeline } from "stream/promises";
14783
14835
  import chalk6 from "chalk";
14784
14836
  import Debug21 from "debug";
14785
14837
  import { createSpinner as createSpinner3 } from "nanospinner";
@@ -14804,31 +14856,130 @@ if (typeof __filename !== "undefined") {
14804
14856
  }
14805
14857
  }
14806
14858
  var costumeRequire2 = createRequire2(moduleUrl2);
14807
- var SNYK_PATH = costumeRequire2.resolve("snyk/bin/snyk");
14808
14859
  var SNYK_ARTICLE_URL = "https://docs.snyk.io/scan-using-snyk/snyk-code/configure-snyk-code#enable-snyk-code";
14809
- debug21("snyk executable path %s", SNYK_PATH);
14860
+ var SNYK_VERSION = packageJson.dependencies.snyk;
14861
+ var SNYK_DOWNLOAD_BASE = process.env["MOBB_SNYK_DOWNLOAD_BASE"] || "https://downloads.snyk.io/cli";
14862
+ var SNYK_BINARY_ASSETS = {
14863
+ "darwin-x64": "snyk-macos",
14864
+ "darwin-arm64": "snyk-macos-arm64",
14865
+ "linux-x64": "snyk-linux",
14866
+ "linux-arm64": "snyk-linux-arm64",
14867
+ "win32-x64": "snyk-win.exe"
14868
+ };
14869
+ async function downloadSnykBinary(asset, dest) {
14870
+ if (!/^\d+\.\d+\.\d+$/.test(SNYK_VERSION)) {
14871
+ throw new CliError(
14872
+ `Cannot build the Snyk CLI download URL: expected an exact version in the "snyk" dependency of package.json, got "${SNYK_VERSION}".`
14873
+ );
14874
+ }
14875
+ const url = `${SNYK_DOWNLOAD_BASE}/v${SNYK_VERSION}/${asset}`;
14876
+ const tmpPath = `${dest}.download.${process.pid}`;
14877
+ const spinner = createSpinner3(
14878
+ `\u2B07\uFE0F Downloading Snyk CLI v${SNYK_VERSION}`
14879
+ ).start();
14880
+ try {
14881
+ fs10.mkdirSync(path10.dirname(dest), { recursive: true });
14882
+ const timeout = () => AbortSignal.timeout(10 * 60 * 1e3);
14883
+ const [binRes, shaRes] = await Promise.all([
14884
+ fetchWithProxy(url, { signal: timeout() }),
14885
+ fetchWithProxy(`${url}.sha256`, { signal: timeout() })
14886
+ ]);
14887
+ if (!binRes.ok || !shaRes.ok || !binRes.body) {
14888
+ throw new CliError(
14889
+ `Snyk CLI download failed with HTTP ${binRes.ok ? shaRes.status : binRes.status}: ${url}
14890
+ If downloads.snyk.io is unreachable from this network, point MOBB_SNYK_DOWNLOAD_BASE at a mirror.`
14891
+ );
14892
+ }
14893
+ const hash = crypto2.createHash("sha256");
14894
+ await pipeline(
14895
+ Readable.fromWeb(binRes.body),
14896
+ async function* (source) {
14897
+ for await (const chunk of source) {
14898
+ hash.update(chunk);
14899
+ yield chunk;
14900
+ }
14901
+ },
14902
+ fs10.createWriteStream(tmpPath, { mode: 493 })
14903
+ );
14904
+ const expected = (await shaRes.text()).trim().split(/\s+/)[0];
14905
+ const actual = hash.digest("hex");
14906
+ if (actual !== expected) {
14907
+ throw new CliError(
14908
+ `Snyk CLI download checksum mismatch (expected ${expected}, got ${actual}) \u2014 refusing to install it. Please try again.`
14909
+ );
14910
+ }
14911
+ fs10.renameSync(tmpPath, dest);
14912
+ spinner.success({ text: `\u2B07\uFE0F Snyk CLI v${SNYK_VERSION} installed` });
14913
+ } catch (e) {
14914
+ fs10.rmSync(tmpPath, { force: true });
14915
+ spinner.error({ text: "\u2B07\uFE0F Snyk CLI download failed" });
14916
+ throw e;
14917
+ }
14918
+ }
14919
+ async function getSnykExecutable() {
14920
+ try {
14921
+ return {
14922
+ processPath: costumeRequire2.resolve("snyk/bin/snyk"),
14923
+ isNodeScript: true
14924
+ };
14925
+ } catch (e) {
14926
+ if (!isStandaloneBinary()) {
14927
+ throw e;
14928
+ }
14929
+ debug21("running as standalone binary, using standalone snyk binary");
14930
+ }
14931
+ const asset = SNYK_BINARY_ASSETS[`${process.platform}-${process.arch}`];
14932
+ if (!asset) {
14933
+ throw new CliError(
14934
+ `Snyk scan is not supported on this platform (${process.platform}-${process.arch}) when running the standalone mobbdev binary. Use the npm package instead: npx mobbdev@latest`
14935
+ );
14936
+ }
14937
+ const dest = path10.join(
14938
+ os4.homedir(),
14939
+ ".mobb",
14940
+ "tools",
14941
+ "snyk",
14942
+ `v${SNYK_VERSION}`,
14943
+ asset
14944
+ );
14945
+ if (!fs10.existsSync(dest)) {
14946
+ await downloadSnykBinary(asset, dest);
14947
+ }
14948
+ return { processPath: dest, isNodeScript: false };
14949
+ }
14810
14950
  async function forkSnyk(args, { display }) {
14811
14951
  debug21("fork snyk with args %o %s", args, display);
14812
- return createFork({ args, processPath: SNYK_PATH, name: "snyk" }, { display });
14952
+ const { processPath, isNodeScript } = await getSnykExecutable();
14953
+ const create = isNodeScript ? createFork : createSpawn;
14954
+ return create({ args, processPath, name: "snyk" }, { display });
14813
14955
  }
14814
14956
  async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
14815
14957
  debug21("get snyk report start %s %s", reportPath, repoRoot);
14816
14958
  const config2 = await forkSnyk(["config"], { display: false });
14817
14959
  const { message: configMessage } = config2;
14818
- if (!configMessage.includes("api: ")) {
14819
- const snykLoginSpinner = createSpinner3().start();
14820
- if (!skipPrompts) {
14960
+ const hasStoredCredential = configMessage.includes("api: ") || configMessage.includes("INTERNAL_OAUTH_TOKEN_STORAGE");
14961
+ if (!hasStoredCredential) {
14962
+ const hasSnykToken = !!process.env["SNYK_TOKEN"];
14963
+ if (skipPrompts) {
14964
+ if (!hasSnykToken) {
14965
+ throw new CliError(
14966
+ "Snyk authentication is required. In CI / non-interactive mode, set the SNYK_TOKEN environment variable (Snyk API token). Interactive `snyk auth` (browser) is not available with --ci."
14967
+ );
14968
+ }
14969
+ debug21("skipPrompts: using SNYK_TOKEN for snyk authentication");
14970
+ } else {
14971
+ const snykLoginSpinner = createSpinner3().start();
14821
14972
  snykLoginSpinner.update({
14822
14973
  text: "\u{1F513} Login to Snyk is required, press any key to continue"
14823
14974
  });
14824
14975
  await keypress();
14976
+ snykLoginSpinner.update({
14977
+ text: "\u{1F513} Waiting for Snyk login to complete"
14978
+ });
14979
+ debug21("no token in the config %s", config2);
14980
+ await forkSnyk(["auth"], { display: true });
14981
+ snykLoginSpinner.success({ text: "\u{1F513} Login to Snyk Successful" });
14825
14982
  }
14826
- snykLoginSpinner.update({
14827
- text: "\u{1F513} Waiting for Snyk login to complete"
14828
- });
14829
- debug21("no token in the config %s", config2);
14830
- await forkSnyk(["auth"], { display: true });
14831
- snykLoginSpinner.success({ text: "\u{1F513} Login to Snyk Successful" });
14832
14983
  }
14833
14984
  const snykSpinner = createSpinner3("\u{1F50D} Scanning your repo with Snyk ").start();
14834
14985
  const { message: scanOutput } = await forkSnyk(
@@ -14890,7 +15041,7 @@ async function downloadRepo({
14890
15041
  const { createSpinner: createSpinner5 } = Spinner2({ ci });
14891
15042
  const repoSpinner = createSpinner5("\u{1F4BE} Downloading Repo").start();
14892
15043
  debug22("download repo %s %s %s", repoUrl, dirname);
14893
- const zipFilePath = path10.join(dirname, "repo.zip");
15044
+ const zipFilePath = path11.join(dirname, "repo.zip");
14894
15045
  debug22("download URL: %s auth headers: %o", downloadUrl, authHeaders);
14895
15046
  const response = await fetch4(downloadUrl, {
14896
15047
  method: "GET",
@@ -14903,19 +15054,19 @@ async function downloadRepo({
14903
15054
  repoSpinner.error({ text: "\u{1F4BE} Repo download failed" });
14904
15055
  throw new Error(`Can't access ${chalk7.bold(repoUrl)}`);
14905
15056
  }
14906
- const fileWriterStream = fs10.createWriteStream(zipFilePath);
15057
+ const fileWriterStream = fs11.createWriteStream(zipFilePath);
14907
15058
  if (!response.body) {
14908
15059
  throw new Error("Response body is empty");
14909
15060
  }
14910
- await pipeline(response.body, fileWriterStream);
15061
+ await pipeline2(response.body, fileWriterStream);
14911
15062
  await extract(zipFilePath, { dir: dirname });
14912
- const repoRoot = fs10.readdirSync(dirname, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name)[0];
15063
+ const repoRoot = fs11.readdirSync(dirname, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name)[0];
14913
15064
  if (!repoRoot) {
14914
15065
  throw new Error("Repo root not found");
14915
15066
  }
14916
15067
  debug22("repo root %s", repoRoot);
14917
15068
  repoSpinner.success({ text: "\u{1F4BE} Repo downloaded successfully" });
14918
- return path10.join(dirname, repoRoot);
15069
+ return path11.join(dirname, repoRoot);
14919
15070
  }
14920
15071
  var getReportUrl = ({
14921
15072
  organizationId,
@@ -15023,7 +15174,7 @@ async function getReport(params, { skipPrompts }) {
15023
15174
  authHeaders: scm.getAuthHeaders(),
15024
15175
  downloadUrl
15025
15176
  });
15026
- const reportPath = path10.join(dirname, REPORT_DEFAULT_FILE_NAME);
15177
+ const reportPath = path11.join(dirname, REPORT_DEFAULT_FILE_NAME);
15027
15178
  switch (scanner) {
15028
15179
  case "snyk":
15029
15180
  await getSnykReport(reportPath, repositoryRoot, { skipPrompts });
@@ -15068,7 +15219,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
15068
15219
  pullRequest,
15069
15220
  polling,
15070
15221
  baselineCommit,
15071
- scanOnly
15222
+ scanOnly: requestedScanOnly
15072
15223
  } = params;
15073
15224
  debug22("start %s %s", dirname, repo);
15074
15225
  const { createSpinner: createSpinner5 } = Spinner2({ ci });
@@ -15084,11 +15235,20 @@ async function _scan(params, { skipPrompts = false } = {}) {
15084
15235
  const {
15085
15236
  projectId,
15086
15237
  organizationId,
15087
- enableV2Fixes: orgEnableV2Fixes
15238
+ enableV2Fixes: orgEnableV2Fixes,
15239
+ isFixEnabled: orgIsFixEnabled
15088
15240
  } = await gqlClient.getLastOrgAndNamedProject({
15089
15241
  projectName: mobbProjectName,
15090
15242
  userDefinedOrganizationId: userOrganizationId
15091
15243
  });
15244
+ const scanOnly = requestedScanOnly || !orgIsFixEnabled;
15245
+ if (scanOnly && !requestedScanOnly) {
15246
+ console.log(
15247
+ chalk7.yellow(
15248
+ "\u2139\uFE0F Your organization is on Mobb Scan (scan-only): issues will be found and reported, but no fixes are generated. Contact support to enable Mobb Fixer."
15249
+ )
15250
+ );
15251
+ }
15092
15252
  const {
15093
15253
  uploadS3BucketInfo: { repoUploadInfo, reportUploadInfo }
15094
15254
  } = await gqlClient.uploadS3BucketInfo();
@@ -15426,7 +15586,7 @@ async function _zipAndUploadRepo({
15426
15586
  const zippingSpinner = createSpinner4("\u{1F4E6} Zipping repo").start();
15427
15587
  let zipBuffer;
15428
15588
  let gitInfo2 = { success: false };
15429
- if (srcFileStatus.isFile() && path10.extname(srcPath).toLowerCase() === ".fpr") {
15589
+ if (srcFileStatus.isFile() && path11.extname(srcPath).toLowerCase() === ".fpr") {
15430
15590
  zipBuffer = await repackFpr(srcPath);
15431
15591
  } else {
15432
15592
  gitInfo2 = await getGitInfo(srcPath);
@@ -15599,17 +15759,17 @@ async function waitForAnaysisAndReviewPr({
15599
15759
  }
15600
15760
 
15601
15761
  // src/commands/scan_skill_input.ts
15602
- import fs11 from "fs";
15603
- import path11 from "path";
15762
+ import fs12 from "fs";
15763
+ import path12 from "path";
15604
15764
  import AdmZip2 from "adm-zip";
15605
15765
  var LOCAL_SKILL_ZIP_DATA_URL_PREFIX = "data:application/zip;base64,";
15606
15766
  var MAX_LOCAL_SKILL_ARCHIVE_BYTES = 2 * 1024 * 1024;
15607
15767
  async function resolveSkillScanInput(skillInput) {
15608
- const resolvedPath = path11.resolve(skillInput);
15609
- if (!fs11.existsSync(resolvedPath)) {
15768
+ const resolvedPath = path12.resolve(skillInput);
15769
+ if (!fs12.existsSync(resolvedPath)) {
15610
15770
  return skillInput;
15611
15771
  }
15612
- const stat5 = fs11.statSync(resolvedPath);
15772
+ const stat5 = fs12.statSync(resolvedPath);
15613
15773
  if (!stat5.isDirectory()) {
15614
15774
  throw new CliError(
15615
15775
  "Local skill input must be a directory containing SKILL.md"
@@ -15619,18 +15779,18 @@ async function resolveSkillScanInput(skillInput) {
15619
15779
  }
15620
15780
  function packageLocalSkillDirectory(directoryPath) {
15621
15781
  const zip = new AdmZip2();
15622
- const rootPath = path11.resolve(directoryPath);
15782
+ const rootPath = path12.resolve(directoryPath);
15623
15783
  const filePaths = listDirectoryFiles(rootPath);
15624
15784
  let hasSkillMd = false;
15625
15785
  for (const relativePath of filePaths) {
15626
- const fullPath = path11.join(rootPath, relativePath);
15627
- const normalizedFullPath = path11.resolve(fullPath);
15628
- if (normalizedFullPath !== rootPath && !normalizedFullPath.startsWith(rootPath + path11.sep)) {
15786
+ const fullPath = path12.join(rootPath, relativePath);
15787
+ const normalizedFullPath = path12.resolve(fullPath);
15788
+ if (normalizedFullPath !== rootPath && !normalizedFullPath.startsWith(rootPath + path12.sep)) {
15629
15789
  continue;
15630
15790
  }
15631
- const fileContent = fs11.readFileSync(normalizedFullPath);
15791
+ const fileContent = fs12.readFileSync(normalizedFullPath);
15632
15792
  zip.addFile(relativePath, fileContent);
15633
- if (path11.basename(relativePath).toLowerCase() === "skill.md") {
15793
+ if (path12.basename(relativePath).toLowerCase() === "skill.md") {
15634
15794
  hasSkillMd = true;
15635
15795
  }
15636
15796
  }
@@ -15648,17 +15808,17 @@ function packageLocalSkillDirectory(directoryPath) {
15648
15808
  function listDirectoryFiles(rootPath) {
15649
15809
  const files = [];
15650
15810
  function walk(relativeDir) {
15651
- const absoluteDir = path11.join(rootPath, relativeDir);
15652
- const entries = fs11.readdirSync(absoluteDir, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
15811
+ const absoluteDir = path12.join(rootPath, relativeDir);
15812
+ const entries = fs12.readdirSync(absoluteDir, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
15653
15813
  for (const entry of entries) {
15654
- const safeEntryName = path11.basename(entry.name).replace(/\0/g, "");
15814
+ const safeEntryName = path12.basename(entry.name).replace(/\0/g, "");
15655
15815
  if (!safeEntryName) {
15656
15816
  continue;
15657
15817
  }
15658
- const relativePath = relativeDir ? path11.posix.join(relativeDir, safeEntryName) : safeEntryName;
15659
- const absolutePath = path11.join(rootPath, relativePath);
15660
- const normalizedAbsolutePath = path11.resolve(absolutePath);
15661
- if (normalizedAbsolutePath !== rootPath && !normalizedAbsolutePath.startsWith(rootPath + path11.sep)) {
15818
+ const relativePath = relativeDir ? path12.posix.join(relativeDir, safeEntryName) : safeEntryName;
15819
+ const absolutePath = path12.join(rootPath, relativePath);
15820
+ const normalizedAbsolutePath = path12.resolve(absolutePath);
15821
+ if (normalizedAbsolutePath !== rootPath && !normalizedAbsolutePath.startsWith(rootPath + path12.sep)) {
15662
15822
  continue;
15663
15823
  }
15664
15824
  if (entry.isSymbolicLink()) {
@@ -15879,7 +16039,7 @@ async function scanSkill(options) {
15879
16039
 
15880
16040
  // src/args/validation.ts
15881
16041
  import chalk9 from "chalk";
15882
- import path12 from "path";
16042
+ import path13 from "path";
15883
16043
  import { z as z28 } from "zod";
15884
16044
  function throwRepoUrlErrorMessage({
15885
16045
  error,
@@ -15923,7 +16083,7 @@ function validateRepoUrl(args) {
15923
16083
  }
15924
16084
  var supportExtensions = [".json", ".xml", ".fpr", ".sarif", ".zip"];
15925
16085
  function validateReportFileFormat(reportFile) {
15926
- if (!supportExtensions.includes(path12.extname(reportFile))) {
16086
+ if (!supportExtensions.includes(path13.extname(reportFile))) {
15927
16087
  throw new CliError(
15928
16088
  `
15929
16089
  ${chalk9.bold(
@@ -15971,7 +16131,7 @@ function analyzeBuilder(yargs2) {
15971
16131
  ).help();
15972
16132
  }
15973
16133
  function validateAnalyzeOptions(argv) {
15974
- if (argv.f && !fs12.existsSync(argv.f)) {
16134
+ if (argv.f && !fs13.existsSync(argv.f)) {
15975
16135
  throw new CliError(`
15976
16136
  Can't access ${chalk10.bold(argv.f)}`);
15977
16137
  }
@@ -16019,8 +16179,8 @@ import { spawn } from "child_process";
16019
16179
 
16020
16180
  // src/features/claude_code/daemon.ts
16021
16181
  import { readFileSync, writeFileSync as writeFileSync2 } from "fs";
16022
- import * as os8 from "os";
16023
- import path24 from "path";
16182
+ import * as os9 from "os";
16183
+ import path25 from "path";
16024
16184
  import { setTimeout as sleep4 } from "timers/promises";
16025
16185
  import Configstore4 from "configstore";
16026
16186
 
@@ -16199,7 +16359,7 @@ function loadBreaker(store) {
16199
16359
  // src/features/analysis/skill_quarantine/runQuarantineCheck.ts
16200
16360
  import { stat as stat3 } from "fs/promises";
16201
16361
  import { homedir as homedir4 } from "os";
16202
- import path19 from "path";
16362
+ import path20 from "path";
16203
16363
 
16204
16364
  // src/features/analysis/skill_quarantine/constants.ts
16205
16365
  var HEARTBEAT_DEBOUNCE_MS = (() => {
@@ -16214,11 +16374,11 @@ var STUB_MARKER = "\u26D4 QUARANTINED BY TRACY";
16214
16374
 
16215
16375
  // src/features/analysis/skill_quarantine/enumerateInstalledSkills.ts
16216
16376
  import { homedir as homedir2 } from "os";
16217
- import path15 from "path";
16377
+ import path16 from "path";
16218
16378
 
16219
16379
  // src/features/analysis/context_file_processor.ts
16220
16380
  import { createHash } from "crypto";
16221
- import path13 from "path";
16381
+ import path14 from "path";
16222
16382
  import AdmZip3 from "adm-zip";
16223
16383
  import pLimit5 from "p-limit";
16224
16384
  var SANITIZE_CONCURRENCY = 5;
@@ -16252,7 +16412,7 @@ async function processContextFiles(regularFiles, skillGroups) {
16252
16412
  );
16253
16413
  for (const file of sortedFiles) {
16254
16414
  const sanitizedContent = await sanitizeFileContent(file.content);
16255
- const zipEntryName = group.isFolder ? path13.relative(group.skillPath, file.path).replace(/\\/g, "/") : path13.basename(file.path);
16415
+ const zipEntryName = group.isFolder ? path14.relative(group.skillPath, file.path).replace(/\\/g, "/") : path14.basename(file.path);
16256
16416
  zip.addFile(zipEntryName, Buffer.from(sanitizedContent, "utf-8"));
16257
16417
  const entry = zip.getEntry(zipEntryName);
16258
16418
  if (entry) {
@@ -16271,7 +16431,7 @@ async function processContextFiles(regularFiles, skillGroups) {
16271
16431
  // src/features/analysis/context_file_scanner.ts
16272
16432
  import { lstat, readdir, readFile, realpath, stat } from "fs/promises";
16273
16433
  import { homedir } from "os";
16274
- import path14 from "path";
16434
+ import path15 from "path";
16275
16435
  import { globby as globby2 } from "globby";
16276
16436
  import { parse as parseJsoncLib } from "jsonc-parser";
16277
16437
 
@@ -16603,25 +16763,25 @@ function resolveCustomLocationPath(raw, workspaceRoot, home) {
16603
16763
  return null;
16604
16764
  }
16605
16765
  if (s.startsWith("~/") || s === "~") {
16606
- s = path14.join(home, s.slice(1));
16766
+ s = path15.join(home, s.slice(1));
16607
16767
  }
16608
- if (!path14.isAbsolute(s)) {
16609
- s = path14.resolve(workspaceRoot, s);
16768
+ if (!path15.isAbsolute(s)) {
16769
+ s = path15.resolve(workspaceRoot, s);
16610
16770
  }
16611
- const resolved = path14.normalize(s);
16771
+ const resolved = path15.normalize(s);
16612
16772
  if (resolved === "/" || resolved === home) {
16613
16773
  return null;
16614
16774
  }
16615
16775
  for (const sub of SENSITIVE_HOME_SUBDIRS) {
16616
- const sensitive = path14.join(home, sub);
16617
- if (resolved === sensitive || resolved.startsWith(`${sensitive}${path14.sep}`)) {
16776
+ const sensitive = path15.join(home, sub);
16777
+ if (resolved === sensitive || resolved.startsWith(`${sensitive}${path15.sep}`)) {
16618
16778
  return null;
16619
16779
  }
16620
16780
  }
16621
- const relWorkspace = path14.relative(workspaceRoot, resolved);
16622
- const relHome = path14.relative(home, resolved);
16623
- const escapesWorkspace = relWorkspace.startsWith("..") || path14.isAbsolute(relWorkspace);
16624
- const escapesHome = relHome.startsWith("..") || path14.isAbsolute(relHome);
16781
+ const relWorkspace = path15.relative(workspaceRoot, resolved);
16782
+ const relHome = path15.relative(home, resolved);
16783
+ const escapesWorkspace = relWorkspace.startsWith("..") || path15.isAbsolute(relWorkspace);
16784
+ const escapesHome = relHome.startsWith("..") || path15.isAbsolute(relHome);
16625
16785
  if (escapesWorkspace && escapesHome) {
16626
16786
  return null;
16627
16787
  }
@@ -16672,15 +16832,15 @@ async function readJsoncSettings(settingsPath) {
16672
16832
  putSettingsCache(settingsPath, { mtimeMs, parsed: payload });
16673
16833
  return payload;
16674
16834
  }
16675
- function putSettingsCache(path37, entry) {
16676
- if (!settingsCache.has(path37) && settingsCache.size >= MAX_SETTINGS_CACHE_SIZE) {
16835
+ function putSettingsCache(path38, entry) {
16836
+ if (!settingsCache.has(path38) && settingsCache.size >= MAX_SETTINGS_CACHE_SIZE) {
16677
16837
  settingsCache.delete(settingsCache.keys().next().value);
16678
16838
  }
16679
- settingsCache.set(path37, entry);
16839
+ settingsCache.set(path38, entry);
16680
16840
  }
16681
16841
  async function readCopilotCustomLocations(workspaceRoot) {
16682
16842
  const parsed = await readJsoncSettings(
16683
- path14.join(workspaceRoot, ".vscode", "settings.json")
16843
+ path15.join(workspaceRoot, ".vscode", "settings.json")
16684
16844
  );
16685
16845
  if (!parsed) {
16686
16846
  return [];
@@ -16727,7 +16887,7 @@ async function readCopilotCustomLocations(workspaceRoot) {
16727
16887
  async function readClaudeCodeCustomLocations() {
16728
16888
  const home = homedir();
16729
16889
  const parsed = await readJsoncSettings(
16730
- path14.join(home, ".claude", "settings.json")
16890
+ path15.join(home, ".claude", "settings.json")
16731
16891
  );
16732
16892
  if (!parsed) {
16733
16893
  return [];
@@ -16769,7 +16929,7 @@ function groupSkills(files, root, baseDir) {
16769
16929
  const folderMap = /* @__PURE__ */ new Map();
16770
16930
  const standalone = [];
16771
16931
  for (const f of skillFiles) {
16772
- const rel = path14.relative(baseDir, f.path).replace(/\\/g, "/");
16932
+ const rel = path15.relative(baseDir, f.path).replace(/\\/g, "/");
16773
16933
  const skillsMarker = "skills/";
16774
16934
  const skillsIdx = rel.indexOf(skillsMarker);
16775
16935
  if (skillsIdx === -1) {
@@ -16796,8 +16956,8 @@ function groupSkills(files, root, baseDir) {
16796
16956
  }
16797
16957
  const groups = [];
16798
16958
  for (const f of standalone) {
16799
- const name = path14.basename(f.path, path14.extname(f.path));
16800
- const standaloneRel = path14.relative(baseDir, f.path).replace(/\\/g, "/");
16959
+ const name = path15.basename(f.path, path15.extname(f.path));
16960
+ const standaloneRel = path15.relative(baseDir, f.path).replace(/\\/g, "/");
16801
16961
  const sessionKey = `skill:${root}:${standaloneRel}`;
16802
16962
  groups.push({
16803
16963
  name,
@@ -16811,7 +16971,7 @@ function groupSkills(files, root, baseDir) {
16811
16971
  }
16812
16972
  for (const [folderKey, { folderName, files: folderFiles }] of folderMap) {
16813
16973
  const maxMtimeMs = Math.max(...folderFiles.map((f) => f.mtimeMs));
16814
- const skillPath = path14.join(baseDir, folderKey);
16974
+ const skillPath = path15.join(baseDir, folderKey);
16815
16975
  const sessionKey = `skill:${root}:${folderKey}`;
16816
16976
  groups.push({
16817
16977
  name: folderName,
@@ -16932,10 +17092,10 @@ async function enumerateGlob(pattern, cwd, category, isDynamic) {
16932
17092
  } catch {
16933
17093
  return [];
16934
17094
  }
16935
- return files.map((path37) => ({ path: path37, category }));
17095
+ return files.map((path38) => ({ path: path38, category }));
16936
17096
  }
16937
17097
  async function enumerateSkillBundle(baseDir, skillsRoot) {
16938
- const skillsDir = path14.resolve(baseDir, skillsRoot);
17098
+ const skillsDir = path15.resolve(baseDir, skillsRoot);
16939
17099
  let manifests;
16940
17100
  try {
16941
17101
  manifests = await globby2("*/SKILL.md", {
@@ -16951,7 +17111,7 @@ async function enumerateSkillBundle(baseDir, skillsRoot) {
16951
17111
  }
16952
17112
  const perSkillResults = await Promise.all(
16953
17113
  manifests.map(async (manifest) => {
16954
- const skillDir = path14.dirname(manifest);
17114
+ const skillDir = path15.dirname(manifest);
16955
17115
  try {
16956
17116
  return await globby2("**/*", {
16957
17117
  cwd: skillDir,
@@ -17000,11 +17160,11 @@ async function enumerateSymlinkedSkills(skillsDir) {
17000
17160
  const results = [];
17001
17161
  for (const entry of dirEntries) {
17002
17162
  if (!entry.isSymbolicLink()) continue;
17003
- const entryPath = path14.join(skillsDir, entry.name);
17163
+ const entryPath = path15.join(skillsDir, entry.name);
17004
17164
  try {
17005
17165
  const st = await stat(entryPath);
17006
17166
  if (st.isDirectory()) {
17007
- const hasManifest = await stat(path14.join(entryPath, "SKILL.md")).then(() => true).catch(() => false);
17167
+ const hasManifest = await stat(path15.join(entryPath, "SKILL.md")).then(() => true).catch(() => false);
17008
17168
  if (!hasManifest) continue;
17009
17169
  const realDir = await realpath(entryPath);
17010
17170
  const realFiles = await globby2("**/*", {
@@ -17017,7 +17177,7 @@ async function enumerateSymlinkedSkills(skillsDir) {
17017
17177
  }).catch(() => []);
17018
17178
  for (const f of realFiles) {
17019
17179
  results.push({
17020
- path: path14.join(entryPath, path14.relative(realDir, f)),
17180
+ path: path15.join(entryPath, path15.relative(realDir, f)),
17021
17181
  category: "skill"
17022
17182
  });
17023
17183
  }
@@ -17049,11 +17209,11 @@ function scopeForRoot(root) {
17049
17209
  return void 0;
17050
17210
  }
17051
17211
  function deriveIdentifier(filePath, baseDir) {
17052
- const relative2 = path14.relative(baseDir, filePath);
17212
+ const relative2 = path15.relative(baseDir, filePath);
17053
17213
  if (!relative2.startsWith("..")) {
17054
17214
  return relative2.replace(/\\/g, "/");
17055
17215
  }
17056
- return path14.basename(filePath);
17216
+ return path15.basename(filePath);
17057
17217
  }
17058
17218
 
17059
17219
  // src/features/analysis/skill_quarantine/enumerateInstalledSkills.ts
@@ -17065,8 +17225,8 @@ async function enumerateInstalledSkills(workspaceRoot) {
17065
17225
  );
17066
17226
  const home = homedir2();
17067
17227
  const agentGroups = regularFiles.filter((f) => f.category === "agent-config").map((f) => ({
17068
- name: path15.basename(f.path, path15.extname(f.path)),
17069
- root: f.path.startsWith(home + path15.sep) ? "home" : "workspace",
17228
+ name: path16.basename(f.path, path16.extname(f.path)),
17229
+ root: f.path.startsWith(home + path16.sep) ? "home" : "workspace",
17070
17230
  skillPath: f.path,
17071
17231
  files: [f],
17072
17232
  isFolder: false,
@@ -17150,32 +17310,32 @@ import {
17150
17310
  unlink,
17151
17311
  writeFile
17152
17312
  } from "fs/promises";
17153
- import path18 from "path";
17313
+ import path19 from "path";
17154
17314
  import AdmZip4 from "adm-zip";
17155
17315
 
17156
17316
  // src/features/analysis/skill_quarantine/paths.ts
17157
17317
  import { homedir as homedir3 } from "os";
17158
- import path16 from "path";
17318
+ import path17 from "path";
17159
17319
  function getQuarantineRoot() {
17160
- return path16.join(homedir3(), ".tracy", "quarantine", "claude", "skills");
17320
+ return path17.join(homedir3(), ".tracy", "quarantine", "claude", "skills");
17161
17321
  }
17162
17322
  function getQuarantineZipPath(md5) {
17163
- return path16.join(getQuarantineRoot(), `${md5}.zip`);
17323
+ return path17.join(getQuarantineRoot(), `${md5}.zip`);
17164
17324
  }
17165
17325
  function getTmpZipPath(md5, uuid) {
17166
- return path16.join(getQuarantineRoot(), `${md5}_tmp_${uuid}.zip`);
17326
+ return path17.join(getQuarantineRoot(), `${md5}_tmp_${uuid}.zip`);
17167
17327
  }
17168
17328
  var TMP_ZIP_REGEX = /^([0-9a-f]{32})_tmp_[0-9a-f-]+\.zip$/;
17169
17329
  var COMMITTED_ZIP_REGEX = /^([0-9a-f]{32})\.zip$/;
17170
17330
 
17171
17331
  // src/features/analysis/skill_quarantine/stubTemplate.ts
17172
- import path17 from "path";
17332
+ import path18 from "path";
17173
17333
  import { quote } from "shell-quote";
17174
17334
  var LEGACY_SUMMARY_FALLBACK = "not available (scan predates current schema)";
17175
17335
  function renderStub(params) {
17176
17336
  const folderOrFile = params.isFolder ? "skill folder" : "skill file";
17177
17337
  const reason = params.summary ?? LEGACY_SUMMARY_FALLBACK;
17178
- const extractParent = path17.dirname(params.origPath);
17338
+ const extractParent = path18.dirname(params.origPath);
17179
17339
  const recoverCommand = `rm -rf ${quote([params.origPath])} && unzip -o ${quote([params.quarantinedZipPath])} -d ${quote([extractParent])}`;
17180
17340
  return `# ${STUB_MARKER}
17181
17341
 
@@ -17289,7 +17449,7 @@ async function quarantineSkill(params) {
17289
17449
  }
17290
17450
  async function preregisterStubMd5(params) {
17291
17451
  const { skillPath, isFolder, origName, log: log2 } = params;
17292
- const stubFilePath = isFolder ? path18.join(skillPath, "SKILL.md") : skillPath;
17452
+ const stubFilePath = isFolder ? path19.join(skillPath, "SKILL.md") : skillPath;
17293
17453
  const stubEntryName = isFolder ? `${origName}/SKILL.md` : origName;
17294
17454
  const content = await readFile2(stubFilePath, "utf-8");
17295
17455
  const fileStat = await stat2(stubFilePath);
@@ -17302,7 +17462,7 @@ async function preregisterStubMd5(params) {
17302
17462
  mtimeMs: fileStat.mtimeMs
17303
17463
  };
17304
17464
  const stubGroup = {
17305
- name: isFolder ? origName : path18.basename(skillPath, path18.extname(skillPath)),
17465
+ name: isFolder ? origName : path19.basename(skillPath, path19.extname(skillPath)),
17306
17466
  root: "workspace",
17307
17467
  // unused by md5 computation
17308
17468
  skillPath,
@@ -17349,7 +17509,7 @@ async function writeStub(params) {
17349
17509
  if (isFolder) {
17350
17510
  await rm(skillPath, { recursive: true, force: true });
17351
17511
  await mkdir(skillPath, { recursive: true });
17352
- await writeFile(path18.join(skillPath, "SKILL.md"), stubContent, "utf8");
17512
+ await writeFile(path19.join(skillPath, "SKILL.md"), stubContent, "utf8");
17353
17513
  } else {
17354
17514
  await writeFile(skillPath, stubContent, "utf8");
17355
17515
  }
@@ -17371,7 +17531,7 @@ async function reconcileAndSweep(log2) {
17371
17531
  for (const entry of entries) {
17372
17532
  const md5 = TMP_ZIP_REGEX.exec(entry)?.[1];
17373
17533
  if (md5 === void 0) continue;
17374
- const full = path18.join(root, entry);
17534
+ const full = path19.join(root, entry);
17375
17535
  if (committed.has(md5)) {
17376
17536
  await unlink(full).catch(
17377
17537
  (err) => log2.warn(
@@ -17431,8 +17591,8 @@ async function addFolderAsync(zip, root, prefix) {
17431
17591
  async function walk(dir, relPrefix) {
17432
17592
  const entries = await readdir2(dir, { withFileTypes: true });
17433
17593
  for (const e of entries) {
17434
- const full = path18.join(dir, e.name);
17435
- const rel = path18.posix.join(relPrefix, e.name);
17594
+ const full = path19.join(dir, e.name);
17595
+ const rel = path19.posix.join(relPrefix, e.name);
17436
17596
  if (e.isDirectory()) await walk(full, rel);
17437
17597
  else if (e.isFile()) zip.addFile(rel, await readFile2(full));
17438
17598
  }
@@ -17478,8 +17638,8 @@ var SKILL_PARENT_DIRS = [
17478
17638
  async function getSkillDirsMtimeMs(cwd) {
17479
17639
  const home = homedir4();
17480
17640
  const dirs = SKILL_PARENT_DIRS.flatMap((d) => [
17481
- path19.join(cwd, d),
17482
- path19.join(home, d)
17641
+ path20.join(cwd, d),
17642
+ path20.join(home, d)
17483
17643
  ]);
17484
17644
  let max = 0;
17485
17645
  for (const dir of dirs) {
@@ -17592,9 +17752,9 @@ async function runQuarantineCheckIfNeeded(opts) {
17592
17752
  }
17593
17753
 
17594
17754
  // src/features/claude_code/daemon_pid_file.ts
17595
- import fs13 from "fs";
17596
- import os4 from "os";
17597
- import path20 from "path";
17755
+ import fs14 from "fs";
17756
+ import os5 from "os";
17757
+ import path21 from "path";
17598
17758
 
17599
17759
  // src/features/claude_code/data_collector_constants.ts
17600
17760
  var CC_VERSION_CACHE_KEY = "claudeCode.detectedCCVersion";
@@ -17620,26 +17780,26 @@ var DAEMON_SHUTDOWN_DRAIN_MS = 6e3;
17620
17780
 
17621
17781
  // src/features/claude_code/daemon_pid_file.ts
17622
17782
  function getMobbdevDir() {
17623
- return path20.join(os4.homedir(), ".mobbdev");
17783
+ return path21.join(os5.homedir(), ".mobbdev");
17624
17784
  }
17625
17785
  function getDaemonCheckScriptPath() {
17626
- return path20.join(getMobbdevDir(), "daemon-check.js");
17786
+ return path21.join(getMobbdevDir(), "daemon-check.js");
17627
17787
  }
17628
17788
  var DaemonPidFile = class {
17629
17789
  constructor() {
17630
17790
  __publicField(this, "data", null);
17631
17791
  }
17632
17792
  get filePath() {
17633
- return path20.join(getMobbdevDir(), "daemon.pid");
17793
+ return path21.join(getMobbdevDir(), "daemon.pid");
17634
17794
  }
17635
17795
  /** Ensure ~/.mobbdev/ directory exists. */
17636
17796
  ensureDir() {
17637
- fs13.mkdirSync(getMobbdevDir(), { recursive: true });
17797
+ fs14.mkdirSync(getMobbdevDir(), { recursive: true });
17638
17798
  }
17639
17799
  /** Read the PID file from disk. Returns the parsed data or null. */
17640
17800
  read() {
17641
17801
  try {
17642
- const raw = fs13.readFileSync(this.filePath, "utf8");
17802
+ const raw = fs14.readFileSync(this.filePath, "utf8");
17643
17803
  const parsed = JSON.parse(raw);
17644
17804
  if (typeof parsed.pid !== "number" || typeof parsed.startedAt !== "number" || typeof parsed.heartbeat !== "number") {
17645
17805
  this.data = null;
@@ -17659,14 +17819,14 @@ var DaemonPidFile = class {
17659
17819
  heartbeat: Date.now(),
17660
17820
  version
17661
17821
  };
17662
- fs13.writeFileSync(this.filePath, JSON.stringify(this.data), "utf8");
17822
+ fs14.writeFileSync(this.filePath, JSON.stringify(this.data), "utf8");
17663
17823
  }
17664
17824
  /** Update the heartbeat timestamp of the current PID file. */
17665
17825
  updateHeartbeat() {
17666
17826
  if (!this.data) this.read();
17667
17827
  if (!this.data) return;
17668
17828
  this.data.heartbeat = Date.now();
17669
- fs13.writeFileSync(this.filePath, JSON.stringify(this.data), "utf8");
17829
+ fs14.writeFileSync(this.filePath, JSON.stringify(this.data), "utf8");
17670
17830
  }
17671
17831
  /** Check whether the previously read PID data represents a live daemon. */
17672
17832
  isAlive() {
@@ -17683,7 +17843,7 @@ var DaemonPidFile = class {
17683
17843
  remove() {
17684
17844
  this.data = null;
17685
17845
  try {
17686
- fs13.unlinkSync(this.filePath);
17846
+ fs14.unlinkSync(this.filePath);
17687
17847
  } catch {
17688
17848
  }
17689
17849
  }
@@ -17693,7 +17853,7 @@ var DaemonPidFile = class {
17693
17853
  import { execFile } from "child_process";
17694
17854
  import { createHash as createHash3 } from "crypto";
17695
17855
  import { access as access2, open as open4, readdir as readdir3, readFile as readFile3, unlink as unlink2 } from "fs/promises";
17696
- import path21 from "path";
17856
+ import path22 from "path";
17697
17857
  import { promisify } from "util";
17698
17858
 
17699
17859
  // src/features/analysis/context_file_uploader.ts
@@ -18057,8 +18217,8 @@ function createConfigstoreStream(store, opts) {
18057
18217
  heartbeatBuffer.length = 0;
18058
18218
  }
18059
18219
  }
18060
- function setScopePath(path37) {
18061
- scopePath = path37;
18220
+ function setScopePath(path38) {
18221
+ scopePath = path38;
18062
18222
  }
18063
18223
  return { writable, flush, setScopePath };
18064
18224
  }
@@ -18140,22 +18300,22 @@ function createDdBatch(config2) {
18140
18300
 
18141
18301
  // src/utils/shared-logger/hostname.ts
18142
18302
  import { createHash as createHash2 } from "crypto";
18143
- import os5 from "os";
18303
+ import os6 from "os";
18144
18304
  function hashString(input) {
18145
18305
  return createHash2("sha256").update(input).digest("hex").slice(0, 16);
18146
18306
  }
18147
18307
  function getPlainHostname() {
18148
18308
  try {
18149
- return `${os5.userInfo().username}@${os5.hostname()}`;
18309
+ return `${os6.userInfo().username}@${os6.hostname()}`;
18150
18310
  } catch {
18151
- return `unknown@${os5.hostname()}`;
18311
+ return `unknown@${os6.hostname()}`;
18152
18312
  }
18153
18313
  }
18154
18314
  function getHashedHostname() {
18155
18315
  try {
18156
- return `${hashString(os5.userInfo().username)}@${hashString(os5.hostname())}`;
18316
+ return `${hashString(os6.userInfo().username)}@${hashString(os6.hostname())}`;
18157
18317
  } catch {
18158
- return `unknown@${hashString(os5.hostname())}`;
18318
+ return `unknown@${hashString(os6.hostname())}`;
18159
18319
  }
18160
18320
  }
18161
18321
 
@@ -18282,7 +18442,7 @@ function createLogger(config2) {
18282
18442
 
18283
18443
  // src/features/claude_code/hook_logger.ts
18284
18444
  var DD_RUM_TOKEN = true ? "pubf59c0182545bfb4c299175119f1abf9b" : "";
18285
- var CLI_VERSION = true ? "1.4.47" : "unknown";
18445
+ var CLI_VERSION = true ? "1.4.49" : "unknown";
18286
18446
  var NAMESPACE = "mobbdev-claude-code-hook-logs";
18287
18447
  var claudeCodeVersion;
18288
18448
  function buildDdTags() {
@@ -18399,12 +18559,12 @@ async function resolveTranscriptPath(transcriptPath, sessionId) {
18399
18559
  return transcriptPath;
18400
18560
  } catch {
18401
18561
  }
18402
- const filename = path21.basename(transcriptPath);
18403
- const dirName = path21.basename(path21.dirname(transcriptPath));
18404
- const projectsDir = path21.dirname(path21.dirname(transcriptPath));
18562
+ const filename = path22.basename(transcriptPath);
18563
+ const dirName = path22.basename(path22.dirname(transcriptPath));
18564
+ const projectsDir = path22.dirname(path22.dirname(transcriptPath));
18405
18565
  const baseDirName = dirName.replace(/[-.]claude-worktrees-.+$/, "");
18406
18566
  if (baseDirName !== dirName) {
18407
- const candidate = path21.join(projectsDir, baseDirName, filename);
18567
+ const candidate = path22.join(projectsDir, baseDirName, filename);
18408
18568
  try {
18409
18569
  await access2(candidate);
18410
18570
  hookLog.info(
@@ -18426,7 +18586,7 @@ async function resolveTranscriptPath(transcriptPath, sessionId) {
18426
18586
  const dirs = await readdir3(projectsDir);
18427
18587
  for (const dir of dirs) {
18428
18588
  if (dir === dirName) continue;
18429
- const candidate = path21.join(projectsDir, dir, filename);
18589
+ const candidate = path22.join(projectsDir, dir, filename);
18430
18590
  try {
18431
18591
  await access2(candidate);
18432
18592
  hookLog.info(
@@ -18648,7 +18808,7 @@ async function cleanupStaleSessions(configDir) {
18648
18808
  );
18649
18809
  let deletedCount = 0;
18650
18810
  for (const file of sessionFiles) {
18651
- const filePath = path21.join(configDir, file);
18811
+ const filePath = path22.join(configDir, file);
18652
18812
  try {
18653
18813
  const content = JSON.parse(await readFile3(filePath, "utf-8"));
18654
18814
  let newest = 0;
@@ -18945,17 +19105,17 @@ function summarizeUploadErrTypes(errs) {
18945
19105
  }
18946
19106
 
18947
19107
  // src/features/claude_code/install_hook.ts
18948
- import fs14 from "fs";
19108
+ import fs15 from "fs";
18949
19109
  import fsPromises4 from "fs/promises";
18950
- import os6 from "os";
18951
- import path22 from "path";
19110
+ import os7 from "os";
19111
+ import path23 from "path";
18952
19112
  import chalk11 from "chalk";
18953
19113
 
18954
19114
  // src/features/claude_code/daemon-check-shim.tmpl.js
18955
19115
  var daemon_check_shim_tmpl_default = "// Mobb daemon shim \u2014 checks if daemon is alive, spawns if dead.\n// Auto-generated by mobbdev CLI. Do not edit.\nvar fs = require('fs')\nvar spawn = require('child_process').spawn\nvar path = require('path')\nvar os = require('os')\n\nvar pidFile = path.join(os.homedir(), '.mobbdev', 'daemon.pid')\nvar HEARTBEAT_STALE_MS = __HEARTBEAT_STALE_MS__\n\ntry {\n var data = JSON.parse(fs.readFileSync(pidFile, 'utf8'))\n if (Date.now() - data.heartbeat > HEARTBEAT_STALE_MS) throw new Error('stale')\n process.kill(data.pid, 0) // throws ESRCH if the process is gone\n} catch (e) {\n var localCli = process.env.MOBBDEV_LOCAL_CLI\n var child = localCli\n ? spawn('node', [localCli, 'claude-code-daemon'], { detached: true, stdio: 'ignore', windowsHide: true })\n : spawn('npx', ['--yes', 'mobbdev@latest', 'claude-code-daemon'], { detached: true, stdio: 'ignore', shell: true, windowsHide: true })\n child.unref()\n}\n";
18956
19116
 
18957
19117
  // src/features/claude_code/install_hook.ts
18958
- var CLAUDE_SETTINGS_PATH = path22.join(os6.homedir(), ".claude", "settings.json");
19118
+ var CLAUDE_SETTINGS_PATH = path23.join(os7.homedir(), ".claude", "settings.json");
18959
19119
  var RECOMMENDED_MATCHER = "*";
18960
19120
  async function claudeSettingsExists() {
18961
19121
  try {
@@ -18990,8 +19150,8 @@ function getDaemonCheckScript() {
18990
19150
  );
18991
19151
  }
18992
19152
  function writeDaemonCheckScript() {
18993
- fs14.mkdirSync(getMobbdevDir(), { recursive: true });
18994
- fs14.writeFileSync(getDaemonCheckScriptPath(), getDaemonCheckScript(), "utf8");
19153
+ fs15.mkdirSync(getMobbdevDir(), { recursive: true });
19154
+ fs15.writeFileSync(getDaemonCheckScriptPath(), getDaemonCheckScript(), "utf8");
18995
19155
  }
18996
19156
  function buildHookCommand(envPrefix) {
18997
19157
  const nodeBin = process.execPath || "node";
@@ -19102,17 +19262,17 @@ async function installMobbHooks(options = {}) {
19102
19262
 
19103
19263
  // src/features/claude_code/transcript_scanner.ts
19104
19264
  import { lstat as lstat2, open as open5, readdir as readdir4, stat as stat4 } from "fs/promises";
19105
- import os7 from "os";
19106
- import path23 from "path";
19265
+ import os8 from "os";
19266
+ import path24 from "path";
19107
19267
  var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
19108
19268
  function getClaudeProjectsDirs() {
19109
19269
  const dirs = [];
19110
19270
  const configDir = process.env["CLAUDE_CONFIG_DIR"];
19111
19271
  if (configDir) {
19112
- dirs.push(path23.join(configDir, "projects"));
19272
+ dirs.push(path24.join(configDir, "projects"));
19113
19273
  }
19114
- dirs.push(path23.join(os7.homedir(), ".config", "claude", "projects"));
19115
- dirs.push(path23.join(os7.homedir(), ".claude", "projects"));
19274
+ dirs.push(path24.join(os8.homedir(), ".config", "claude", "projects"));
19275
+ dirs.push(path24.join(os8.homedir(), ".claude", "projects"));
19116
19276
  return dirs;
19117
19277
  }
19118
19278
  var META_MAX_BYTES = 4096;
@@ -19168,7 +19328,7 @@ async function collectJsonlFiles(files, dir, projectDir, seen, now, results, ove
19168
19328
  sessionId = basename2;
19169
19329
  isSubagent = false;
19170
19330
  }
19171
- const filePath = path23.join(dir, file);
19331
+ const filePath = path24.join(dir, file);
19172
19332
  if (seen.has(filePath)) continue;
19173
19333
  seen.add(filePath);
19174
19334
  let fileStat;
@@ -19202,7 +19362,7 @@ async function scanForTranscripts(projectsDirs = getClaudeProjectsDirs()) {
19202
19362
  continue;
19203
19363
  }
19204
19364
  for (const projName of projectDirs) {
19205
- const projPath = path23.join(projectsDir, projName);
19365
+ const projPath = path24.join(projectsDir, projName);
19206
19366
  let projStat;
19207
19367
  try {
19208
19368
  projStat = await stat4(projPath);
@@ -19219,7 +19379,7 @@ async function scanForTranscripts(projectsDirs = getClaudeProjectsDirs()) {
19219
19379
  await collectJsonlFiles(files, projPath, projPath, seen, now, results);
19220
19380
  for (const entry of files) {
19221
19381
  if (!UUID_RE.test(entry)) continue;
19222
- const subagentsDir = path23.join(projPath, entry, "subagents");
19382
+ const subagentsDir = path24.join(projPath, entry, "subagents");
19223
19383
  if (knownAbsentSubagentDirs.has(subagentsDir)) continue;
19224
19384
  try {
19225
19385
  const s = await stat4(subagentsDir);
@@ -19325,8 +19485,8 @@ async function startDaemon() {
19325
19485
  const sessionCwdCache = /* @__PURE__ */ new Map();
19326
19486
  let lastContextScanMs = 0;
19327
19487
  const machineContext = {
19328
- cpuCount: os8.cpus().length,
19329
- totalMemGB: Math.round(os8.totalmem() / 1024 ** 3),
19488
+ cpuCount: os9.cpus().length,
19489
+ totalMemGB: Math.round(os9.totalmem() / 1024 ** 3),
19330
19490
  nodeVersion: process.version
19331
19491
  };
19332
19492
  while (true) {
@@ -19349,7 +19509,7 @@ async function startDaemon() {
19349
19509
  for (const transcript of changed) {
19350
19510
  const sessionStore = createSessionConfigStore(transcript.sessionId);
19351
19511
  if (!cleanupConfigDir) {
19352
- cleanupConfigDir = path24.dirname(sessionStore.path);
19512
+ cleanupConfigDir = path25.dirname(sessionStore.path);
19353
19513
  }
19354
19514
  pidFile.updateHeartbeat();
19355
19515
  const drainStart = Date.now();
@@ -19637,6 +19797,12 @@ var claudeCodeDaemonBuilder = (yargs2) => {
19637
19797
  ).strict();
19638
19798
  };
19639
19799
  var claudeCodeInstallHookHandler = async (argv) => {
19800
+ if (isStandaloneBinary()) {
19801
+ console.error(
19802
+ "Claude Code hooks are not available in the standalone mobbdev binary (they need a Node.js runtime). Install them with the npm package instead: npx mobbdev@latest claude-code-install-hook"
19803
+ );
19804
+ process.exit(1);
19805
+ }
19640
19806
  try {
19641
19807
  await getAuthenticatedGQLClient({ isSkipPrompts: false });
19642
19808
  await installMobbHooks({ saveEnv: argv["save-env"] });
@@ -19705,8 +19871,8 @@ var WorkspaceService = class {
19705
19871
  * Sets a known workspace path that was discovered through successful validation
19706
19872
  * @param path The validated workspace path to store
19707
19873
  */
19708
- static setKnownWorkspacePath(path37) {
19709
- this.knownWorkspacePath = path37;
19874
+ static setKnownWorkspacePath(path38) {
19875
+ this.knownWorkspacePath = path38;
19710
19876
  }
19711
19877
  /**
19712
19878
  * Gets the known workspace path that was previously validated
@@ -19847,7 +20013,7 @@ var logDebug = (message, data) => logger2.log(message, "debug", data);
19847
20013
  var log = logger2.log.bind(logger2);
19848
20014
 
19849
20015
  // src/mcp/services/McpGQLClient.ts
19850
- import os9 from "os";
20016
+ import os10 from "os";
19851
20017
  init_client_generates();
19852
20018
  init_configs();
19853
20019
 
@@ -20056,6 +20222,7 @@ var partitionInteractiveFixes = (fixes) => {
20056
20222
  };
20057
20223
 
20058
20224
  // src/mcp/services/McpGQLClient.ts
20225
+ var MVS_SCAN_ONLY_ERROR = "Mobb Vibe Shield is not available for your organization: it is on Mobb Scan (scan-only), which reports issues but does not generate fixes. Contact support to enable Mobb Fixer.";
20059
20226
  var McpGQLClient = class extends GQLClient {
20060
20227
  constructor(args) {
20061
20228
  super({
@@ -20235,12 +20402,16 @@ var McpGQLClient = class extends GQLClient {
20235
20402
  throw new Error("User email not found");
20236
20403
  }
20237
20404
  const orgRes = await this._clientSdk.getLastOrg({ email: userEmail });
20238
- const organizationId = orgRes.user?.[0]?.userOrganizationsAndUserOrganizationRoles?.[0]?.organization?.id;
20405
+ const organization = orgRes.user?.[0]?.userOrganizationsAndUserOrganizationRoles?.[0]?.organization;
20406
+ const organizationId = organization?.id;
20239
20407
  if (!organizationId) {
20240
20408
  throw new Error(
20241
20409
  `The user with email:${userEmail} is not associated with any organization`
20242
20410
  );
20243
20411
  }
20412
+ if (organization.isFixEnabled === false) {
20413
+ throw new Error(MVS_SCAN_ONLY_ERROR);
20414
+ }
20244
20415
  const mvsRes = await this._clientSdk.getMvsProject({ organizationId });
20245
20416
  const projectId = mvsRes.getMvsProject?.projectId;
20246
20417
  if (!projectId) {
@@ -20353,7 +20524,7 @@ var McpGQLClient = class extends GQLClient {
20353
20524
  projectId: params.projectId ?? null,
20354
20525
  repoUrl: params.repoUrl ?? null,
20355
20526
  riskCount: params.riskCount ?? null,
20356
- computerName: os9.hostname(),
20527
+ computerName: os10.hostname(),
20357
20528
  computerUser: getComputerUser() ?? null,
20358
20529
  clientVersion: packageJson.version
20359
20530
  });
@@ -20636,9 +20807,9 @@ async function createAuthenticatedMcpGQLClient({
20636
20807
 
20637
20808
  // src/mcp/services/McpUsageService/host.ts
20638
20809
  import { execSync as execSync2 } from "child_process";
20639
- import fs15 from "fs";
20640
- import os10 from "os";
20641
- import path25 from "path";
20810
+ import fs16 from "fs";
20811
+ import os11 from "os";
20812
+ import path26 from "path";
20642
20813
  var IDEs = ["cursor", "windsurf", "webstorm", "vscode", "claude"];
20643
20814
  var runCommand = (cmd) => {
20644
20815
  try {
@@ -20652,18 +20823,18 @@ var gitInfo = {
20652
20823
  email: runCommand("git config user.email")
20653
20824
  };
20654
20825
  var getClaudeWorkspacePaths = () => {
20655
- const home = os10.homedir();
20656
- const claudeIdePath = path25.join(home, ".claude", "ide");
20826
+ const home = os11.homedir();
20827
+ const claudeIdePath = path26.join(home, ".claude", "ide");
20657
20828
  const workspacePaths = [];
20658
- if (!fs15.existsSync(claudeIdePath)) {
20829
+ if (!fs16.existsSync(claudeIdePath)) {
20659
20830
  return workspacePaths;
20660
20831
  }
20661
20832
  try {
20662
- const lockFiles = fs15.readdirSync(claudeIdePath).filter((file) => file.endsWith(".lock"));
20833
+ const lockFiles = fs16.readdirSync(claudeIdePath).filter((file) => file.endsWith(".lock"));
20663
20834
  for (const lockFile of lockFiles) {
20664
- const lockFilePath = path25.join(claudeIdePath, lockFile);
20835
+ const lockFilePath = path26.join(claudeIdePath, lockFile);
20665
20836
  try {
20666
- const lockContent = JSON.parse(fs15.readFileSync(lockFilePath, "utf8"));
20837
+ const lockContent = JSON.parse(fs16.readFileSync(lockFilePath, "utf8"));
20667
20838
  if (lockContent.workspaceFolders && Array.isArray(lockContent.workspaceFolders)) {
20668
20839
  workspacePaths.push(...lockContent.workspaceFolders);
20669
20840
  }
@@ -20681,29 +20852,29 @@ var getClaudeWorkspacePaths = () => {
20681
20852
  return workspacePaths;
20682
20853
  };
20683
20854
  var getMCPConfigPaths = (hostName) => {
20684
- const home = os10.homedir();
20855
+ const home = os11.homedir();
20685
20856
  const currentDir = process.env["WORKSPACE_FOLDER_PATHS"] || process.env["PWD"] || process.cwd();
20686
20857
  switch (hostName.toLowerCase()) {
20687
20858
  case "cursor":
20688
20859
  return [
20689
- path25.join(currentDir, ".cursor", "mcp.json"),
20860
+ path26.join(currentDir, ".cursor", "mcp.json"),
20690
20861
  // local first
20691
- path25.join(home, ".cursor", "mcp.json")
20862
+ path26.join(home, ".cursor", "mcp.json")
20692
20863
  ];
20693
20864
  case "windsurf":
20694
20865
  return [
20695
- path25.join(currentDir, ".codeium", "mcp_config.json"),
20866
+ path26.join(currentDir, ".codeium", "mcp_config.json"),
20696
20867
  // local first
20697
- path25.join(home, ".codeium", "windsurf", "mcp_config.json")
20868
+ path26.join(home, ".codeium", "windsurf", "mcp_config.json")
20698
20869
  ];
20699
20870
  case "webstorm":
20700
20871
  return [];
20701
20872
  case "visualstudiocode":
20702
20873
  case "vscode":
20703
20874
  return [
20704
- path25.join(currentDir, ".vscode", "mcp.json"),
20875
+ path26.join(currentDir, ".vscode", "mcp.json"),
20705
20876
  // local first
20706
- process.platform === "win32" ? path25.join(home, "AppData", "Roaming", "Code", "User", "mcp.json") : path25.join(
20877
+ process.platform === "win32" ? path26.join(home, "AppData", "Roaming", "Code", "User", "mcp.json") : path26.join(
20707
20878
  home,
20708
20879
  "Library",
20709
20880
  "Application Support",
@@ -20714,13 +20885,13 @@ var getMCPConfigPaths = (hostName) => {
20714
20885
  ];
20715
20886
  case "claude": {
20716
20887
  const claudePaths = [
20717
- path25.join(currentDir, ".claude.json"),
20888
+ path26.join(currentDir, ".claude.json"),
20718
20889
  // local first
20719
- path25.join(home, ".claude.json")
20890
+ path26.join(home, ".claude.json")
20720
20891
  ];
20721
20892
  const workspacePaths = getClaudeWorkspacePaths();
20722
20893
  for (const workspacePath of workspacePaths) {
20723
- claudePaths.push(path25.join(workspacePath, ".mcp.json"));
20894
+ claudePaths.push(path26.join(workspacePath, ".mcp.json"));
20724
20895
  }
20725
20896
  return claudePaths;
20726
20897
  }
@@ -20729,9 +20900,9 @@ var getMCPConfigPaths = (hostName) => {
20729
20900
  }
20730
20901
  };
20731
20902
  var readConfigFile = (filePath) => {
20732
- if (!fs15.existsSync(filePath)) return null;
20903
+ if (!fs16.existsSync(filePath)) return null;
20733
20904
  try {
20734
- return JSON.parse(fs15.readFileSync(filePath, "utf8"));
20905
+ return JSON.parse(fs16.readFileSync(filePath, "utf8"));
20735
20906
  } catch (error) {
20736
20907
  logWarn(`[UsageService] Failed to read MCP config: ${filePath}`);
20737
20908
  return null;
@@ -20771,7 +20942,7 @@ var readMCPConfig = (hostName) => {
20771
20942
  };
20772
20943
  var getRunningProcesses = () => {
20773
20944
  try {
20774
- return os10.platform() === "win32" ? execSync2("tasklist", { encoding: "utf8" }) : execSync2("ps aux", { encoding: "utf8" });
20945
+ return os11.platform() === "win32" ? execSync2("tasklist", { encoding: "utf8" }) : execSync2("ps aux", { encoding: "utf8" });
20775
20946
  } catch {
20776
20947
  return "";
20777
20948
  }
@@ -20846,7 +21017,7 @@ var versionCommands = {
20846
21017
  }
20847
21018
  };
20848
21019
  var getProcessInfo = (pid) => {
20849
- const platform2 = os10.platform();
21020
+ const platform2 = os11.platform();
20850
21021
  try {
20851
21022
  if (platform2 === "linux" || platform2 === "darwin") {
20852
21023
  const output = execSync2(`ps -o pid=,ppid=,comm= -p ${pid}`, {
@@ -20881,10 +21052,10 @@ var getHostInfo = (additionalMcpList) => {
20881
21052
  const ideConfigPaths = /* @__PURE__ */ new Set();
20882
21053
  for (const ide of IDEs) {
20883
21054
  const configPaths = getMCPConfigPaths(ide);
20884
- configPaths.forEach((path37) => ideConfigPaths.add(path37));
21055
+ configPaths.forEach((path38) => ideConfigPaths.add(path38));
20885
21056
  }
20886
21057
  const uniqueAdditionalPaths = additionalMcpList.filter(
20887
- (path37) => !ideConfigPaths.has(path37)
21058
+ (path38) => !ideConfigPaths.has(path38)
20888
21059
  );
20889
21060
  for (const ide of IDEs) {
20890
21061
  const cfg = readMCPConfig(ide);
@@ -20965,7 +21136,7 @@ var getHostInfo = (additionalMcpList) => {
20965
21136
  const config2 = allConfigs[ide] || null;
20966
21137
  const ideName = ide.charAt(0).toUpperCase() + ide.slice(1) || "Unknown";
20967
21138
  let ideVersion = "Unknown";
20968
- const platform2 = os10.platform();
21139
+ const platform2 = os11.platform();
20969
21140
  const cmds = versionCommands[ideName]?.[platform2] ?? [];
20970
21141
  for (const cmd of cmds) {
20971
21142
  try {
@@ -20998,15 +21169,15 @@ var getHostInfo = (additionalMcpList) => {
20998
21169
 
20999
21170
  // src/mcp/services/McpUsageService/McpUsageService.ts
21000
21171
  import fetch6 from "node-fetch";
21001
- import os12 from "os";
21172
+ import os13 from "os";
21002
21173
  import { v4 as uuidv42, v5 as uuidv5 } from "uuid";
21003
21174
  init_configs();
21004
21175
 
21005
21176
  // src/mcp/services/McpUsageService/system.ts
21006
21177
  init_configs();
21007
- import fs16 from "fs";
21008
- import os11 from "os";
21009
- import path26 from "path";
21178
+ import fs17 from "fs";
21179
+ import os12 from "os";
21180
+ import path27 from "path";
21010
21181
  var MAX_DEPTH = 2;
21011
21182
  var patterns = ["mcp", "claude"];
21012
21183
  var isFileMatch = (fileName) => {
@@ -21015,7 +21186,7 @@ var isFileMatch = (fileName) => {
21015
21186
  };
21016
21187
  var safeAccess = async (filePath) => {
21017
21188
  try {
21018
- await fs16.promises.access(filePath, fs16.constants.R_OK);
21189
+ await fs17.promises.access(filePath, fs17.constants.R_OK);
21019
21190
  return true;
21020
21191
  } catch {
21021
21192
  return false;
@@ -21024,9 +21195,9 @@ var safeAccess = async (filePath) => {
21024
21195
  var searchDir = async (dir, depth = 0) => {
21025
21196
  const results = [];
21026
21197
  if (depth > MAX_DEPTH) return results;
21027
- const entries = await fs16.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
21198
+ const entries = await fs17.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
21028
21199
  for (const entry of entries) {
21029
- const fullPath = path26.join(dir, entry.name);
21200
+ const fullPath = path27.join(dir, entry.name);
21030
21201
  if (entry.isFile() && isFileMatch(entry.name)) {
21031
21202
  results.push(fullPath);
21032
21203
  } else if (entry.isDirectory()) {
@@ -21040,17 +21211,17 @@ var searchDir = async (dir, depth = 0) => {
21040
21211
  };
21041
21212
  var findSystemMCPConfigs = async () => {
21042
21213
  try {
21043
- const home = os11.homedir();
21044
- const platform2 = os11.platform();
21214
+ const home = os12.homedir();
21215
+ const platform2 = os12.platform();
21045
21216
  const knownDirs = platform2 === "win32" ? [
21046
- path26.join(home, ".cursor"),
21047
- path26.join(home, "Documents"),
21048
- path26.join(home, "Downloads")
21217
+ path27.join(home, ".cursor"),
21218
+ path27.join(home, "Documents"),
21219
+ path27.join(home, "Downloads")
21049
21220
  ] : [
21050
- path26.join(home, ".cursor"),
21051
- process.env["XDG_CONFIG_HOME"] || path26.join(home, ".config"),
21052
- path26.join(home, "Documents"),
21053
- path26.join(home, "Downloads")
21221
+ path27.join(home, ".cursor"),
21222
+ process.env["XDG_CONFIG_HOME"] || path27.join(home, ".config"),
21223
+ path27.join(home, "Documents"),
21224
+ path27.join(home, "Downloads")
21054
21225
  ];
21055
21226
  const timeoutPromise = new Promise(
21056
21227
  (resolve) => setTimeout(() => {
@@ -21062,7 +21233,7 @@ var findSystemMCPConfigs = async () => {
21062
21233
  );
21063
21234
  const searchPromise = Promise.all(
21064
21235
  knownDirs.map(
21065
- (dir) => fs16.existsSync(dir) ? searchDir(dir) : Promise.resolve([])
21236
+ (dir) => fs17.existsSync(dir) ? searchDir(dir) : Promise.resolve([])
21066
21237
  )
21067
21238
  ).then((results) => results.flat());
21068
21239
  return await Promise.race([timeoutPromise, searchPromise]);
@@ -21113,7 +21284,7 @@ var McpUsageService = class {
21113
21284
  generateHostId() {
21114
21285
  const stored = configStore.get(this.configKey);
21115
21286
  if (stored?.mcpHostId) return stored.mcpHostId;
21116
- const interfaces = os12.networkInterfaces();
21287
+ const interfaces = os13.networkInterfaces();
21117
21288
  const macs = [];
21118
21289
  for (const iface of Object.values(interfaces)) {
21119
21290
  if (!iface) continue;
@@ -21121,7 +21292,7 @@ var McpUsageService = class {
21121
21292
  if (net.mac && net.mac !== "00:00:00:00:00:00") macs.push(net.mac);
21122
21293
  }
21123
21294
  }
21124
- const macString = macs.length ? macs.sort().join(",") : `${os12.hostname()}-${uuidv42()}`;
21295
+ const macString = macs.length ? macs.sort().join(",") : `${os13.hostname()}-${uuidv42()}`;
21125
21296
  const hostId = uuidv5(macString, uuidv5.DNS);
21126
21297
  logDebug("[UsageService] Generated new host ID", { hostId });
21127
21298
  return hostId;
@@ -21144,7 +21315,7 @@ var McpUsageService = class {
21144
21315
  mcpHostId,
21145
21316
  organizationId,
21146
21317
  mcpVersion: packageJson.version,
21147
- mcpOsName: os12.platform(),
21318
+ mcpOsName: os13.platform(),
21148
21319
  mcps: JSON.stringify(mcps),
21149
21320
  status,
21150
21321
  userName: user.name,
@@ -23465,31 +23636,31 @@ For a complete security audit workflow, use the \`full-security-audit\` prompt.
23465
23636
  };
23466
23637
 
23467
23638
  // src/mcp/services/McpDetectionService/CursorMcpDetectionService.ts
23468
- import * as fs19 from "fs";
23469
- import * as os14 from "os";
23470
- import * as path28 from "path";
23639
+ import * as fs20 from "fs";
23640
+ import * as os15 from "os";
23641
+ import * as path29 from "path";
23471
23642
 
23472
23643
  // src/mcp/services/McpDetectionService/BaseMcpDetectionService.ts
23473
23644
  init_configs();
23474
- import * as fs18 from "fs";
23645
+ import * as fs19 from "fs";
23475
23646
  import fetch7 from "node-fetch";
23476
- import * as path27 from "path";
23647
+ import * as path28 from "path";
23477
23648
 
23478
23649
  // src/mcp/services/McpDetectionService/McpDetectionServiceUtils.ts
23479
- import * as fs17 from "fs";
23480
- import * as os13 from "os";
23650
+ import * as fs18 from "fs";
23651
+ import * as os14 from "os";
23481
23652
 
23482
23653
  // src/mcp/services/McpDetectionService/VscodeMcpDetectionService.ts
23483
- import * as fs20 from "fs";
23484
- import * as os15 from "os";
23485
- import * as path29 from "path";
23654
+ import * as fs21 from "fs";
23655
+ import * as os16 from "os";
23656
+ import * as path30 from "path";
23486
23657
 
23487
23658
  // src/mcp/tools/checkForNewAvailableFixes/CheckForNewAvailableFixesTool.ts
23488
23659
  import { z as z37 } from "zod";
23489
23660
 
23490
23661
  // src/mcp/services/PathValidation.ts
23491
- import fs21 from "fs";
23492
- import path30 from "path";
23662
+ import fs22 from "fs";
23663
+ import path31 from "path";
23493
23664
  async function validatePath(inputPath) {
23494
23665
  logDebug("Validating MCP path", { inputPath });
23495
23666
  if (/^\/[a-zA-Z]:\//.test(inputPath)) {
@@ -23521,7 +23692,7 @@ async function validatePath(inputPath) {
23521
23692
  logError(error);
23522
23693
  return { isValid: false, error, path: inputPath };
23523
23694
  }
23524
- const normalizedPath = path30.normalize(inputPath);
23695
+ const normalizedPath = path31.normalize(inputPath);
23525
23696
  if (normalizedPath.includes("..")) {
23526
23697
  const error = `Normalized path contains path traversal patterns: ${inputPath}`;
23527
23698
  logError(error);
@@ -23548,7 +23719,7 @@ async function validatePath(inputPath) {
23548
23719
  logDebug("Path validation successful", { inputPath });
23549
23720
  logDebug("Checking path existence", { inputPath });
23550
23721
  try {
23551
- await fs21.promises.access(inputPath);
23722
+ await fs22.promises.access(inputPath);
23552
23723
  logDebug("Path exists and is accessible", { inputPath });
23553
23724
  WorkspaceService.setKnownWorkspacePath(inputPath);
23554
23725
  logDebug("Stored validated path in WorkspaceService", { inputPath });
@@ -24302,10 +24473,10 @@ If you wish to scan files that were recently changed in your git history call th
24302
24473
  init_FileUtils();
24303
24474
  init_GitService();
24304
24475
  init_configs();
24305
- import fs22 from "fs/promises";
24476
+ import fs23 from "fs/promises";
24306
24477
  import nodePath from "path";
24307
24478
  var getLocalFiles = async ({
24308
- path: path37,
24479
+ path: path38,
24309
24480
  maxFileSize = MCP_MAX_FILE_SIZE,
24310
24481
  maxFiles,
24311
24482
  isAllFilesScan,
@@ -24313,17 +24484,17 @@ var getLocalFiles = async ({
24313
24484
  scanRecentlyChangedFiles
24314
24485
  }) => {
24315
24486
  logDebug(`[${scanContext}] Starting getLocalFiles`, {
24316
- path: path37,
24487
+ path: path38,
24317
24488
  maxFileSize,
24318
24489
  maxFiles,
24319
24490
  isAllFilesScan,
24320
24491
  scanRecentlyChangedFiles
24321
24492
  });
24322
24493
  try {
24323
- const resolvedRepoPath = await fs22.realpath(path37);
24494
+ const resolvedRepoPath = await fs23.realpath(path38);
24324
24495
  logDebug(`[${scanContext}] Resolved repository path`, {
24325
24496
  resolvedRepoPath,
24326
- originalPath: path37
24497
+ originalPath: path38
24327
24498
  });
24328
24499
  const gitService = new GitService(resolvedRepoPath, log);
24329
24500
  const gitValidation = await gitService.validateRepository();
@@ -24336,7 +24507,7 @@ var getLocalFiles = async ({
24336
24507
  if (!gitValidation.isValid || isAllFilesScan) {
24337
24508
  try {
24338
24509
  files = await FileUtils.getLastChangedFiles({
24339
- dir: path37,
24510
+ dir: path38,
24340
24511
  maxFileSize,
24341
24512
  maxFiles,
24342
24513
  isAllFilesScan
@@ -24400,7 +24571,7 @@ var getLocalFiles = async ({
24400
24571
  absoluteFilePath
24401
24572
  );
24402
24573
  try {
24403
- const fileStat = await fs22.stat(absoluteFilePath);
24574
+ const fileStat = await fs23.stat(absoluteFilePath);
24404
24575
  return {
24405
24576
  filename: nodePath.basename(absoluteFilePath),
24406
24577
  relativePath,
@@ -24428,7 +24599,7 @@ var getLocalFiles = async ({
24428
24599
  logError(`${scanContext}Unexpected error in getLocalFiles`, {
24429
24600
  error: error instanceof Error ? error.message : String(error),
24430
24601
  stack: error instanceof Error ? error.stack : void 0,
24431
- path: path37
24602
+ path: path38
24432
24603
  });
24433
24604
  throw error;
24434
24605
  }
@@ -24437,8 +24608,8 @@ var getLocalFiles = async ({
24437
24608
  // src/mcp/services/LocalMobbFolderService.ts
24438
24609
  init_GitService();
24439
24610
  init_issueTypeCatalog();
24440
- import fs23 from "fs";
24441
- import path31 from "path";
24611
+ import fs24 from "fs";
24612
+ import path32 from "path";
24442
24613
  function extractPathFromPatch(patch) {
24443
24614
  const match = patch?.match(/diff --git a\/([^\s]+) b\//);
24444
24615
  return match?.[1] ?? null;
@@ -24520,19 +24691,19 @@ var LocalMobbFolderService = class {
24520
24691
  "[LocalMobbFolderService] Non-git repository detected, skipping .gitignore operations"
24521
24692
  );
24522
24693
  }
24523
- const mobbFolderPath = path31.join(
24694
+ const mobbFolderPath = path32.join(
24524
24695
  this.repoPath,
24525
24696
  this.defaultMobbFolderName
24526
24697
  );
24527
- if (!fs23.existsSync(mobbFolderPath)) {
24698
+ if (!fs24.existsSync(mobbFolderPath)) {
24528
24699
  logInfo("[LocalMobbFolderService] Creating .mobb folder", {
24529
24700
  mobbFolderPath
24530
24701
  });
24531
- fs23.mkdirSync(mobbFolderPath, { recursive: true });
24702
+ fs24.mkdirSync(mobbFolderPath, { recursive: true });
24532
24703
  } else {
24533
24704
  logDebug("[LocalMobbFolderService] .mobb folder already exists");
24534
24705
  }
24535
- const stats = fs23.statSync(mobbFolderPath);
24706
+ const stats = fs24.statSync(mobbFolderPath);
24536
24707
  if (!stats.isDirectory()) {
24537
24708
  throw new Error(`Path exists but is not a directory: ${mobbFolderPath}`);
24538
24709
  }
@@ -24573,13 +24744,13 @@ var LocalMobbFolderService = class {
24573
24744
  logDebug("[LocalMobbFolderService] Git repository validated successfully");
24574
24745
  } else {
24575
24746
  try {
24576
- const stats = fs23.statSync(this.repoPath);
24747
+ const stats = fs24.statSync(this.repoPath);
24577
24748
  if (!stats.isDirectory()) {
24578
24749
  throw new Error(
24579
24750
  `Path exists but is not a directory: ${this.repoPath}`
24580
24751
  );
24581
24752
  }
24582
- fs23.accessSync(this.repoPath, fs23.constants.R_OK | fs23.constants.W_OK);
24753
+ fs24.accessSync(this.repoPath, fs24.constants.R_OK | fs24.constants.W_OK);
24583
24754
  logDebug(
24584
24755
  "[LocalMobbFolderService] Non-git directory validated successfully"
24585
24756
  );
@@ -24692,8 +24863,8 @@ var LocalMobbFolderService = class {
24692
24863
  mobbFolderPath,
24693
24864
  baseFileName
24694
24865
  );
24695
- const filePath = path31.join(mobbFolderPath, uniqueFileName);
24696
- await fs23.promises.writeFile(filePath, patch, "utf8");
24866
+ const filePath = path32.join(mobbFolderPath, uniqueFileName);
24867
+ await fs24.promises.writeFile(filePath, patch, "utf8");
24697
24868
  logInfo("[LocalMobbFolderService] Patch saved successfully", {
24698
24869
  filePath,
24699
24870
  fileName: uniqueFileName,
@@ -24750,11 +24921,11 @@ var LocalMobbFolderService = class {
24750
24921
  * @returns Unique filename that doesn't conflict with existing files
24751
24922
  */
24752
24923
  getUniqueFileName(folderPath, baseFileName) {
24753
- const baseName = path31.parse(baseFileName).name;
24754
- const extension = path31.parse(baseFileName).ext;
24924
+ const baseName = path32.parse(baseFileName).name;
24925
+ const extension = path32.parse(baseFileName).ext;
24755
24926
  let uniqueFileName = baseFileName;
24756
24927
  let index = 1;
24757
- while (fs23.existsSync(path31.join(folderPath, uniqueFileName))) {
24928
+ while (fs24.existsSync(path32.join(folderPath, uniqueFileName))) {
24758
24929
  uniqueFileName = `${baseName}-${index}${extension}`;
24759
24930
  index++;
24760
24931
  if (index > 1e3) {
@@ -24785,18 +24956,18 @@ var LocalMobbFolderService = class {
24785
24956
  logDebug("[LocalMobbFolderService] Logging patch info", { fixId: fix.id });
24786
24957
  try {
24787
24958
  const mobbFolderPath = await this.getFolder();
24788
- const patchInfoPath = path31.join(mobbFolderPath, "patchInfo.md");
24959
+ const patchInfoPath = path32.join(mobbFolderPath, "patchInfo.md");
24789
24960
  const markdownContent = this.generateFixMarkdown(fix, savedPatchFileName);
24790
24961
  let existingContent = "";
24791
- if (fs23.existsSync(patchInfoPath)) {
24792
- existingContent = await fs23.promises.readFile(patchInfoPath, "utf8");
24962
+ if (fs24.existsSync(patchInfoPath)) {
24963
+ existingContent = await fs24.promises.readFile(patchInfoPath, "utf8");
24793
24964
  logDebug("[LocalMobbFolderService] Existing patchInfo.md found");
24794
24965
  } else {
24795
24966
  logDebug("[LocalMobbFolderService] Creating new patchInfo.md file");
24796
24967
  }
24797
24968
  const separator = existingContent ? "\n\n================================================================================\n\n" : "";
24798
24969
  const updatedContent = `${markdownContent}${separator}${existingContent}`;
24799
- await fs23.promises.writeFile(patchInfoPath, updatedContent, "utf8");
24970
+ await fs24.promises.writeFile(patchInfoPath, updatedContent, "utf8");
24800
24971
  logInfo("[LocalMobbFolderService] Patch info logged successfully", {
24801
24972
  patchInfoPath,
24802
24973
  fixId: fix.id,
@@ -24827,7 +24998,7 @@ var LocalMobbFolderService = class {
24827
24998
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
24828
24999
  const patch = this.extractPatchFromFix(fix);
24829
25000
  const relativePatchedFilePath = patch ? extractPathFromPatch(patch) : null;
24830
- const patchedFilePath = relativePatchedFilePath ? path31.resolve(this.repoPath, relativePatchedFilePath) : null;
25001
+ const patchedFilePath = relativePatchedFilePath ? path32.resolve(this.repoPath, relativePatchedFilePath) : null;
24831
25002
  const fixIdentifier = savedPatchFileName ? savedPatchFileName.replace(".patch", "") : fix.id;
24832
25003
  let markdown = `# Fix ${fixIdentifier}
24833
25004
 
@@ -25169,16 +25340,16 @@ import {
25169
25340
  unlinkSync,
25170
25341
  writeFileSync as writeFileSync3
25171
25342
  } from "fs";
25172
- import fs24 from "fs/promises";
25343
+ import fs25 from "fs/promises";
25173
25344
  import parseDiff2 from "parse-diff";
25174
- import path32 from "path";
25345
+ import path33 from "path";
25175
25346
  var PatchApplicationService = class {
25176
25347
  /**
25177
25348
  * Gets the appropriate comment syntax for a file based on its extension
25178
25349
  */
25179
25350
  static getCommentSyntax(filePath) {
25180
- const ext = path32.extname(filePath).toLowerCase();
25181
- const basename2 = path32.basename(filePath);
25351
+ const ext = path33.extname(filePath).toLowerCase();
25352
+ const basename2 = path33.basename(filePath);
25182
25353
  const commentMap = {
25183
25354
  // C-style languages (single line comments)
25184
25355
  ".js": "//",
@@ -25386,7 +25557,7 @@ var PatchApplicationService = class {
25386
25557
  }
25387
25558
  );
25388
25559
  }
25389
- const dirPath = path32.dirname(normalizedFilePath);
25560
+ const dirPath = path33.dirname(normalizedFilePath);
25390
25561
  mkdirSync(dirPath, { recursive: true });
25391
25562
  writeFileSync3(normalizedFilePath, finalContent, "utf8");
25392
25563
  return normalizedFilePath;
@@ -25395,9 +25566,9 @@ var PatchApplicationService = class {
25395
25566
  repositoryPath,
25396
25567
  targetPath
25397
25568
  }) {
25398
- const repoRoot = path32.resolve(repositoryPath);
25399
- const normalizedPath = path32.resolve(repoRoot, targetPath);
25400
- const repoRootWithSep = repoRoot.endsWith(path32.sep) ? repoRoot : `${repoRoot}${path32.sep}`;
25569
+ const repoRoot = path33.resolve(repositoryPath);
25570
+ const normalizedPath = path33.resolve(repoRoot, targetPath);
25571
+ const repoRootWithSep = repoRoot.endsWith(path33.sep) ? repoRoot : `${repoRoot}${path33.sep}`;
25401
25572
  if (normalizedPath !== repoRoot && !normalizedPath.startsWith(repoRootWithSep)) {
25402
25573
  throw new Error(
25403
25574
  `Security violation: target path ${targetPath} resolves outside repository`
@@ -25406,7 +25577,7 @@ var PatchApplicationService = class {
25406
25577
  return {
25407
25578
  repoRoot,
25408
25579
  normalizedPath,
25409
- relativePath: path32.relative(repoRoot, normalizedPath)
25580
+ relativePath: path33.relative(repoRoot, normalizedPath)
25410
25581
  };
25411
25582
  }
25412
25583
  /**
@@ -25688,9 +25859,9 @@ var PatchApplicationService = class {
25688
25859
  continue;
25689
25860
  }
25690
25861
  try {
25691
- const absolutePath = path32.resolve(repositoryPath, targetFile);
25862
+ const absolutePath = path33.resolve(repositoryPath, targetFile);
25692
25863
  if (existsSync6(absolutePath)) {
25693
- const stats = await fs24.stat(absolutePath);
25864
+ const stats = await fs25.stat(absolutePath);
25694
25865
  const fileModTime = stats.mtime.getTime();
25695
25866
  if (fileModTime > scanStartTime) {
25696
25867
  logError(
@@ -25732,7 +25903,7 @@ var PatchApplicationService = class {
25732
25903
  const appliedFixes = [];
25733
25904
  const failedFixes = [];
25734
25905
  const skippedFixes = [];
25735
- const resolvedRepoPath = await fs24.realpath(repositoryPath);
25906
+ const resolvedRepoPath = await fs25.realpath(repositoryPath);
25736
25907
  logInfo(
25737
25908
  `[${scanContext}] Starting patch application for ${fixes.length} fixes`,
25738
25909
  {
@@ -25921,7 +26092,7 @@ var PatchApplicationService = class {
25921
26092
  fix,
25922
26093
  scanContext
25923
26094
  });
25924
- appliedFiles.push(path32.relative(repositoryPath, actualPath));
26095
+ appliedFiles.push(path33.relative(repositoryPath, actualPath));
25925
26096
  logDebug(`[${scanContext}] Created new file: ${relativePath}`);
25926
26097
  }
25927
26098
  /**
@@ -25970,7 +26141,7 @@ var PatchApplicationService = class {
25970
26141
  fix,
25971
26142
  scanContext
25972
26143
  });
25973
- appliedFiles.push(path32.relative(repositoryPath, actualPath));
26144
+ appliedFiles.push(path33.relative(repositoryPath, actualPath));
25974
26145
  logDebug(`[${scanContext}] Modified file: ${relativePath}`);
25975
26146
  }
25976
26147
  }
@@ -26162,13 +26333,13 @@ var PatchApplicationService = class {
26162
26333
  // src/mcp/services/ScanFiles.ts
26163
26334
  init_client_generates();
26164
26335
  init_GitService();
26165
- import os16 from "os";
26336
+ import os17 from "os";
26166
26337
  init_configs();
26167
26338
 
26168
26339
  // src/mcp/services/FileOperations.ts
26169
26340
  init_FileUtils();
26170
- import fs25 from "fs";
26171
- import path33 from "path";
26341
+ import fs26 from "fs";
26342
+ import path34 from "path";
26172
26343
  import AdmZip5 from "adm-zip";
26173
26344
  var FileOperations = class {
26174
26345
  /**
@@ -26188,10 +26359,10 @@ var FileOperations = class {
26188
26359
  let packedFilesCount = 0;
26189
26360
  const packedFiles = [];
26190
26361
  const excludedFiles = [];
26191
- const resolvedRepoPath = path33.resolve(repositoryPath);
26362
+ const resolvedRepoPath = path34.resolve(repositoryPath);
26192
26363
  for (const filepath of fileList) {
26193
- const absoluteFilepath = path33.join(repositoryPath, filepath);
26194
- const resolvedFilePath = path33.resolve(absoluteFilepath);
26364
+ const absoluteFilepath = path34.join(repositoryPath, filepath);
26365
+ const resolvedFilePath = path34.resolve(absoluteFilepath);
26195
26366
  if (!resolvedFilePath.startsWith(resolvedRepoPath)) {
26196
26367
  const reason = "potential path traversal security risk";
26197
26368
  logDebug(`[FileOperations] Skipping ${filepath} due to ${reason}`);
@@ -26238,11 +26409,11 @@ var FileOperations = class {
26238
26409
  fileList,
26239
26410
  repositoryPath
26240
26411
  }) {
26241
- const resolvedRepoPath = path33.resolve(repositoryPath);
26412
+ const resolvedRepoPath = path34.resolve(repositoryPath);
26242
26413
  const validatedPaths = [];
26243
26414
  for (const filepath of fileList) {
26244
- const absoluteFilepath = path33.join(repositoryPath, filepath);
26245
- const resolvedFilePath = path33.resolve(absoluteFilepath);
26415
+ const absoluteFilepath = path34.join(repositoryPath, filepath);
26416
+ const resolvedFilePath = path34.resolve(absoluteFilepath);
26246
26417
  if (!resolvedFilePath.startsWith(resolvedRepoPath)) {
26247
26418
  logDebug(
26248
26419
  `[FileOperations] Rejecting ${filepath} - path traversal attempt detected`
@@ -26250,7 +26421,7 @@ var FileOperations = class {
26250
26421
  continue;
26251
26422
  }
26252
26423
  try {
26253
- await fs25.promises.access(absoluteFilepath, fs25.constants.R_OK);
26424
+ await fs26.promises.access(absoluteFilepath, fs26.constants.R_OK);
26254
26425
  validatedPaths.push(filepath);
26255
26426
  } catch (error) {
26256
26427
  logDebug(
@@ -26269,8 +26440,8 @@ var FileOperations = class {
26269
26440
  const fileDataArray = [];
26270
26441
  for (const absolutePath of filePaths) {
26271
26442
  try {
26272
- const content = await fs25.promises.readFile(absolutePath);
26273
- const relativePath = path33.basename(absolutePath);
26443
+ const content = await fs26.promises.readFile(absolutePath);
26444
+ const relativePath = path34.basename(absolutePath);
26274
26445
  fileDataArray.push({
26275
26446
  relativePath,
26276
26447
  absolutePath,
@@ -26295,7 +26466,7 @@ var FileOperations = class {
26295
26466
  relativeFilepath
26296
26467
  }) {
26297
26468
  try {
26298
- return await fs25.promises.readFile(absoluteFilepath);
26469
+ return await fs26.promises.readFile(absoluteFilepath);
26299
26470
  } catch (fsError) {
26300
26471
  logError(
26301
26472
  `[FileOperations] Failed to read ${relativeFilepath} from filesystem: ${fsError}`
@@ -26439,7 +26610,7 @@ var executeSecurityScan = async ({
26439
26610
  fileCount,
26440
26611
  // MVS device attribution: a developer appears in the MVS Developers grid
26441
26612
  // from scanning alone (no fresh login needed).
26442
- computerName: os16.hostname(),
26613
+ computerName: os17.hostname(),
26443
26614
  computerUser: getComputerUser(),
26444
26615
  clientVersion: packageJson.version
26445
26616
  };
@@ -26589,14 +26760,14 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
26589
26760
  * since the last scan.
26590
26761
  */
26591
26762
  async scanForSecurityVulnerabilities({
26592
- path: path37,
26763
+ path: path38,
26593
26764
  isAllDetectionRulesScan,
26594
26765
  isAllFilesScan,
26595
26766
  scanContext
26596
26767
  }) {
26597
26768
  this.hasAuthenticationFailed = false;
26598
26769
  logDebug(`[${scanContext}] Scanning for new security vulnerabilities`, {
26599
- path: path37
26770
+ path: path38
26600
26771
  });
26601
26772
  if (!this.gqlClient) {
26602
26773
  logInfo(`[${scanContext}] No GQL client found, skipping scan`);
@@ -26612,11 +26783,11 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
26612
26783
  }
26613
26784
  logDebug(
26614
26785
  `[${scanContext}] Connected to the API, assembling list of files to scan`,
26615
- { path: path37 }
26786
+ { path: path38 }
26616
26787
  );
26617
26788
  const isBackgroundScan = scanContext === ScanContext.BACKGROUND_INITIAL || scanContext === ScanContext.BACKGROUND_PERIODIC;
26618
26789
  const files = await getLocalFiles({
26619
- path: path37,
26790
+ path: path38,
26620
26791
  isAllFilesScan,
26621
26792
  scanContext,
26622
26793
  scanRecentlyChangedFiles: !isBackgroundScan
@@ -26642,13 +26813,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
26642
26813
  });
26643
26814
  const { fixReportId, projectId } = await scanFiles({
26644
26815
  fileList: filesToScan.map((file) => file.relativePath),
26645
- repositoryPath: path37,
26816
+ repositoryPath: path38,
26646
26817
  gqlClient: this.gqlClient,
26647
26818
  isAllDetectionRulesScan,
26648
26819
  scanContext
26649
26820
  });
26650
26821
  logInfo(
26651
- `[${scanContext}] Security scan completed for ${path37} reportId: ${fixReportId} projectId: ${projectId}`
26822
+ `[${scanContext}] Security scan completed for ${path38} reportId: ${fixReportId} projectId: ${projectId}`
26652
26823
  );
26653
26824
  if (isAllFilesScan) {
26654
26825
  return;
@@ -26952,13 +27123,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
26952
27123
  });
26953
27124
  return scannedFiles.some((file) => file.relativePath === fixFile);
26954
27125
  }
26955
- async getFreshFixes({ path: path37 }) {
27126
+ async getFreshFixes({ path: path38 }) {
26956
27127
  const scanContext = ScanContext.USER_REQUEST;
26957
- logDebug(`[${scanContext}] Getting fresh fixes`, { path: path37 });
26958
- if (this.path !== path37) {
26959
- this.path = path37;
27128
+ logDebug(`[${scanContext}] Getting fresh fixes`, { path: path38 });
27129
+ if (this.path !== path38) {
27130
+ this.path = path38;
26960
27131
  this.reset();
26961
- logInfo(`[${scanContext}] Reset service state for new path`, { path: path37 });
27132
+ logInfo(`[${scanContext}] Reset service state for new path`, { path: path38 });
26962
27133
  }
26963
27134
  try {
26964
27135
  const loginContext = createMcpLoginContext("check_new_fixes");
@@ -26977,7 +27148,7 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
26977
27148
  }
26978
27149
  throw error;
26979
27150
  }
26980
- this.triggerScan({ path: path37, gqlClient: this.gqlClient });
27151
+ this.triggerScan({ path: path38, gqlClient: this.gqlClient });
26981
27152
  let isMvsAutoFixEnabled = null;
26982
27153
  try {
26983
27154
  isMvsAutoFixEnabled = await this.gqlClient.getMvsAutoFixSettings();
@@ -27011,33 +27182,33 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
27011
27182
  return noFreshFixesPrompt;
27012
27183
  }
27013
27184
  triggerScan({
27014
- path: path37,
27185
+ path: path38,
27015
27186
  gqlClient
27016
27187
  }) {
27017
- if (this.path !== path37) {
27018
- this.path = path37;
27188
+ if (this.path !== path38) {
27189
+ this.path = path38;
27019
27190
  this.reset();
27020
- logInfo(`Reset service state for new path in triggerScan`, { path: path37 });
27191
+ logInfo(`Reset service state for new path in triggerScan`, { path: path38 });
27021
27192
  }
27022
27193
  this.gqlClient = gqlClient;
27023
27194
  if (!this.intervalId) {
27024
- this.startPeriodicScanning(path37);
27025
- this.executeInitialScan(path37);
27026
- void this.executeInitialFullScan(path37);
27195
+ this.startPeriodicScanning(path38);
27196
+ this.executeInitialScan(path38);
27197
+ void this.executeInitialFullScan(path38);
27027
27198
  }
27028
27199
  }
27029
- startPeriodicScanning(path37) {
27200
+ startPeriodicScanning(path38) {
27030
27201
  const scanContext = ScanContext.BACKGROUND_PERIODIC;
27031
27202
  logDebug(
27032
27203
  `[${scanContext}] Starting periodic scan for new security vulnerabilities`,
27033
27204
  {
27034
- path: path37
27205
+ path: path38
27035
27206
  }
27036
27207
  );
27037
27208
  this.intervalId = setInterval(() => {
27038
- logDebug(`[${scanContext}] Triggering periodic security scan`, { path: path37 });
27209
+ logDebug(`[${scanContext}] Triggering periodic security scan`, { path: path38 });
27039
27210
  this.scanForSecurityVulnerabilities({
27040
- path: path37,
27211
+ path: path38,
27041
27212
  scanContext
27042
27213
  }).catch((error) => {
27043
27214
  logError(`[${scanContext}] Error during periodic security scan`, {
@@ -27046,45 +27217,45 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
27046
27217
  });
27047
27218
  }, MCP_PERIODIC_CHECK_INTERVAL);
27048
27219
  }
27049
- async executeInitialFullScan(path37) {
27220
+ async executeInitialFullScan(path38) {
27050
27221
  const scanContext = ScanContext.FULL_SCAN;
27051
- logDebug(`[${scanContext}] Triggering initial full security scan`, { path: path37 });
27222
+ logDebug(`[${scanContext}] Triggering initial full security scan`, { path: path38 });
27052
27223
  logDebug(`[${scanContext}] Full scan paths scanned`, {
27053
27224
  fullScanPathsScanned: this.fullScanPathsScanned
27054
27225
  });
27055
- if (this.fullScanPathsScanned.includes(path37)) {
27226
+ if (this.fullScanPathsScanned.includes(path38)) {
27056
27227
  logDebug(`[${scanContext}] Full scan already executed for this path`, {
27057
- path: path37
27228
+ path: path38
27058
27229
  });
27059
27230
  return;
27060
27231
  }
27061
27232
  configStore.set("fullScanPathsScanned", [
27062
27233
  ...this.fullScanPathsScanned,
27063
- path37
27234
+ path38
27064
27235
  ]);
27065
27236
  try {
27066
27237
  await this.scanForSecurityVulnerabilities({
27067
- path: path37,
27238
+ path: path38,
27068
27239
  isAllFilesScan: true,
27069
27240
  isAllDetectionRulesScan: true,
27070
27241
  scanContext: ScanContext.FULL_SCAN
27071
27242
  });
27072
- if (!this.fullScanPathsScanned.includes(path37)) {
27073
- this.fullScanPathsScanned.push(path37);
27243
+ if (!this.fullScanPathsScanned.includes(path38)) {
27244
+ this.fullScanPathsScanned.push(path38);
27074
27245
  configStore.set("fullScanPathsScanned", this.fullScanPathsScanned);
27075
27246
  }
27076
- logInfo(`[${scanContext}] Full scan completed`, { path: path37 });
27247
+ logInfo(`[${scanContext}] Full scan completed`, { path: path38 });
27077
27248
  } catch (error) {
27078
27249
  logError(`[${scanContext}] Error during initial full security scan`, {
27079
27250
  error
27080
27251
  });
27081
27252
  }
27082
27253
  }
27083
- executeInitialScan(path37) {
27254
+ executeInitialScan(path38) {
27084
27255
  const scanContext = ScanContext.BACKGROUND_INITIAL;
27085
- logDebug(`[${scanContext}] Triggering initial security scan`, { path: path37 });
27256
+ logDebug(`[${scanContext}] Triggering initial security scan`, { path: path38 });
27086
27257
  this.scanForSecurityVulnerabilities({
27087
- path: path37,
27258
+ path: path38,
27088
27259
  scanContext: ScanContext.BACKGROUND_INITIAL
27089
27260
  }).catch((error) => {
27090
27261
  logError(`[${scanContext}] Error during initial security scan`, { error });
@@ -27185,9 +27356,9 @@ Example payload:
27185
27356
  `Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
27186
27357
  );
27187
27358
  }
27188
- const path37 = pathValidationResult.path;
27359
+ const path38 = pathValidationResult.path;
27189
27360
  const resultText = await this.newFixesService.getFreshFixes({
27190
- path: path37
27361
+ path: path38
27191
27362
  });
27192
27363
  logInfo("CheckForNewAvailableFixesTool execution completed", {
27193
27364
  resultText
@@ -27368,8 +27539,8 @@ Call this tool instead of ${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES} when you only
27368
27539
  `Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
27369
27540
  );
27370
27541
  }
27371
- const path37 = pathValidationResult.path;
27372
- const gitService = new GitService(path37, log);
27542
+ const path38 = pathValidationResult.path;
27543
+ const gitService = new GitService(path38, log);
27373
27544
  const gitValidation = await gitService.validateRepository();
27374
27545
  if (!gitValidation.isValid) {
27375
27546
  throw new Error(`Invalid git repository: ${gitValidation.error}`);
@@ -27406,7 +27577,7 @@ Call this tool instead of ${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES} when you only
27406
27577
  }
27407
27578
  const fixResult = await this.availableFixesService.checkForAvailableFixes({
27408
27579
  repoUrl: originUrl,
27409
- repositoryPath: path37,
27580
+ repositoryPath: path38,
27410
27581
  limit: args.limit,
27411
27582
  offset: args.offset,
27412
27583
  fileFilter: actualFileFilter
@@ -27991,7 +28162,7 @@ Example payload (Mode B \u2014 abstain from every interactive fix, no rescan):
27991
28162
  `Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
27992
28163
  );
27993
28164
  }
27994
- const path37 = pathValidationResult.path;
28165
+ const path38 = pathValidationResult.path;
27995
28166
  if (args.interactiveAnswers !== void 0) {
27996
28167
  if (args.interactiveAnswers.length === 0) {
27997
28168
  return this.createSuccessResponse(
@@ -28001,7 +28172,7 @@ Example payload (Mode B \u2014 abstain from every interactive fix, no rescan):
28001
28172
  try {
28002
28173
  const result = await this.vulnerabilityFixService.applyInteractiveAnswers({
28003
28174
  interactiveAnswers: args.interactiveAnswers,
28004
- repositoryPath: path37
28175
+ repositoryPath: path38
28005
28176
  });
28006
28177
  return this.createSuccessResponse(result);
28007
28178
  } catch (error) {
@@ -28013,7 +28184,7 @@ Example payload (Mode B \u2014 abstain from every interactive fix, no rescan):
28013
28184
  }
28014
28185
  }
28015
28186
  const files = await getLocalFiles({
28016
- path: path37,
28187
+ path: path38,
28017
28188
  maxFileSize: MCP_MAX_FILE_SIZE,
28018
28189
  maxFiles: args.maxFiles,
28019
28190
  scanContext: ScanContext.USER_REQUEST,
@@ -28033,7 +28204,7 @@ Example payload (Mode B \u2014 abstain from every interactive fix, no rescan):
28033
28204
  try {
28034
28205
  const fixResult = await this.vulnerabilityFixService.processVulnerabilities({
28035
28206
  fileList: files.map((file) => file.relativePath),
28036
- repositoryPath: path37,
28207
+ repositoryPath: path38,
28037
28208
  offset: args.offset,
28038
28209
  limit: args.limit,
28039
28210
  isRescan: args.rescan || !!args.maxFiles
@@ -28137,7 +28308,7 @@ var mcpHandler = async (_args) => {
28137
28308
  };
28138
28309
 
28139
28310
  // src/args/commands/review.ts
28140
- import fs26 from "fs";
28311
+ import fs27 from "fs";
28141
28312
  import chalk12 from "chalk";
28142
28313
  function reviewBuilder(yargs2) {
28143
28314
  return yargs2.option("f", {
@@ -28174,7 +28345,7 @@ function reviewBuilder(yargs2) {
28174
28345
  ).help();
28175
28346
  }
28176
28347
  function validateReviewOptions(argv) {
28177
- if (!fs26.existsSync(argv.f)) {
28348
+ if (!fs27.existsSync(argv.f)) {
28178
28349
  throw new CliError(`
28179
28350
  Can't access ${chalk12.bold(argv.f)}`);
28180
28351
  }
@@ -28334,10 +28505,10 @@ init_client_generates();
28334
28505
  init_urlParser2();
28335
28506
 
28336
28507
  // src/features/codeium_intellij/codeium_language_server_grpc_client.ts
28337
- import path34 from "path";
28508
+ import path35 from "path";
28338
28509
  import * as grpc from "@grpc/grpc-js";
28339
28510
  import * as protoLoader from "@grpc/proto-loader";
28340
- var PROTO_PATH = path34.join(
28511
+ var PROTO_PATH = path35.join(
28341
28512
  getModuleRootDir(),
28342
28513
  "src/features/codeium_intellij/proto/exa/language_server_pb/language_server.proto"
28343
28514
  );
@@ -28349,7 +28520,7 @@ function loadProto() {
28349
28520
  defaults: true,
28350
28521
  oneofs: true,
28351
28522
  includeDirs: [
28352
- path34.join(getModuleRootDir(), "src/features/codeium_intellij/proto")
28523
+ path35.join(getModuleRootDir(), "src/features/codeium_intellij/proto")
28353
28524
  ]
28354
28525
  });
28355
28526
  return grpc.loadPackageDefinition(
@@ -28403,30 +28574,30 @@ async function getGrpcClient(port, csrf) {
28403
28574
  }
28404
28575
 
28405
28576
  // src/features/codeium_intellij/parse_intellij_logs.ts
28406
- import fs27 from "fs";
28407
- import os17 from "os";
28408
- import path35 from "path";
28577
+ import fs28 from "fs";
28578
+ import os18 from "os";
28579
+ import path36 from "path";
28409
28580
  function getLogsDir() {
28410
28581
  if (process.platform === "darwin") {
28411
- return path35.join(os17.homedir(), "Library/Logs/JetBrains");
28582
+ return path36.join(os18.homedir(), "Library/Logs/JetBrains");
28412
28583
  } else if (process.platform === "win32") {
28413
- return path35.join(
28414
- process.env["LOCALAPPDATA"] || path35.join(os17.homedir(), "AppData/Local"),
28584
+ return path36.join(
28585
+ process.env["LOCALAPPDATA"] || path36.join(os18.homedir(), "AppData/Local"),
28415
28586
  "JetBrains"
28416
28587
  );
28417
28588
  } else {
28418
- return path35.join(os17.homedir(), ".cache/JetBrains");
28589
+ return path36.join(os18.homedir(), ".cache/JetBrains");
28419
28590
  }
28420
28591
  }
28421
28592
  function parseIdeLogDir(ideLogDir) {
28422
- const logFiles = fs27.readdirSync(ideLogDir).filter((f) => /^idea(\.\d+)?\.log$/.test(f)).map((f) => ({
28593
+ const logFiles = fs28.readdirSync(ideLogDir).filter((f) => /^idea(\.\d+)?\.log$/.test(f)).map((f) => ({
28423
28594
  name: f,
28424
- mtime: fs27.statSync(path35.join(ideLogDir, f)).mtimeMs
28595
+ mtime: fs28.statSync(path36.join(ideLogDir, f)).mtimeMs
28425
28596
  })).sort((a, b) => a.mtime - b.mtime).map((f) => f.name);
28426
28597
  let latestCsrf = null;
28427
28598
  let latestPort = null;
28428
28599
  for (const logFile of logFiles) {
28429
- const lines = fs27.readFileSync(path35.join(ideLogDir, logFile), "utf-8").split("\n");
28600
+ const lines = fs28.readFileSync(path36.join(ideLogDir, logFile), "utf-8").split("\n");
28430
28601
  for (const line of lines) {
28431
28602
  if (!line.includes(
28432
28603
  "com.codeium.intellij.language_server.LanguageServerProcessHandler"
@@ -28452,13 +28623,13 @@ function parseIdeLogDir(ideLogDir) {
28452
28623
  function findRunningCodeiumLanguageServers() {
28453
28624
  const results = [];
28454
28625
  const logsDir = getLogsDir();
28455
- if (!fs27.existsSync(logsDir)) return results;
28456
- for (const ide of fs27.readdirSync(logsDir)) {
28457
- let ideLogDir = path35.join(logsDir, ide);
28626
+ if (!fs28.existsSync(logsDir)) return results;
28627
+ for (const ide of fs28.readdirSync(logsDir)) {
28628
+ let ideLogDir = path36.join(logsDir, ide);
28458
28629
  if (process.platform !== "darwin") {
28459
- ideLogDir = path35.join(ideLogDir, "log");
28630
+ ideLogDir = path36.join(ideLogDir, "log");
28460
28631
  }
28461
- if (!fs27.existsSync(ideLogDir) || !fs27.statSync(ideLogDir).isDirectory()) {
28632
+ if (!fs28.existsSync(ideLogDir) || !fs28.statSync(ideLogDir).isDirectory()) {
28462
28633
  continue;
28463
28634
  }
28464
28635
  const result = parseIdeLogDir(ideLogDir);
@@ -28638,11 +28809,11 @@ function processChatStepCodeAction(step) {
28638
28809
 
28639
28810
  // src/features/codeium_intellij/install_hook.ts
28640
28811
  import fsPromises5 from "fs/promises";
28641
- import os18 from "os";
28642
- import path36 from "path";
28812
+ import os19 from "os";
28813
+ import path37 from "path";
28643
28814
  import chalk14 from "chalk";
28644
28815
  function getCodeiumHooksPath() {
28645
- return path36.join(os18.homedir(), ".codeium", "hooks.json");
28816
+ return path37.join(os19.homedir(), ".codeium", "hooks.json");
28646
28817
  }
28647
28818
  async function readCodeiumHooks() {
28648
28819
  const hooksPath = getCodeiumHooksPath();
@@ -28655,7 +28826,7 @@ async function readCodeiumHooks() {
28655
28826
  }
28656
28827
  async function writeCodeiumHooks(config2) {
28657
28828
  const hooksPath = getCodeiumHooksPath();
28658
- const dir = path36.dirname(hooksPath);
28829
+ const dir = path37.dirname(hooksPath);
28659
28830
  await fsPromises5.mkdir(dir, { recursive: true });
28660
28831
  await fsPromises5.writeFile(
28661
28832
  hooksPath,