mobbdev 1.0.178 → 1.0.180

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.
Files changed (2) hide show
  1. package/dist/index.mjs +432 -101
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -2276,6 +2276,39 @@ var UploadS3BucketInfoDocument = `
2276
2276
  }
2277
2277
  }
2278
2278
  `;
2279
+ var UploadAiBlameInferencesInitDocument = `
2280
+ mutation UploadAIBlameInferencesInit($sessions: [AIBlameInferenceInitInput!]!) {
2281
+ uploadAIBlameInferencesInit(sessions: $sessions) {
2282
+ status
2283
+ error
2284
+ uploadSessions {
2285
+ aiBlameInferenceId
2286
+ prompt {
2287
+ url
2288
+ artifactId
2289
+ fileName
2290
+ uploadFieldsJSON
2291
+ uploadKey
2292
+ }
2293
+ inference {
2294
+ url
2295
+ artifactId
2296
+ fileName
2297
+ uploadFieldsJSON
2298
+ uploadKey
2299
+ }
2300
+ }
2301
+ }
2302
+ }
2303
+ `;
2304
+ var FinalizeAiBlameInferencesUploadDocument = `
2305
+ mutation FinalizeAIBlameInferencesUpload($sessions: [AIBlameInferenceFinalizeInput!]!) {
2306
+ finalizeAIBlameInferencesUpload(sessions: $sessions) {
2307
+ status
2308
+ error
2309
+ }
2310
+ }
2311
+ `;
2279
2312
  var DigestVulnerabilityReportDocument = `
2280
2313
  mutation DigestVulnerabilityReport($vulnerabilityReportFileName: String, $fixReportId: String!, $projectId: String!, $scanSource: String!, $repoUrl: String, $reference: String, $sha: String) {
2281
2314
  digestVulnerabilityReport(
@@ -2533,6 +2566,12 @@ function getSdk(client, withWrapper = defaultWrapper) {
2533
2566
  uploadS3BucketInfo(variables, requestHeaders, signal) {
2534
2567
  return withWrapper((wrappedRequestHeaders) => client.request({ document: UploadS3BucketInfoDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "uploadS3BucketInfo", "mutation", variables);
2535
2568
  },
2569
+ UploadAIBlameInferencesInit(variables, requestHeaders, signal) {
2570
+ return withWrapper((wrappedRequestHeaders) => client.request({ document: UploadAiBlameInferencesInitDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "UploadAIBlameInferencesInit", "mutation", variables);
2571
+ },
2572
+ FinalizeAIBlameInferencesUpload(variables, requestHeaders, signal) {
2573
+ return withWrapper((wrappedRequestHeaders) => client.request({ document: FinalizeAiBlameInferencesUploadDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "FinalizeAIBlameInferencesUpload", "mutation", variables);
2574
+ },
2536
2575
  DigestVulnerabilityReport(variables, requestHeaders, signal) {
2537
2576
  return withWrapper((wrappedRequestHeaders) => client.request({ document: DigestVulnerabilityReportDocument, variables, requestHeaders: { ...requestHeaders, ...wrappedRequestHeaders }, signal }), "DigestVulnerabilityReport", "mutation", variables);
2538
2577
  },
@@ -6375,7 +6414,7 @@ async function getAdoSdk(params) {
6375
6414
  const url = new URL(repoUrl);
6376
6415
  const origin2 = url.origin.toLowerCase().endsWith(".visualstudio.com") ? DEFUALT_ADO_ORIGIN : url.origin.toLowerCase();
6377
6416
  const params2 = `path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=commit&versionDescriptor[version]=${branch}&resolveLfs=true&$format=zip&api-version=5.0&download=true`;
6378
- const path16 = [
6417
+ const path17 = [
6379
6418
  prefixPath,
6380
6419
  owner,
6381
6420
  projectName,
@@ -6386,7 +6425,7 @@ async function getAdoSdk(params) {
6386
6425
  "items",
6387
6426
  "items"
6388
6427
  ].filter(Boolean).join("/");
6389
- return new URL(`${path16}?${params2}`, origin2).toString();
6428
+ return new URL(`${path17}?${params2}`, origin2).toString();
6390
6429
  },
6391
6430
  async getAdoBranchList({ repoUrl }) {
6392
6431
  try {
@@ -6877,6 +6916,9 @@ var AdoSCMLib = class extends SCMLib {
6877
6916
  markdownComment: comment
6878
6917
  });
6879
6918
  }
6919
+ async getCommitDiff(_commitSha) {
6920
+ throw new Error("getCommitDiff not implemented for ADO");
6921
+ }
6880
6922
  };
6881
6923
 
6882
6924
  // src/features/analysis/scm/bitbucket/bitbucket.ts
@@ -7440,6 +7482,9 @@ var BitbucketSCMLib = class extends SCMLib {
7440
7482
  markdownComment: comment
7441
7483
  });
7442
7484
  }
7485
+ async getCommitDiff(_commitSha) {
7486
+ throw new Error("getCommitDiff not implemented for Bitbucket");
7487
+ }
7443
7488
  };
7444
7489
 
7445
7490
  // src/features/analysis/scm/constants.ts
@@ -7808,6 +7853,33 @@ function getGithubSdk(params = {}) {
7808
7853
  commit_sha: commitSha
7809
7854
  });
7810
7855
  },
7856
+ async getCommitWithDiff({
7857
+ commitSha,
7858
+ owner,
7859
+ repo
7860
+ }) {
7861
+ const [commitData, diffData] = await Promise.all([
7862
+ // Get commit metadata
7863
+ octokit.rest.repos.getCommit({
7864
+ repo,
7865
+ owner,
7866
+ ref: commitSha
7867
+ }),
7868
+ // Get commit diff
7869
+ octokit.request("GET /repos/{owner}/{repo}/commits/{ref}", {
7870
+ owner,
7871
+ repo,
7872
+ ref: commitSha,
7873
+ headers: {
7874
+ Accept: "application/vnd.github.v3.diff"
7875
+ }
7876
+ })
7877
+ ]);
7878
+ return {
7879
+ commit: commitData.data,
7880
+ diff: diffData.data
7881
+ };
7882
+ },
7811
7883
  async getTagDate({
7812
7884
  tag,
7813
7885
  owner,
@@ -7841,14 +7913,14 @@ function getGithubSdk(params = {}) {
7841
7913
  };
7842
7914
  },
7843
7915
  async getGithubBlameRanges(params2) {
7844
- const { ref, gitHubUrl, path: path16 } = params2;
7916
+ const { ref, gitHubUrl, path: path17 } = params2;
7845
7917
  const { owner, repo } = parseGithubOwnerAndRepo(gitHubUrl);
7846
7918
  const res = await octokit.graphql(
7847
7919
  GET_BLAME_DOCUMENT,
7848
7920
  {
7849
7921
  owner,
7850
7922
  repo,
7851
- path: path16,
7923
+ path: path17,
7852
7924
  ref
7853
7925
  }
7854
7926
  );
@@ -8155,11 +8227,11 @@ var GithubSCMLib = class extends SCMLib {
8155
8227
  markdownComment: comment
8156
8228
  });
8157
8229
  }
8158
- async getRepoBlameRanges(ref, path16) {
8230
+ async getRepoBlameRanges(ref, path17) {
8159
8231
  this._validateUrl();
8160
8232
  return await this.githubSdk.getGithubBlameRanges({
8161
8233
  ref,
8162
- path: path16,
8234
+ path: path17,
8163
8235
  gitHubUrl: this.url
8164
8236
  });
8165
8237
  }
@@ -8243,6 +8315,24 @@ var GithubSCMLib = class extends SCMLib {
8243
8315
  comment_id: commentId
8244
8316
  });
8245
8317
  }
8318
+ async getCommitDiff(commitSha) {
8319
+ this._validateAccessTokenAndUrl();
8320
+ const { owner, repo } = parseGithubOwnerAndRepo(this.url);
8321
+ const { commit, diff } = await this.githubSdk.getCommitWithDiff({
8322
+ owner,
8323
+ repo,
8324
+ commitSha
8325
+ });
8326
+ const commitTimestamp = commit.commit.committer?.date ? new Date(commit.commit.committer.date) : new Date(commit.commit.author?.date || Date.now());
8327
+ return {
8328
+ diff,
8329
+ commitTimestamp,
8330
+ commitSha: commit.sha,
8331
+ authorName: commit.commit.author?.name,
8332
+ authorEmail: commit.commit.author?.email,
8333
+ message: commit.commit.message
8334
+ };
8335
+ }
8246
8336
  };
8247
8337
 
8248
8338
  // src/features/analysis/scm/gitlab/gitlab.ts
@@ -8573,13 +8663,13 @@ function parseGitlabOwnerAndRepo(gitlabUrl) {
8573
8663
  const { organization, repoName, projectPath } = parsingResult;
8574
8664
  return { owner: organization, repo: repoName, projectPath };
8575
8665
  }
8576
- async function getGitlabBlameRanges({ ref, gitlabUrl, path: path16 }, options) {
8666
+ async function getGitlabBlameRanges({ ref, gitlabUrl, path: path17 }, options) {
8577
8667
  const { projectPath } = parseGitlabOwnerAndRepo(gitlabUrl);
8578
8668
  const api2 = getGitBeaker({
8579
8669
  url: gitlabUrl,
8580
8670
  gitlabAuthToken: options?.gitlabAuthToken
8581
8671
  });
8582
- const resp = await api2.RepositoryFiles.allFileBlames(projectPath, path16, ref);
8672
+ const resp = await api2.RepositoryFiles.allFileBlames(projectPath, path17, ref);
8583
8673
  let lineNumber = 1;
8584
8674
  return resp.filter((range) => range.lines).map((range) => {
8585
8675
  const oldLineNumber = lineNumber;
@@ -8755,10 +8845,10 @@ var GitlabSCMLib = class extends SCMLib {
8755
8845
  markdownComment: comment
8756
8846
  });
8757
8847
  }
8758
- async getRepoBlameRanges(ref, path16) {
8848
+ async getRepoBlameRanges(ref, path17) {
8759
8849
  this._validateUrl();
8760
8850
  return await getGitlabBlameRanges(
8761
- { ref, path: path16, gitlabUrl: this.url },
8851
+ { ref, path: path17, gitlabUrl: this.url },
8762
8852
  {
8763
8853
  url: this.url,
8764
8854
  gitlabAuthToken: this.accessToken
@@ -8808,6 +8898,9 @@ var GitlabSCMLib = class extends SCMLib {
8808
8898
  this._validateAccessTokenAndUrl();
8809
8899
  return `${this.url}/-/commits/${branchName}`;
8810
8900
  }
8901
+ async getCommitDiff(_commitSha) {
8902
+ throw new Error("getCommitDiff not implemented for GitLab");
8903
+ }
8811
8904
  };
8812
8905
 
8813
8906
  // src/features/analysis/scm/scmFactory.ts
@@ -8904,6 +8997,17 @@ var StubSCMLib = class extends SCMLib {
8904
8997
  async addCommentToSubmitRequest(_submitRequestId, _comment) {
8905
8998
  console.warn("addCommentToSubmitRequest() no-op");
8906
8999
  }
9000
+ async getCommitDiff(_commitSha) {
9001
+ console.warn("getCommitDiff() returning stub diff");
9002
+ return {
9003
+ diff: "",
9004
+ commitTimestamp: /* @__PURE__ */ new Date(),
9005
+ commitSha: _commitSha,
9006
+ authorName: void 0,
9007
+ authorEmail: void 0,
9008
+ message: void 0
9009
+ };
9010
+ }
8907
9011
  };
8908
9012
 
8909
9013
  // src/features/analysis/scm/scmFactory.ts
@@ -9456,7 +9560,8 @@ var mobbCliCommand = {
9456
9560
  analyze: "analyze",
9457
9561
  review: "review",
9458
9562
  convertToSarif: "convert-to-sarif",
9459
- mcp: "mcp"
9563
+ mcp: "mcp",
9564
+ uploadAiBlame: "upload-ai-blame"
9460
9565
  };
9461
9566
  var ScanContext = {
9462
9567
  FULL_SCAN: "FULL_SCAN",
@@ -9467,7 +9572,7 @@ var ScanContext = {
9467
9572
  };
9468
9573
 
9469
9574
  // src/args/yargs.ts
9470
- import chalk10 from "chalk";
9575
+ import chalk11 from "chalk";
9471
9576
  import yargs from "yargs/yargs";
9472
9577
 
9473
9578
  // src/args/commands/analyze.ts
@@ -9836,7 +9941,7 @@ async function postIssueComment(params) {
9836
9941
  fpDescription
9837
9942
  } = params;
9838
9943
  const {
9839
- path: path16,
9944
+ path: path17,
9840
9945
  startLine,
9841
9946
  vulnerabilityReportIssue: {
9842
9947
  vulnerabilityReportIssueTags,
@@ -9851,7 +9956,7 @@ async function postIssueComment(params) {
9851
9956
  Refresh the page in order to see the changes.`,
