mobbdev 1.0.178 → 1.0.179

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 +333 -96
  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");
@@ -13121,13 +13232,13 @@ async function createAuthenticatedMcpGQLClient({
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
  }
@@ -14421,23 +14535,23 @@ init_configs();
14421
14535
  import fs12 from "fs/promises";
14422
14536
  import nodePath from "path";
14423
14537
  var getLocalFiles = async ({
14424
- path: path16,
14538
+ path: path17,
14425
14539
  maxFileSize = MCP_MAX_FILE_SIZE,
14426
14540
  maxFiles,
14427
14541
  isAllFilesScan,
14428
14542
  scanContext
14429
14543
  }) => {
14430
14544
  logDebug(`[${scanContext}] Starting getLocalFiles`, {
14431
- path: path16,
14545
+ path: path17,
14432
14546
  maxFileSize,
14433
14547
  maxFiles,
14434
14548
  isAllFilesScan
14435
14549
  });
14436
14550
  try {
14437
- const resolvedRepoPath = await fs12.realpath(path16);
14551
+ const resolvedRepoPath = await fs12.realpath(path17);
14438
14552
  logDebug(`[${scanContext}] Resolved repository path`, {
14439
14553
  resolvedRepoPath,
14440
- originalPath: path16
14554
+ originalPath: path17
14441
14555
  });
14442
14556
  const gitService = new GitService(resolvedRepoPath, log);
14443
14557
  const gitValidation = await gitService.validateRepository();
@@ -14450,7 +14564,7 @@ var getLocalFiles = async ({
14450
14564
  if (!gitValidation.isValid || isAllFilesScan) {
14451
14565
  try {
14452
14566
  files = await FileUtils.getLastChangedFiles({
14453
- dir: path16,
14567
+ dir: path17,
14454
14568
  maxFileSize,
14455
14569
  maxFiles,
14456
14570
  isAllFilesScan
@@ -14542,7 +14656,7 @@ var getLocalFiles = async ({
14542
14656
  logError(`${scanContext}Unexpected error in getLocalFiles`, {
14543
14657
  error: error instanceof Error ? error.message : String(error),
14544
14658
  stack: error instanceof Error ? error.stack : void 0,
14545
- path: path16
14659
+ path: path17
14546
14660
  });
14547
14661
  throw error;
14548
14662
  }
@@ -16676,14 +16790,14 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
16676
16790
  * since the last scan.
16677
16791
  */
16678
16792
  async scanForSecurityVulnerabilities({
16679
- path: path16,
16793
+ path: path17,
16680
16794
  isAllDetectionRulesScan,
16681
16795
  isAllFilesScan,
16682
16796
  scanContext
16683
16797
  }) {
16684
16798
  this.hasAuthenticationFailed = false;
16685
16799
  logDebug(`[${scanContext}] Scanning for new security vulnerabilities`, {
16686
- path: path16
16800
+ path: path17
16687
16801
  });
16688
16802
  if (!this.gqlClient) {
16689
16803
  logInfo(`[${scanContext}] No GQL client found, skipping scan`);
@@ -16699,10 +16813,10 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
16699
16813
  }
16700
16814
  logDebug(
16701
16815
  `[${scanContext}] Connected to the API, assembling list of files to scan`,
16702
- { path: path16 }
16816
+ { path: path17 }
16703
16817
  );
16704
16818
  const files = await getLocalFiles({
16705
- path: path16,
16819
+ path: path17,
16706
16820
  isAllFilesScan,
16707
16821
  scanContext
16708
16822
  });
@@ -16727,13 +16841,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
16727
16841
  });
16728
16842
  const { fixReportId, projectId } = await scanFiles({
16729
16843
  fileList: filesToScan.map((file) => file.relativePath),
16730
- repositoryPath: path16,
16844
+ repositoryPath: path17,
16731
16845
  gqlClient: this.gqlClient,
16732
16846
  isAllDetectionRulesScan,
16733
16847
  scanContext
16734
16848
  });
16735
16849
  logInfo(
16736
- `[${scanContext}] Security scan completed for ${path16} reportId: ${fixReportId} projectId: ${projectId}`
16850
+ `[${scanContext}] Security scan completed for ${path17} reportId: ${fixReportId} projectId: ${projectId}`
16737
16851
  );
16738
16852
  if (isAllFilesScan) {
16739
16853
  return;
@@ -17027,13 +17141,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
17027
17141
  });
17028
17142
  return scannedFiles.some((file) => file.relativePath === fixFile);
17029
17143
  }
17030
- async getFreshFixes({ path: path16 }) {
17144
+ async getFreshFixes({ path: path17 }) {
17031
17145
  const scanContext = ScanContext.USER_REQUEST;
17032
- logDebug(`[${scanContext}] Getting fresh fixes`, { path: path16 });
17033
- if (this.path !== path16) {
17034
- this.path = path16;
17146
+ logDebug(`[${scanContext}] Getting fresh fixes`, { path: path17 });
17147
+ if (this.path !== path17) {
17148
+ this.path = path17;
17035
17149
  this.reset();
17036
- logInfo(`[${scanContext}] Reset service state for new path`, { path: path16 });
17150
+ logInfo(`[${scanContext}] Reset service state for new path`, { path: path17 });
17037
17151
  }
17038
17152
  try {
17039
17153
  this.gqlClient = await createAuthenticatedMcpGQLClient();
@@ -17051,7 +17165,7 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
17051
17165
  }
17052
17166
  throw error;
17053
17167
  }
17054
- this.triggerScan({ path: path16, gqlClient: this.gqlClient });
17168
+ this.triggerScan({ path: path17, gqlClient: this.gqlClient });
17055
17169
  let isMvsAutoFixEnabled = null;
17056
17170
  try {
17057
17171
  isMvsAutoFixEnabled = await this.gqlClient.getMvsAutoFixSettings();
@@ -17085,33 +17199,33 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
17085
17199
  return noFreshFixesPrompt;
17086
17200
  }
17087
17201
  triggerScan({
17088
- path: path16,
17202
+ path: path17,
17089
17203
  gqlClient
17090
17204
  }) {
17091
- if (this.path !== path16) {
17092
- this.path = path16;
17205
+ if (this.path !== path17) {
17206
+ this.path = path17;
17093
17207
  this.reset();
17094
- logInfo(`Reset service state for new path in triggerScan`, { path: path16 });
17208
+ logInfo(`Reset service state for new path in triggerScan`, { path: path17 });
17095
17209
  }
17096
17210
  this.gqlClient = gqlClient;
17097
17211
  if (!this.intervalId) {
17098
- this.startPeriodicScanning(path16);
17099
- this.executeInitialScan(path16);
17100
- void this.executeInitialFullScan(path16);
17212
+ this.startPeriodicScanning(path17);
17213
+ this.executeInitialScan(path17);
17214
+ void this.executeInitialFullScan(path17);
17101
17215
  }
17102
17216
  }
17103
- startPeriodicScanning(path16) {
17217
+ startPeriodicScanning(path17) {
17104
17218
  const scanContext = ScanContext.BACKGROUND_PERIODIC;
17105
17219
  logDebug(
17106
17220
  `[${scanContext}] Starting periodic scan for new security vulnerabilities`,
17107
17221
  {
17108
- path: path16
17222
+ path: path17
17109
17223
  }
17110
17224
  );
17111
17225
  this.intervalId = setInterval(() => {
17112
- logDebug(`[${scanContext}] Triggering periodic security scan`, { path: path16 });
17226
+ logDebug(`[${scanContext}] Triggering periodic security scan`, { path: path17 });
17113
17227
  this.scanForSecurityVulnerabilities({
17114
- path: path16,
17228
+ path: path17,
17115
17229
  scanContext
17116
17230
  }).catch((error) => {
17117
17231
  logError(`[${scanContext}] Error during periodic security scan`, {
@@ -17120,45 +17234,45 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
17120
17234
  });
17121
17235
  }, MCP_PERIODIC_CHECK_INTERVAL);
17122
17236
  }
17123
- async executeInitialFullScan(path16) {
17237
+ async executeInitialFullScan(path17) {
17124
17238
  const scanContext = ScanContext.FULL_SCAN;
17125
- logDebug(`[${scanContext}] Triggering initial full security scan`, { path: path16 });
17239
+ logDebug(`[${scanContext}] Triggering initial full security scan`, { path: path17 });
17126
17240
  logDebug(`[${scanContext}] Full scan paths scanned`, {
17127
17241
  fullScanPathsScanned: this.fullScanPathsScanned
17128
17242
  });
17129
- if (this.fullScanPathsScanned.includes(path16)) {
17243
+ if (this.fullScanPathsScanned.includes(path17)) {
17130
17244
  logDebug(`[${scanContext}] Full scan already executed for this path`, {
17131
- path: path16
17245
+ path: path17
17132
17246
  });
17133
17247
  return;
17134
17248
  }
17135
17249
  configStore.set("fullScanPathsScanned", [
17136
17250
  ...this.fullScanPathsScanned,
17137
- path16
17251
+ path17
17138
17252
  ]);
17139
17253
  try {
17140
17254
  await this.scanForSecurityVulnerabilities({
17141
- path: path16,
17255
+ path: path17,
17142
17256
  isAllFilesScan: true,
17143
17257
  isAllDetectionRulesScan: true,
17144
17258
  scanContext: ScanContext.FULL_SCAN
17145
17259
  });
17146
- if (!this.fullScanPathsScanned.includes(path16)) {
17147
- this.fullScanPathsScanned.push(path16);
17260
+ if (!this.fullScanPathsScanned.includes(path17)) {
17261
+ this.fullScanPathsScanned.push(path17);
17148
17262
  configStore.set("fullScanPathsScanned", this.fullScanPathsScanned);
17149
17263
  }
17150
- logInfo(`[${scanContext}] Full scan completed`, { path: path16 });
17264
+ logInfo(`[${scanContext}] Full scan completed`, { path: path17 });
17151
17265
  } catch (error) {
17152
17266
  logError(`[${scanContext}] Error during initial full security scan`, {
17153
17267
  error
17154
17268
  });
17155
17269
  }
17156
17270
  }
17157
- executeInitialScan(path16) {
17271
+ executeInitialScan(path17) {
17158
17272
  const scanContext = ScanContext.BACKGROUND_INITIAL;
17159
- logDebug(`[${scanContext}] Triggering initial security scan`, { path: path16 });
17273
+ logDebug(`[${scanContext}] Triggering initial security scan`, { path: path17 });
17160
17274
  this.scanForSecurityVulnerabilities({
17161
- path: path16,
17275
+ path: path17,
17162
17276
  scanContext: ScanContext.BACKGROUND_INITIAL
17163
17277
  }).catch((error) => {
17164
17278
  logError(`[${scanContext}] Error during initial security scan`, { error });
@@ -17254,9 +17368,9 @@ Example payload:
17254
17368
  `Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
17255
17369
  );
17256
17370
  }
17257
- const path16 = pathValidationResult.path;
17371
+ const path17 = pathValidationResult.path;
17258
17372
  const resultText = await this.newFixesService.getFreshFixes({
17259
- path: path16
17373
+ path: path17
17260
17374
  });
17261
17375
  logInfo("CheckForNewAvailableFixesTool execution completed", {
17262
17376
  resultText
@@ -17404,8 +17518,8 @@ Call this tool instead of ${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES} when you only
17404
17518
  `Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
17405
17519
  );
17406
17520
  }
17407
- const path16 = pathValidationResult.path;
17408
- const gitService = new GitService(path16, log);
17521
+ const path17 = pathValidationResult.path;
17522
+ const gitService = new GitService(path17, log);
17409
17523
  const gitValidation = await gitService.validateRepository();
17410
17524
  if (!gitValidation.isValid) {
17411
17525
  throw new Error(`Invalid git repository: ${gitValidation.error}`);
@@ -17671,9 +17785,9 @@ Example payload:
17671
17785
  `Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
17672
17786
  );
17673
17787
  }
17674
- const path16 = pathValidationResult.path;
17788
+ const path17 = pathValidationResult.path;
17675
17789
  const files = await getLocalFiles({
17676
- path: path16,
17790
+ path: path17,
17677
17791
  maxFileSize: MCP_MAX_FILE_SIZE,
17678
17792
  maxFiles: args.maxFiles,
17679
17793
  scanContext: ScanContext.USER_REQUEST
@@ -17692,7 +17806,7 @@ Example payload:
17692
17806
  try {
17693
17807
  const fixResult = await this.vulnerabilityFixService.processVulnerabilities({
17694
17808
  fileList: files.map((file) => file.relativePath),
17695
- repositoryPath: path16,
17809
+ repositoryPath: path17,
17696
17810
  offset: args.offset,
17697
17811
  limit: args.limit,
17698
17812
  isRescan: args.rescan || !!args.maxFiles
@@ -17886,60 +18000,183 @@ async function addScmTokenHandler(args) {
17886
18000
  await addScmToken(args);
17887
18001
  }
17888
18002
 
18003
+ // src/args/commands/upload_ai_blame.ts
18004
+ import fs17 from "fs/promises";
18005
+ import path16 from "path";
18006
+ import chalk10 from "chalk";
18007
+ function uploadAiBlameBuilder(args) {
18008
+ return args.option("prompt", {
18009
+ type: "string",
18010
+ array: true,
18011
+ demandOption: true,
18012
+ describe: chalk10.bold("Path(s) to prompt artifact(s) (one per session)")
18013
+ }).option("inference", {
18014
+ type: "string",
18015
+ array: true,
18016
+ demandOption: true,
18017
+ describe: chalk10.bold(
18018
+ "Path(s) to inference artifact(s) (one per session)"
18019
+ )
18020
+ }).option("ai-response-at", {
18021
+ type: "string",
18022
+ array: true,
18023
+ describe: chalk10.bold(
18024
+ "ISO timestamp(s) for AI response (one per session, defaults to now)"
18025
+ )
18026
+ }).option("model", {
18027
+ type: "string",
18028
+ array: true,
18029
+ describe: chalk10.bold("AI model name(s) (optional, one per session)")
18030
+ }).option("tool-name", {
18031
+ type: "string",
18032
+ array: true,
18033
+ describe: chalk10.bold("Tool/IDE name(s) (optional, one per session)")
18034
+ }).strict();
18035
+ }
18036
+ async function uploadAiBlameHandler(args) {
18037
+ const prompts = args.prompt || [];
18038
+ const inferences = args.inference || [];
18039
+ const models = args.model || [];
18040
+ const tools = args.toolName || args["tool-name"] || [];
18041
+ const responseTimes = args.aiResponseAt || args["ai-response-at"] || [];
18042
+ if (prompts.length !== inferences.length) {
18043
+ console.error(
18044
+ chalk10.red("prompt and inference must have the same number of entries")
18045
+ );
18046
+ process.exit(1);
18047
+ }
18048
+ const nowIso = (/* @__PURE__ */ new Date()).toISOString();
18049
+ const sessions = [];
18050
+ for (let i = 0; i < prompts.length; i++) {
18051
+ const promptPath = String(prompts[i]);
18052
+ const inferencePath = String(inferences[i]);
18053
+ try {
18054
+ await Promise.all([fs17.access(promptPath), fs17.access(inferencePath)]);
18055
+ } catch {
18056
+ console.error(chalk10.red(`File not found for session ${i + 1}`));
18057
+ process.exit(1);
18058
+ }
18059
+ sessions.push({
18060
+ promptFileName: path16.basename(promptPath),
18061
+ inferenceFileName: path16.basename(inferencePath),
18062
+ aiResponseAt: responseTimes[i] || nowIso,
18063
+ model: models[i],
18064
+ toolName: tools[i]
18065
+ });
18066
+ }
18067
+ const gqlClient = await createAuthenticatedMcpGQLClient();
18068
+ const initRes = await gqlClient.uploadAIBlameInferencesInitRaw({ sessions });
18069
+ const uploadSessions = initRes.uploadAIBlameInferencesInit?.uploadSessions ?? [];
18070
+ if (uploadSessions.length !== sessions.length) {
18071
+ console.error(
18072
+ chalk10.red("Init failed to return expected number of sessions")
18073
+ );
18074
+ process.exit(1);
18075
+ }
18076
+ for (let i = 0; i < uploadSessions.length; i++) {
18077
+ const us = uploadSessions[i];
18078
+ const promptPath = String(prompts[i]);
18079
+ const inferencePath = String(inferences[i]);
18080
+ await uploadFile({
18081
+ file: promptPath,
18082
+ url: us.prompt.url,
18083
+ uploadFields: JSON.parse(us.prompt.uploadFieldsJSON),
18084
+ uploadKey: us.prompt.uploadKey
18085
+ });
18086
+ await uploadFile({
18087
+ file: inferencePath,
18088
+ url: us.inference.url,
18089
+ uploadFields: JSON.parse(us.inference.uploadFieldsJSON),
18090
+ uploadKey: us.inference.uploadKey
18091
+ });
18092
+ }
18093
+ const finalizeSessions = uploadSessions.map((us, i) => {
18094
+ const s = sessions[i];
18095
+ return {
18096
+ aiBlameInferenceId: us.aiBlameInferenceId,
18097
+ promptKey: us.prompt.uploadKey,
18098
+ inferenceKey: us.inference.uploadKey,
18099
+ aiResponseAt: s.aiResponseAt,
18100
+ model: s.model,
18101
+ toolName: s.toolName
18102
+ };
18103
+ });
18104
+ const finRes = await gqlClient.finalizeAIBlameInferencesUploadRaw({
18105
+ sessions: finalizeSessions
18106
+ });
18107
+ const status = finRes?.finalizeAIBlameInferencesUpload?.status;
18108
+ if (status !== "OK") {
18109
+ console.error(
18110
+ chalk10.red(
18111
+ `Finalize failed: ${finRes?.finalizeAIBlameInferencesUpload?.error || "unknown error"}`
18112
+ )
18113
+ );
18114
+ process.exit(1);
18115
+ }
18116
+ console.log(chalk10.green("AI Blame uploads finalized successfully"));
18117
+ }
18118
+
17889
18119
  // src/args/yargs.ts
17890
18120
  var parseArgs = async (args) => {
17891
18121
  const yargsInstance = yargs(args);
17892
18122
  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")
18123
+ "Commands:": chalk11.yellow.underline.bold("Commands:"),
18124
+ "Options:": chalk11.yellow.underline.bold("Options:"),
18125
+ "Examples:": chalk11.yellow.underline.bold("Examples:"),
18126
+ "Show help": chalk11.bold("Show help")
17897
18127
  }).usage(
17898
- `${chalk10.bold(
18128
+ `${chalk11.bold(
17899
18129
  "\n Bugsy - Trusted, Automatic Vulnerability Fixer \u{1F575}\uFE0F\u200D\u2642\uFE0F\n\n"
17900
- )} ${chalk10.yellow.underline.bold("Usage:")}
17901
- $0 ${chalk10.green(
18130
+ )} ${chalk11.yellow.underline.bold("Usage:")}
18131
+ $0 ${chalk11.green(
17902
18132
  "<command>"
17903
- )} ${chalk10.dim("[options]")}
18133
+ )} ${chalk11.dim("[options]")}
17904
18134
  `
17905
18135
  ).version(false).command(
17906
18136
  mobbCliCommand.scan,
17907
- chalk10.bold(
18137
+ chalk11.bold(
17908
18138
  "Scan your code for vulnerabilities, get automated fixes right away."
17909
18139
  ),
17910
18140
  scanBuilder,
17911
18141
  scanHandler
17912
18142
  ).command(
17913
18143
  mobbCliCommand.analyze,
17914
- chalk10.bold(
18144
+ chalk11.bold(
17915
18145
  "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
18146
  ),
17917
18147
  analyzeBuilder,
17918
18148
  analyzeHandler
17919
18149
  ).command(
17920
18150
  mobbCliCommand.review,
17921
- chalk10.bold(
18151
+ chalk11.bold(
17922
18152
  "Mobb will review your github pull requests and provide comments with fixes "
17923
18153
  ),
17924
18154
  reviewBuilder,
17925
18155
  reviewHandler
17926
18156
  ).command(
17927
18157
  mobbCliCommand.addScmToken,
17928
- chalk10.bold(
18158
+ chalk11.bold(
17929
18159
  "Add your SCM (Github, Gitlab, Azure DevOps) token to Mobb to enable automated fixes."
17930
18160
  ),
17931
18161
  addScmTokenBuilder,
17932
18162
  addScmTokenHandler
17933
18163
  ).command(
17934
18164
  mobbCliCommand.convertToSarif,
17935
- chalk10.bold("Convert an existing SAST report to SARIF format."),
18165
+ chalk11.bold("Convert an existing SAST report to SARIF format."),
17936
18166
  convertToSarifBuilder,
17937
18167
  convertToSarifHandler
17938
18168
  ).command(
17939
18169
  mobbCliCommand.mcp,
17940
- chalk10.bold("Launch the MCP (Model Context Protocol) server."),
18170
+ chalk11.bold("Launch the MCP (Model Context Protocol) server."),
17941
18171
  mcpBuilder,
17942
18172
  mcpHandler
18173
+ ).command(
18174
+ mobbCliCommand.uploadAiBlame,
18175
+ chalk11.bold(
18176
+ "Upload AI Blame inference artifacts (prompt + inference) and finalize them."
18177
+ ),
18178
+ uploadAiBlameBuilder,
18179
+ uploadAiBlameHandler
17943
18180
  ).example(
17944
18181
  "npx mobbdev@latest scan -r https://github.com/WebGoat/WebGoat",
17945
18182
  "Scan an existing repository"
@@ -17948,7 +18185,7 @@ var parseArgs = async (args) => {
17948
18185
  handler() {
17949
18186
  yargsInstance.showHelp();
17950
18187
  }
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();
18188
+ }).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
18189
  };
17953
18190
 
17954
18191
  // 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.179",
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",