9852
9957
  pull_number: pullRequest,
9853
9958
  commit_id: commitSha,
9854
- path: path16,
9959
+ path: path17,
9855
9960
  line: startLine
9856
9961
  });
9857
9962
  const commentId = commentRes.data.id;
@@ -9885,7 +9990,7 @@ async function postFixComment(params) {
9885
9990
  scanner
9886
9991
  } = params;
9887
9992
  const {
9888
- path: path16,
9993
+ path: path17,
9889
9994
  startLine,
9890
9995
  vulnerabilityReportIssue: { fixId, vulnerabilityReportIssueTags, category },
9891
9996
  vulnerabilityReportIssueId
@@ -9903,7 +10008,7 @@ async function postFixComment(params) {
9903
10008
  Refresh the page in order to see the changes.`,
9904
10009
  pull_number: pullRequest,
9905
10010
  commit_id: commitSha,
9906
- path: path16,
10011
+ path: path17,
9907
10012
  line: startLine
9908
10013
  });
9909
10014
  const commentId = commentRes.data.id;
@@ -12559,6 +12664,12 @@ var McpGQLClient = class {
12559
12664
  }
12560
12665
  };
12561
12666
  }
12667
+ async uploadAIBlameInferencesInitRaw(variables) {
12668
+ return await this.clientSdk.UploadAIBlameInferencesInit(variables);
12669
+ }
12670
+ async finalizeAIBlameInferencesUploadRaw(variables) {
12671
+ return await this.clientSdk.FinalizeAIBlameInferencesUpload(variables);
12672
+ }
12562
12673
  async isApiEndpointReachable() {
12563
12674
  try {
12564
12675
  logDebug("[GraphQL] Calling Me query for API connection verification");
@@ -13095,7 +13206,7 @@ var McpGQLClient = class {
13095
13206
  }
13096
13207
  };
13097
13208
  async function createAuthenticatedMcpGQLClient({
13098
- isBackgoundCall = false
13209
+ isBackgroundCall = false
13099
13210
  } = {}) {
13100
13211
  logDebug("[GraphQL] Getting config", {
13101
13212
  apiToken: configStore.get("apiToken")
@@ -13116,18 +13227,18 @@ async function createAuthenticatedMcpGQLClient({
13116
13227
  return initialClient;
13117
13228
  }
13118
13229
  const authService = new McpAuthService(initialClient);
13119
- const newApiToken = await authService.authenticate(isBackgoundCall);
13230
+ const newApiToken = await authService.authenticate(isBackgroundCall);
13120
13231
  configStore.set("apiToken", newApiToken);
13121
13232
  return new McpGQLClient({ apiKey: newApiToken, type: "apiKey" });
13122
13233
  }
13123
13234
 
13124
- // src/mcp/services/McpUsageService.ts
13235
+ // src/mcp/services/McpUsageService/McpUsageService.ts
13125
13236
  init_configs();
13126
13237
  import fetch5 from "node-fetch";
13127
13238
  import os4 from "os";
13128
13239
  import { v4 as uuidv43, v5 as uuidv5 } from "uuid";
13129
13240
 
13130
- // src/mcp/core/host.ts
13241
+ // src/mcp/services/McpUsageService/host.ts
13131
13242
  import { execSync } from "child_process";
13132
13243
  import fs10 from "fs";
13133
13244
  import os3 from "os";
@@ -13242,7 +13353,7 @@ var getProcessInfo = (pid) => {
13242
13353
  const cmd = parts.slice(2).join(" ");
13243
13354
  return { pid: pidStr ?? "", ppid: ppid ?? "", cmd };
13244
13355
  } else {
13245
- logWarn(`Unsupported platform: ${platform}`);
13356
+ logWarn(`[UsageService] Unsupported platform: ${platform}`);
13246
13357
  return null;
13247
13358
  }
13248
13359
  } catch {
@@ -13350,7 +13461,7 @@ var getHostInfo = () => {
13350
13461
  return { mcps: results, user: gitInfo };
13351
13462
  };
13352
13463
 
13353
- // src/mcp/services/McpUsageService.ts
13464
+ // src/mcp/services/McpUsageService/McpUsageService.ts
13354
13465
  var McpUsageService = class {
13355
13466
  constructor() {
13356
13467
  __publicField(this, "configKey", "mcpUsage");
@@ -13364,10 +13475,9 @@ var McpUsageService = class {
13364
13475
  }
13365
13476
  }
13366
13477
  startPeriodicTracking() {
13367
- const scanContext = ScanContext.BACKGROUND_PERIODIC;
13368
- logDebug(`[${scanContext}] Starting periodic tracking for mcps`, {});
13478
+ logDebug(`[UsageService] Starting periodic tracking for mcps`, {});
13369
13479
  this.intervalId = setInterval(async () => {
13370
- logDebug(`[${scanContext}] Triggering periodic security scan`, {
13480
+ logDebug(`[UsageService] Triggering periodic usage service`, {
13371
13481
  MCP_PERIODIC_TRACK_INTERVAL
13372
13482
  });
13373
13483
  await mcpUsageService.trackServerStart();
@@ -13386,13 +13496,13 @@ var McpUsageService = class {
13386
13496
  }
13387
13497
  const macString = macs.length ? macs.sort().join(",") : `${os4.hostname()}-${uuidv43()}`;
13388
13498
  const hostId = uuidv5(macString, uuidv5.DNS);
13389
- logDebug("Generated new host ID", { hostId });
13499
+ logDebug("[UsageService] Generated new host ID", { hostId });
13390
13500
  return hostId;
13391
13501
  }
13392
13502
  getOrganizationId() {
13393
13503
  const organizationId = configStore.get("GOV-ORG-ID") || "";
13394
13504
  if (organizationId) {
13395
- logDebug("Using stored organization ID", {
13505
+ logDebug("[UsageService] Using stored organization ID", {
13396
13506
  organizationId
13397
13507
  });
13398
13508
  return organizationId;
@@ -13419,7 +13529,9 @@ var McpUsageService = class {
13419
13529
  const hostId = this.generateHostId();
13420
13530
  const organizationId = this.getOrganizationId();
13421
13531
  if (!organizationId) {
13422
- logError("Cannot track MCP usage - organization ID not available");
13532
+ logError(
13533
+ "[UsageService] Cannot track MCP usage - organization ID not available"
13534
+ );
13423
13535
  return;
13424
13536
  }
13425
13537
  const usageData = this.createUsageData(hostId, organizationId, status);
@@ -13428,10 +13540,12 @@ var McpUsageService = class {
13428
13540
  (key) => usageData[key] !== stored[key]
13429
13541
  );
13430
13542
  if (!hasChanges) {
13431
- logDebug(`Skipping ${status} usage tracking - no changes`);
13543
+ logDebug(
13544
+ `[UsageService] Skipping ${status} usage tracking - no changes`
13545
+ );
13432
13546
  return;
13433
13547
  }
13434
- logDebug("Before", { usageData });
13548
+ logDebug("[UsageService] Before", { usageData });
13435
13549
  try {
13436
13550
  const res = await fetch5(this.REST_API_URL, {
13437
13551
  method: "POST",
@@ -13448,19 +13562,19 @@ var McpUsageService = class {
13448
13562
  })
13449
13563
  });
13450
13564
  const authResult = await res.json();
13451
- logDebug("Success usage data", { authResult });
13565
+ logDebug("[UsageService] Success usage data", { authResult });
13452
13566
  } catch (err) {
13453
- logDebug("Error usage data", { err });
13567
+ logDebug("[UsageService] Error usage data", { err });
13454
13568
  }
13455
- logDebug("Saving usage data", { usageData });
13569
+ logDebug("[UsageService] Saving usage data", { usageData });
13456
13570
  configStore.set(this.configKey, usageData);
13457
13571
  logInfo(
13458
- `MCP server ${status === "ACTIVE" ? "start" : "stop"} tracked successfully`
13572
+ `[UsageService] MCP server ${status === "ACTIVE" ? "start" : "stop"} tracked successfully`
13459
13573
  );
13460
13574
  } catch (error) {
13461
13575
  configStore.set(this.configKey, { status: "FAILED" });
13462
13576
  logError(
13463
- `Failed to track MCP server ${status === "ACTIVE" ? "start" : "stop"}`,
13577
+ `[UsageService] Failed to track MCP server ${status === "ACTIVE" ? "start" : "stop"}`,
13464
13578
  { error }
13465
13579
  );
13466
13580
  }
@@ -13530,6 +13644,9 @@ var McpServer = class {
13530
13644
  __publicField(this, "toolRegistry");
13531
13645
  __publicField(this, "isEventHandlersSetup", false);
13532
13646
  __publicField(this, "eventHandlers", /* @__PURE__ */ new Map());
13647
+ __publicField(this, "parentProcessCheckInterval");
13648
+ __publicField(this, "parentPid");
13649
+ this.parentPid = process.ppid;
13533
13650
  this.server = new Server(
13534
13651
  {
13535
13652
  name: config4.name,
@@ -13544,8 +13661,12 @@ var McpServer = class {
13544
13661
  this.toolRegistry = new ToolRegistry();
13545
13662
  this.setupHandlers();
13546
13663
  this.setupProcessEventHandlers();
13664
+ this.setupParentProcessMonitoring();
13547
13665
  logInfo("MCP server instance created");
13548
- logDebug("MCP server instance config", { config: config4 });
13666
+ logDebug("MCP server instance config", {
13667
+ config: config4,
13668
+ parentPid: this.parentPid
13669
+ });
13549
13670
  }
13550
13671
  async trackServerUsage(action, signalOrError) {
13551
13672
  try {
@@ -13570,6 +13691,12 @@ var McpServer = class {
13570
13691
  const messages = {
13571
13692
  SIGINT: "MCP server interrupted",
13572
13693
  SIGTERM: "MCP server terminated",
13694
+ SIGHUP: "MCP server hangup signal received",
13695
+ SIGQUIT: "MCP server quit signal received",
13696
+ SIGABRT: "MCP server abort signal received",
13697
+ SIGPIPE: "MCP server broken pipe signal received",
13698
+ SIGCHLD: "MCP server child process signal received",
13699
+ SIGTSTP: "MCP server terminal stop signal received",
13573
13700
  exit: "MCP server exiting",
13574
13701
  uncaughtException: "Uncaught exception in MCP server",
13575
13702
  unhandledRejection: "Unhandled promise rejection in MCP server",
@@ -13600,7 +13727,10 @@ var McpServer = class {
13600
13727
  } else {
13601
13728
  logDebug(message, { signal });
13602
13729
  }
13603
- if (signal === "SIGINT" || signal === "SIGTERM") {
13730
+ if (signal === "SIGCHLD") {
13731
+ return;
13732
+ }
13733
+ if (signal === "SIGINT" || signal === "SIGTERM" || signal === "SIGHUP" || signal === "SIGQUIT" || signal === "SIGABRT" || signal === "SIGPIPE" || signal === "SIGTSTP") {
13604
13734
  await this.trackServerUsage("stop", signal);
13605
13735
  process.exit(0);
13606
13736
  }
@@ -13609,6 +13739,62 @@ var McpServer = class {
13609
13739
  process.exit(1);
13610
13740
  }
13611
13741
  }
13742
+ isParentProcessAlive() {
13743
+ try {
13744
+ process.kill(this.parentPid, 0);
13745
+ return true;
13746
+ } catch (error) {
13747
+ return false;
13748
+ }
13749
+ }
13750
+ async handleParentProcessDeath(source) {
13751
+ logInfo(`Parent process death detected via ${source}`, {
13752
+ parentPid: this.parentPid
13753
+ });
13754
+ await this.trackServerUsage("stop", `parent-death-${source}`);
13755
+ process.exit(0);
13756
+ }
13757
+ setupParentProcessMonitoring() {
13758
+ logInfo("Setting up parent process monitoring", {
13759
+ parentPid: this.parentPid
13760
+ });
13761
+ process.stdin.on("close", async () => {
13762
+ logDebug("stdin closed - parent likely terminated");
13763
+ await this.handleParentProcessDeath("stdin-close");
13764
+ });
13765
+ process.stdin.on("end", async () => {
13766
+ logDebug("stdin ended - parent likely terminated");
13767
+ await this.handleParentProcessDeath("stdin-end");
13768
+ });
13769
+ process.stdout.on("error", async (error) => {
13770
+ logWarn("stdout error - parent may have terminated", { error });
13771
+ if (error.message.includes("EPIPE") || error.message.includes("ECONNRESET")) {
13772
+ await this.handleParentProcessDeath("stdout-error");
13773
+ }
13774
+ });
13775
+ process.stderr.on("error", async (error) => {
13776
+ logWarn("stderr error - parent may have terminated", { error });
13777
+ if (error.message.includes("EPIPE") || error.message.includes("ECONNRESET")) {
13778
+ await this.handleParentProcessDeath("stderr-error");
13779
+ }
13780
+ });
13781
+ if (process.send) {
13782
+ process.on("disconnect", async () => {
13783
+ logDebug("IPC disconnected - parent terminated");
13784
+ await this.handleParentProcessDeath("ipc-disconnect");
13785
+ });
13786
+ logDebug("IPC monitoring enabled");
13787
+ } else {
13788
+ logDebug("IPC not available - skipping IPC monitoring");
13789
+ }
13790
+ this.parentProcessCheckInterval = setInterval(async () => {
13791
+ if (!this.isParentProcessAlive()) {
13792
+ logDebug("Parent process not alive during periodic check");
13793
+ await this.handleParentProcessDeath("periodic-check");
13794
+ }
13795
+ }, 1e4);
13796
+ logInfo("Parent process monitoring setup complete");
13797
+ }
13612
13798
  setupProcessEventHandlers() {
13613
13799
  if (this.isEventHandlersSetup) {
13614
13800
  logDebug("Process event handlers already setup, skipping");
@@ -13617,6 +13803,12 @@ var McpServer = class {
13617
13803
  const signals = [
13618
13804
  "SIGINT",
13619
13805
  "SIGTERM",
13806
+ "SIGHUP",
13807
+ "SIGQUIT",
13808
+ "SIGABRT",
13809
+ "SIGPIPE",
13810
+ "SIGCHLD",
13811
+ "SIGTSTP",
13620
13812
  "exit",
13621
13813
  "uncaughtException",
13622
13814
  "unhandledRejection",
@@ -13640,12 +13832,17 @@ var McpServer = class {
13640
13832
  };
13641
13833
  process.once("SIGINT", cleanup);
13642
13834
  process.once("SIGTERM", cleanup);
13835
+ process.once("SIGHUP", cleanup);
13836
+ process.once("SIGQUIT", cleanup);
13837
+ process.once("SIGABRT", cleanup);
13838
+ process.once("SIGPIPE", cleanup);
13839
+ process.once("SIGTSTP", cleanup);
13643
13840
  });
13644
13841
  }
13645
13842
  async triggerScanForNewAvailableFixes() {
13646
13843
  try {
13647
13844
  const gqlClient = await createAuthenticatedMcpGQLClient({
13648
- isBackgoundCall: true
13845
+ isBackgroundCall: true
13649
13846
  });
13650
13847
  const isConnected = await gqlClient.verifyApiConnection();
13651
13848
  if (!isConnected) {
@@ -13770,6 +13967,12 @@ var McpServer = class {
13770
13967
  this.toolRegistry.registerTool(tool);
13771
13968
  logInfo(`Tool registered: ${tool.name}`);
13772
13969
  }
13970
+ getParentProcessId() {
13971
+ return this.parentPid;
13972
+ }
13973
+ checkParentProcessAlive() {
13974
+ return this.isParentProcessAlive();
13975
+ }
13773
13976
  async start() {
13774
13977
  try {
13775
13978
  logInfo("Starting MCP server");
@@ -13788,6 +13991,11 @@ var McpServer = class {
13788
13991
  async stop() {
13789
13992
  logDebug("MCP server shutting down");
13790
13993
  await this.trackServerUsage("stop");
13994
+ if (this.parentProcessCheckInterval) {
13995
+ clearInterval(this.parentProcessCheckInterval);
13996
+ this.parentProcessCheckInterval = void 0;
13997
+ logDebug("Parent process check interval cleared");
13998
+ }
13791
13999
  this.eventHandlers.forEach((handler, signal) => {
13792
14000
  process.removeListener(signal, handler);
13793
14001
  });
@@ -14421,23 +14629,23 @@ init_configs();
14421
14629
  import fs12 from "fs/promises";
14422
14630
  import nodePath from "path";
14423
14631
  var getLocalFiles = async ({
14424
- path: path16,
14632
+ path: path17,
14425
14633
  maxFileSize = MCP_MAX_FILE_SIZE,
14426
14634
  maxFiles,
14427
14635
  isAllFilesScan,
14428
14636
  scanContext
14429
14637
  }) => {
14430
14638
  logDebug(`[${scanContext}] Starting getLocalFiles`, {
14431
- path: path16,
14639
+ path: path17,
14432
14640
  maxFileSize,
14433
14641
  maxFiles,
14434
14642
  isAllFilesScan
14435
14643
  });
14436
14644
  try {
14437
- const resolvedRepoPath = await fs12.realpath(path16);
14645
+ const resolvedRepoPath = await fs12.realpath(path17);
14438
14646
  logDebug(`[${scanContext}] Resolved repository path`, {
14439
14647
  resolvedRepoPath,
14440
- originalPath: path16
14648
+ originalPath: path17
14441
14649
  });
14442
14650
  const gitService = new GitService(resolvedRepoPath, log);
14443
14651
  const gitValidation = await gitService.validateRepository();
@@ -14450,7 +14658,7 @@ var getLocalFiles = async ({
14450
14658
  if (!gitValidation.isValid || isAllFilesScan) {
14451
14659
  try {
14452
14660
  files = await FileUtils.getLastChangedFiles({
14453
- dir: path16,
14661
+ dir: path17,
14454
14662
  maxFileSize,
14455
14663
  maxFiles,
14456
14664
  isAllFilesScan
@@ -14542,7 +14750,7 @@ var getLocalFiles = async ({
14542
14750
  logError(`${scanContext}Unexpected error in getLocalFiles`, {
14543
14751
  error: error instanceof Error ? error.message : String(error),
14544
14752
  stack: error instanceof Error ? error.stack : void 0,
14545
- path: path16
14753
+ path: path17
14546
14754
  });
14547
14755
  throw error;
14548
14756
  }
@@ -16676,14 +16884,14 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
16676
16884
  * since the last scan.
16677
16885
  */
16678
16886
  async scanForSecurityVulnerabilities({
16679
- path: path16,
16887
+ path: path17,
16680
16888
  isAllDetectionRulesScan,
16681
16889
  isAllFilesScan,
16682
16890
  scanContext
16683
16891
  }) {
16684
16892
  this.hasAuthenticationFailed = false;
16685
16893
  logDebug(`[${scanContext}] Scanning for new security vulnerabilities`, {
16686
- path: path16
16894
+ path: path17
16687
16895
  });
16688
16896
  if (!this.gqlClient) {
16689
16897
  logInfo(`[${scanContext}] No GQL client found, skipping scan`);
@@ -16699,10 +16907,10 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
16699
16907
  }
16700
16908
  logDebug(
16701
16909
  `[${scanContext}] Connected to the API, assembling list of files to scan`,
16702
- { path: path16 }
16910
+ { path: path17 }
16703
16911
  );
16704
16912
  const files = await getLocalFiles({
16705
- path: path16,
16913
+ path: path17,
16706
16914
  isAllFilesScan,
16707
16915
  scanContext
16708
16916
  });
@@ -16727,13 +16935,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
16727
16935
  });
16728
16936
  const { fixReportId, projectId } = await scanFiles({
16729
16937
  fileList: filesToScan.map((file) => file.relativePath),
16730
- repositoryPath: path16,
16938
+ repositoryPath: path17,
16731
16939
  gqlClient: this.gqlClient,
16732
16940
  isAllDetectionRulesScan,
16733
16941
  scanContext
16734
16942
  });
16735
16943
  logInfo(
16736
- `[${scanContext}] Security scan completed for ${path16} reportId: ${fixReportId} projectId: ${projectId}`
16944
+ `[${scanContext}] Security scan completed for ${path17} reportId: ${fixReportId} projectId: ${projectId}`
16737
16945
  );
16738
16946
  if (isAllFilesScan) {
16739
16947
  return;
@@ -17027,13 +17235,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
17027
17235
  });
17028
17236
  return scannedFiles.some((file) => file.relativePath === fixFile);
17029
17237
  }
17030
- async getFreshFixes({ path: path16 }) {
17238
+ async getFreshFixes({ path: path17 }) {
17031
17239
  const scanContext = ScanContext.USER_REQUEST;
17032
- logDebug(`[${scanContext}] Getting fresh fixes`, { path: path16 });
17033
- if (this.path !== path16) {
17034
- this.path = path16;
17240
+ logDebug(`[${scanContext}] Getting fresh fixes`, { path: path17 });
17241
+ if (this.path !== path17) {
17242
+ this.path = path17;
17035
17243
  this.reset();
17036
- logInfo(`[${scanContext}] Reset service state for new path`, { path: path16 });
17244
+ logInfo(`[${scanContext}] Reset service state for new path`, { path: path17 });
17037
17245
  }
17038
17246
  try {
17039
17247
  this.gqlClient = await createAuthenticatedMcpGQLClient();
@@ -17051,7 +17259,7 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
17051
17259
  }
17052
17260
  throw error;
17053
17261
  }
17054
- this.triggerScan({ path: path16, gqlClient: this.gqlClient });
17262
+ this.triggerScan({ path: path17, gqlClient: this.gqlClient });
17055
17263
  let isMvsAutoFixEnabled = null;
17056
17264
  try {
17057
17265
  isMvsAutoFixEnabled = await this.gqlClient.getMvsAutoFixSettings();
@@ -17085,33 +17293,33 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
17085
17293
  return noFreshFixesPrompt;
17086
17294
  }
17087
17295
  triggerScan({
17088
- path: path16,
17296
+ path: path17,
17089
17297
  gqlClient
17090
17298
  }) {
17091
- if (this.path !== path16) {
17092
- this.path = path16;
17299
+ if (this.path !== path17) {
17300
+ this.path = path17;
17093
17301
  this.reset();
17094
- logInfo(`Reset service state for new path in triggerScan`, { path: path16 });
17302
+ logInfo(`Reset service state for new path in triggerScan`, { path: path17 });
17095
17303
  }
17096
17304
  this.gqlClient = gqlClient;
17097
17305
  if (!this.intervalId) {
17098
- this.startPeriodicScanning(path16);
17099
- this.executeInitialScan(path16);
17100
- void this.executeInitialFullScan(path16);
17306
+ this.startPeriodicScanning(path17);
17307
+ this.executeInitialScan(path17);
17308
+ void this.executeInitialFullScan(path17);
17101
17309
  }
17102
17310
  }
17103
- startPeriodicScanning(path16) {
17311
+ startPeriodicScanning(path17) {
17104
17312
  const scanContext = ScanContext.BACKGROUND_PERIODIC;
17105
17313
  logDebug(
17106
17314
  `[${scanContext}] Starting periodic scan for new security vulnerabilities`,
17107
17315
  {
17108
- path: path16
17316
+ path: path17
17109
17317
  }
17110
17318
  );
17111
17319
  this.intervalId = setInterval(() => {
17112
- logDebug(`[${scanContext}] Triggering periodic security scan`, { path: path16 });
17320
+ logDebug(`[${scanContext}] Triggering periodic security scan`, { path: path17 });
17113
17321
  this.scanForSecurityVulnerabilities({
17114
- path: path16,
17322
+ path: path17,
17115
17323
  scanContext
17116
17324
  }).catch((error) => {
17117
17325
  logError(`[${scanContext}] Error during periodic security scan`, {
@@ -17120,45 +17328,45 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
17120
17328
  });
17121
17329
  }, MCP_PERIODIC_CHECK_INTERVAL);
17122
17330
  }
17123
- async executeInitialFullScan(path16) {
17331
+ async executeInitialFullScan(path17) {
17124
17332
  const scanContext = ScanContext.FULL_SCAN;
17125
- logDebug(`[${scanContext}] Triggering initial full security scan`, { path: path16 });
17333
+ logDebug(`[${scanContext}] Triggering initial full security scan`, { path: path17 });
17126
17334
  logDebug(`[${scanContext}] Full scan paths scanned`, {
17127
17335
  fullScanPathsScanned: this.fullScanPathsScanned
17128
17336
  });
17129
- if (this.fullScanPathsScanned.includes(path16)) {
17337
+ if (this.fullScanPathsScanned.includes(path17)) {
17130
17338
  logDebug(`[${scanContext}] Full scan already executed for this path`, {
17131
- path: path16
17339
+ path: path17
17132
17340
  });
17133
17341
  return;
17134
17342
  }
17135
17343
  configStore.set("fullScanPathsScanned", [
17136
17344
  ...this.fullScanPathsScanned,
17137
- path16
17345
+ path17
17138
17346
  ]);
17139
17347
  try {
17140
17348
  await this.scanForSecurityVulnerabilities({
17141
- path: path16,
17349
+ path: path17,
17142
17350
  isAllFilesScan: true,
17143
17351
  isAllDetectionRulesScan: true,
17144
17352
  scanContext: ScanContext.FULL_SCAN
17145
17353
  });
17146
- if (!this.fullScanPathsScanned.includes(path16)) {
17147
- this.fullScanPathsScanned.push(path16);
17354
+ if (!this.fullScanPathsScanned.includes(path17)) {
17355
+ this.fullScanPathsScanned.push(path17);
17148
17356
  configStore.set("fullScanPathsScanned", this.fullScanPathsScanned);
17149
17357
  }
17150
- logInfo(`[${scanContext}] Full scan completed`, { path: path16 });
17358
+ logInfo(`[${scanContext}] Full scan completed`, { path: path17 });
17151
17359
  } catch (error) {
17152
17360
  logError(`[${scanContext}] Error during initial full security scan`, {
17153
17361
  error
17154
17362
  });
17155
17363
  }
17156
17364
  }
17157
- executeInitialScan(path16) {
17365
+ executeInitialScan(path17) {
17158
17366
  const scanContext = ScanContext.BACKGROUND_INITIAL;
17159
- logDebug(`[${scanContext}] Triggering initial security scan`, { path: path16 });
17367
+ logDebug(`[${scanContext}] Triggering initial security scan`, { path: path17 });
17160
17368
  this.scanForSecurityVulnerabilities({
17161
- path: path16,
17369
+ path: path17,
17162
17370
  scanContext: ScanContext.BACKGROUND_INITIAL
17163
17371
  }).catch((error) => {
17164
17372
  logError(`[${scanContext}] Error during initial security scan`, { error });
@@ -17254,9 +17462,9 @@ Example payload:
17254
17462
  `Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
17255
17463
  );
17256
17464
  }
17257
- const path16 = pathValidationResult.path;
17465
+ const path17 = pathValidationResult.path;
17258
17466
  const resultText = await this.newFixesService.getFreshFixes({
17259
- path: path16
17467
+ path: path17
17260
17468
  });
17261
17469
  logInfo("CheckForNewAvailableFixesTool execution completed", {
17262
17470
  resultText
@@ -17404,8 +17612,8 @@ Call this tool instead of ${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES} when you only
17404
17612
  `Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
17405
17613
  );
17406
17614
  }
17407
- const path16 = pathValidationResult.path;
17408
- const gitService = new GitService(path16, log);
17615
+ const path17 = pathValidationResult.path;
17616
+ const gitService = new GitService(path17, log);
17409
17617
  const gitValidation = await gitService.validateRepository();
17410
17618
  if (!gitValidation.isValid) {
17411
17619
  throw new Error(`Invalid git repository: ${gitValidation.error}`);
@@ -17671,9 +17879,9 @@ Example payload:
17671
17879
  `Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
17672
17880
  );
17673
17881
  }
17674
- const path16 = pathValidationResult.path;
17882
+ const path17 = pathValidationResult.path;
17675
17883
  const files = await getLocalFiles({
17676
- path: path16,
17884
+ path: path17,
17677
17885
  maxFileSize: MCP_MAX_FILE_SIZE,
17678
17886
  maxFiles: args.maxFiles,
17679
17887
  scanContext: ScanContext.USER_REQUEST
@@ -17692,7 +17900,7 @@ Example payload:
17692
17900
  try {
17693
17901
  const fixResult = await this.vulnerabilityFixService.processVulnerabilities({
17694
17902
  fileList: files.map((file) => file.relativePath),
17695
- repositoryPath: path16,
17903
+ repositoryPath: path17,
17696
17904
  offset: args.offset,
17697
17905
  limit: args.limit,
17698
17906
  isRescan: args.rescan || !!args.maxFiles
@@ -17886,60 +18094,183 @@ async function addScmTokenHandler(args) {
17886
18094
  await addScmToken(args);
17887
18095
  }
17888
18096
 
18097
+ // src/args/commands/upload_ai_blame.ts
18098
+ import fs17 from "fs/promises";
18099
+ import path16 from "path";
18100
+ import chalk10 from "chalk";
18101
+ function uploadAiBlameBuilder(args) {
18102
+ return args.option("prompt", {
18103
+ type: "string",
18104
+ array: true,
18105
+ demandOption: true,
18106
+ describe: chalk10.bold("Path(s) to prompt artifact(s) (one per session)")
18107
+ }).option("inference", {
18108
+ type: "string",
18109
+ array: true,
18110
+ demandOption: true,
18111
+ describe: chalk10.bold(
18112
+ "Path(s) to inference artifact(s) (one per session)"
18113
+ )
18114
+ }).option("ai-response-at", {
18115
+ type: "string",
18116
+ array: true,
18117
+ describe: chalk10.bold(
18118
+ "ISO timestamp(s) for AI response (one per session, defaults to now)"
18119
+ )
18120
+ }).option("model", {
18121
+ type: "string",
18122
+ array: true,
18123
+ describe: chalk10.bold("AI model name(s) (optional, one per session)")
18124
+ }).option("tool-name", {
18125
+ type: "string",
18126
+ array: true,
18127
+ describe: chalk10.bold("Tool/IDE name(s) (optional, one per session)")
18128
+ }).strict();
18129
+ }
18130
+ async function uploadAiBlameHandler(args) {
18131
+ const prompts = args.prompt || [];
18132
+ const inferences = args.inference || [];
18133
+ const models = args.model || [];
18134
+ const tools = args.toolName || args["tool-name"] || [];
18135
+ const responseTimes = args.aiResponseAt || args["ai-response-at"] || [];
18136
+ if (prompts.length !== inferences.length) {
18137
+ console.error(
18138
+ chalk10.red("prompt and inference must have the same number of entries")
18139
+ );
18140
+ process.exit(1);
18141
+ }
18142
+ const nowIso = (/* @__PURE__ */ new Date()).toISOString();
18143
+ const sessions = [];
18144
+ for (let i = 0; i < prompts.length; i++) {
18145
+ const promptPath = String(prompts[i]);
18146
+ const inferencePath = String(inferences[i]);
18147
+ try {
18148
+ await Promise.all([fs17.access(promptPath), fs17.access(inferencePath)]);
18149
+ } catch {
18150
+ console.error(chalk10.red(`File not found for session ${i + 1}`));
18151
+ process.exit(1);
18152
+ }
18153
+ sessions.push({
18154
+ promptFileName: path16.basename(promptPath),
18155
+ inferenceFileName: path16.basename(inferencePath),
18156
+ aiResponseAt: responseTimes[i] || nowIso,
18157
+ model: models[i],
18158
+ toolName: tools[i]
18159
+ });
18160
+ }
18161
+ const gqlClient = await createAuthenticatedMcpGQLClient();
18162
+ const initRes = await gqlClient.uploadAIBlameInferencesInitRaw({ sessions });
18163
+ const uploadSessions = initRes.uploadAIBlameInferencesInit?.uploadSessions ?? [];
18164
+ if (uploadSessions.length !== sessions.length) {
18165
+ console.error(
18166
+ chalk10.red("Init failed to return expected number of sessions")
18167
+ );
18168
+ process.exit(1);
18169
+ }
18170
+ for (let i = 0; i < uploadSessions.length; i++) {
18171
+ const us = uploadSessions[i];
18172
+ const promptPath = String(prompts[i]);
18173
+ const inferencePath = String(inferences[i]);
18174
+ await uploadFile({
18175
+ file: promptPath,
18176
+ url: us.prompt.url,
18177
+ uploadFields: JSON.parse(us.prompt.uploadFieldsJSON),
18178
+ uploadKey: us.prompt.uploadKey
18179
+ });
18180
+ await uploadFile({
18181
+ file: inferencePath,
18182
+ url: us.inference.url,
18183
+ uploadFields: JSON.parse(us.inference.uploadFieldsJSON),
18184
+ uploadKey: us.inference.uploadKey
18185
+ });
18186
+ }
18187
+ const finalizeSessions = uploadSessions.map((us, i) => {
18188
+ const s = sessions[i];
18189
+ return {
18190
+ aiBlameInferenceId: us.aiBlameInferenceId,
18191
+ promptKey: us.prompt.uploadKey,
18192
+ inferenceKey: us.inference.uploadKey,
18193
+ aiResponseAt: s.aiResponseAt,
18194
+ model: s.model,
18195
+ toolName: s.toolName
18196
+ };
18197
+ });
18198
+ const finRes = await gqlClient.finalizeAIBlameInferencesUploadRaw({
18199
+ sessions: finalizeSessions
18200
+ });
18201
+ const status = finRes?.finalizeAIBlameInferencesUpload?.status;
18202
+ if (status !== "OK") {
18203
+ console.error(
18204
+ chalk10.red(
18205
+ `Finalize failed: ${finRes?.finalizeAIBlameInferencesUpload?.error || "unknown error"}`
18206
+ )
18207
+ );
18208
+ process.exit(1);
18209
+ }
18210
+ console.log(chalk10.green("AI Blame uploads finalized successfully"));
18211
+ }
18212
+
17889
18213
  // src/args/yargs.ts
17890
18214
  var parseArgs = async (args) => {
17891
18215
  const yargsInstance = yargs(args);
17892
18216
  return yargsInstance.updateStrings({
17893
- "Commands:": chalk10.yellow.underline.bold("Commands:"),
17894
- "Options:": chalk10.yellow.underline.bold("Options:"),
17895
- "Examples:": chalk10.yellow.underline.bold("Examples:"),
17896
- "Show help": chalk10.bold("Show help")
18217
+ "Commands:": chalk11.yellow.underline.bold("Commands:"),
18218
+ "Options:": chalk11.yellow.underline.bold("Options:"),
18219
+ "Examples:": chalk11.yellow.underline.bold("Examples:"),
18220
+ "Show help": chalk11.bold("Show help")
17897
18221
  }).usage(
17898
- `${chalk10.bold(
18222
+ `${chalk11.bold(
17899
18223
  "\n Bugsy - Trusted, Automatic Vulnerability Fixer \u{1F575}\uFE0F\u200D\u2642\uFE0F\n\n"
17900
- )} ${chalk10.yellow.underline.bold("Usage:")}
17901
- $0 ${chalk10.green(
18224
+ )} ${chalk11.yellow.underline.bold("Usage:")}
18225
+ $0 ${chalk11.green(
17902
18226
  "<command>"
17903
- )} ${chalk10.dim("[options]")}
18227
+ )} ${chalk11.dim("[options]")}
17904
18228
  `
17905
18229
  ).version(false).command(
17906
18230
  mobbCliCommand.scan,
17907
- chalk10.bold(
18231
+ chalk11.bold(
17908
18232
  "Scan your code for vulnerabilities, get automated fixes right away."
17909
18233
  ),
17910
18234
  scanBuilder,
17911
18235
  scanHandler
17912
18236
  ).command(
17913
18237
  mobbCliCommand.analyze,
17914
- chalk10.bold(
18238
+ chalk11.bold(
17915
18239
  "Provide a code repository, get automated fixes right away. You can also provide a vulnerability report to analyze or have Mobb scan the code for you."
17916
18240
  ),
17917
18241
  analyzeBuilder,
17918
18242
  analyzeHandler
17919
18243
  ).command(
17920
18244
  mobbCliCommand.review,
17921
- chalk10.bold(
18245
+ chalk11.bold(
17922
18246
  "Mobb will review your github pull requests and provide comments with fixes "
17923
18247
  ),
17924
18248
  reviewBuilder,
17925
18249
  reviewHandler
17926
18250
  ).command(
17927
18251
  mobbCliCommand.addScmToken,
17928
- chalk10.bold(
18252
+ chalk11.bold(
17929
18253
  "Add your SCM (Github, Gitlab, Azure DevOps) token to Mobb to enable automated fixes."
17930
18254
  ),
17931
18255
  addScmTokenBuilder,
17932
18256
  addScmTokenHandler
17933
18257
  ).command(
17934
18258
  mobbCliCommand.convertToSarif,
17935
- chalk10.bold("Convert an existing SAST report to SARIF format."),
18259
+ chalk11.bold("Convert an existing SAST report to SARIF format."),
17936
18260
  convertToSarifBuilder,
17937
18261
  convertToSarifHandler
17938
18262
  ).command(
17939
18263
  mobbCliCommand.mcp,
17940
- chalk10.bold("Launch the MCP (Model Context Protocol) server."),
18264
+ chalk11.bold("Launch the MCP (Model Context Protocol) server."),
17941
18265
  mcpBuilder,
17942
18266
  mcpHandler
18267
+ ).command(
18268
+ mobbCliCommand.uploadAiBlame,
18269
+ chalk11.bold(
18270
+ "Upload AI Blame inference artifacts (prompt + inference) and finalize them."
18271
+ ),
18272
+ uploadAiBlameBuilder,
18273
+ uploadAiBlameHandler
17943
18274
  ).example(
17944
18275
  "npx mobbdev@latest scan -r https://github.com/WebGoat/WebGoat",
17945
18276
  "Scan an existing repository"
@@ -17948,7 +18279,7 @@ var parseArgs = async (args) => {
17948
18279
  handler() {
17949
18280
  yargsInstance.showHelp();
17950
18281
  }
17951
- }).strictOptions().help("h").alias("h", "help").epilog(chalk10.bgBlue("Made with \u2764\uFE0F by Mobb")).showHelpOnFail(true).wrap(Math.min(120, yargsInstance.terminalWidth())).parse();
18282
+ }).strictOptions().help("h").alias("h", "help").epilog(chalk11.bgBlue("Made with \u2764\uFE0F by Mobb")).showHelpOnFail(true).wrap(Math.min(120, yargsInstance.terminalWidth())).parse();
17952
18283
  };
17953
18284
 
17954
18285
  // src/index.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mobbdev",
3
- "version": "1.0.178",
3
+ "version": "1.0.180",
4
4
  "description": "Automated secure code remediation tool",
5
5
  "repository": "git+https://github.com/mobb-dev/bugsy.git",
6
6
  "main": "dist/index.mjs",