mobbdev 1.1.32 → 1.1.35
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/args/commands/upload_ai_blame.d.mts +30 -28
- package/dist/args/commands/upload_ai_blame.mjs +1303 -8
- package/dist/index.mjs +98 -117
- package/package.json +2 -1
package/dist/index.mjs
CHANGED
|
@@ -717,12 +717,71 @@ var init_FileUtils = __esm({
|
|
|
717
717
|
// src/features/analysis/scm/services/GitService.ts
|
|
718
718
|
var GitService_exports = {};
|
|
719
719
|
__export(GitService_exports, {
|
|
720
|
-
GitService: () => GitService
|
|
720
|
+
GitService: () => GitService,
|
|
721
|
+
isGitHubUrl: () => isGitHubUrl,
|
|
722
|
+
normalizeGitUrl: () => normalizeGitUrl
|
|
721
723
|
});
|
|
722
724
|
import fs2 from "fs";
|
|
723
725
|
import ignore from "ignore";
|
|
724
726
|
import * as path2 from "path";
|
|
725
727
|
import { simpleGit } from "simple-git";
|
|
728
|
+
function normalizeGitUrl(url) {
|
|
729
|
+
let normalizedUrl = url;
|
|
730
|
+
if (normalizedUrl.endsWith(".git")) {
|
|
731
|
+
normalizedUrl = normalizedUrl.slice(0, -".git".length);
|
|
732
|
+
}
|
|
733
|
+
const sshToHttpsMappings = [
|
|
734
|
+
// GitHub
|
|
735
|
+
{ pattern: "git@github.com:", replacement: "https://github.com/" },
|
|
736
|
+
// GitLab
|
|
737
|
+
{ pattern: "git@gitlab.com:", replacement: "https://gitlab.com/" },
|
|
738
|
+
// Bitbucket
|
|
739
|
+
{ pattern: "git@bitbucket.org:", replacement: "https://bitbucket.org/" },
|
|
740
|
+
// Azure DevOps (SSH format)
|
|
741
|
+
{
|
|
742
|
+
pattern: "git@ssh.dev.azure.com:",
|
|
743
|
+
replacement: "https://dev.azure.com/"
|
|
744
|
+
},
|
|
745
|
+
// Azure DevOps (alternative SSH format)
|
|
746
|
+
{
|
|
747
|
+
pattern: /git@([^:]+):v3\/([^/]+)\/([^/]+)\/([^/]+)/,
|
|
748
|
+
replacement: "https://$1/$2/_git/$4"
|
|
749
|
+
}
|
|
750
|
+
];
|
|
751
|
+
for (const mapping of sshToHttpsMappings) {
|
|
752
|
+
if (typeof mapping.pattern === "string") {
|
|
753
|
+
if (normalizedUrl.startsWith(mapping.pattern)) {
|
|
754
|
+
normalizedUrl = normalizedUrl.replace(
|
|
755
|
+
mapping.pattern,
|
|
756
|
+
mapping.replacement
|
|
757
|
+
);
|
|
758
|
+
break;
|
|
759
|
+
}
|
|
760
|
+
} else {
|
|
761
|
+
const match = normalizedUrl.match(mapping.pattern);
|
|
762
|
+
if (match) {
|
|
763
|
+
normalizedUrl = normalizedUrl.replace(
|
|
764
|
+
mapping.pattern,
|
|
765
|
+
mapping.replacement
|
|
766
|
+
);
|
|
767
|
+
break;
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
if (normalizedUrl.startsWith("https://") || normalizedUrl.startsWith("http://")) {
|
|
772
|
+
normalizedUrl = normalizedUrl.replace(/^(https?:\/\/)([^@/]+@)/, "$1");
|
|
773
|
+
}
|
|
774
|
+
return normalizedUrl;
|
|
775
|
+
}
|
|
776
|
+
function isGitHubUrl(normalizedUrl) {
|
|
777
|
+
try {
|
|
778
|
+
const url = new URL(normalizedUrl);
|
|
779
|
+
const host = url.host.toLowerCase();
|
|
780
|
+
return host === "github.com" || host.endsWith(".github.com");
|
|
781
|
+
} catch {
|
|
782
|
+
return false;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
726
785
|
var MAX_COMMIT_DIFF_SIZE_BYTES, GitService;
|
|
727
786
|
var init_GitService = __esm({
|
|
728
787
|
"src/features/analysis/scm/services/GitService.ts"() {
|
|
@@ -843,7 +902,7 @@ var init_GitService = __esm({
|
|
|
843
902
|
this.git.revparse(["HEAD"]),
|
|
844
903
|
this.git.revparse(["--abbrev-ref", "HEAD"])
|
|
845
904
|
]);
|
|
846
|
-
const normalizedRepoUrl = repoUrl.value ?
|
|
905
|
+
const normalizedRepoUrl = repoUrl.value ? normalizeGitUrl(repoUrl.value) : "";
|
|
847
906
|
this.log("[GitService] Git repository information retrieved", "debug", {
|
|
848
907
|
repoUrl: normalizedRepoUrl,
|
|
849
908
|
hash,
|
|
@@ -941,23 +1000,14 @@ var init_GitService = __esm({
|
|
|
941
1000
|
}
|
|
942
1001
|
}
|
|
943
1002
|
/**
|
|
944
|
-
* Gets the remote repository URL
|
|
1003
|
+
* Gets the remote repository URL (origin)
|
|
945
1004
|
*/
|
|
946
1005
|
async getRemoteUrl() {
|
|
947
1006
|
this.log("[GitService] Getting remote repository URL", "debug");
|
|
948
1007
|
try {
|
|
949
1008
|
const remoteUrl = await this.git.getConfig("remote.origin.url");
|
|
950
1009
|
const url = remoteUrl.value || "";
|
|
951
|
-
|
|
952
|
-
if (normalizedUrl.endsWith(".git")) {
|
|
953
|
-
normalizedUrl = normalizedUrl.slice(0, -".git".length);
|
|
954
|
-
}
|
|
955
|
-
if (normalizedUrl.startsWith("git@github.com:")) {
|
|
956
|
-
normalizedUrl = normalizedUrl.replace(
|
|
957
|
-
"git@github.com:",
|
|
958
|
-
"https://github.com/"
|
|
959
|
-
);
|
|
960
|
-
}
|
|
1010
|
+
const normalizedUrl = normalizeGitUrl(url);
|
|
961
1011
|
this.log("[GitService] Remote repository URL retrieved", "debug", {
|
|
962
1012
|
url: normalizedUrl
|
|
963
1013
|
});
|
|
@@ -1091,95 +1141,6 @@ var init_GitService = __esm({
|
|
|
1091
1141
|
throw new Error(errorMessage);
|
|
1092
1142
|
}
|
|
1093
1143
|
}
|
|
1094
|
-
/**
|
|
1095
|
-
* Normalizes a Git URL to HTTPS format for various Git hosting platforms
|
|
1096
|
-
* @param url The Git URL to normalize
|
|
1097
|
-
* @returns The normalized HTTPS URL
|
|
1098
|
-
*/
|
|
1099
|
-
normalizeGitUrl(url) {
|
|
1100
|
-
let normalizedUrl = url;
|
|
1101
|
-
if (normalizedUrl.endsWith(".git")) {
|
|
1102
|
-
normalizedUrl = normalizedUrl.slice(0, -".git".length);
|
|
1103
|
-
}
|
|
1104
|
-
const sshToHttpsMappings = [
|
|
1105
|
-
// GitHub
|
|
1106
|
-
{ pattern: "git@github.com:", replacement: "https://github.com/" },
|
|
1107
|
-
// GitLab
|
|
1108
|
-
{ pattern: "git@gitlab.com:", replacement: "https://gitlab.com/" },
|
|
1109
|
-
// Bitbucket
|
|
1110
|
-
{ pattern: "git@bitbucket.org:", replacement: "https://bitbucket.org/" },
|
|
1111
|
-
// Azure DevOps (SSH format)
|
|
1112
|
-
{
|
|
1113
|
-
pattern: "git@ssh.dev.azure.com:",
|
|
1114
|
-
replacement: "https://dev.azure.com/"
|
|
1115
|
-
},
|
|
1116
|
-
// Azure DevOps (alternative SSH format)
|
|
1117
|
-
{
|
|
1118
|
-
pattern: /git@([^:]+):v3\/([^/]+)\/([^/]+)\/([^/]+)/,
|
|
1119
|
-
replacement: "https://$1/$2/_git/$4"
|
|
1120
|
-
}
|
|
1121
|
-
];
|
|
1122
|
-
for (const mapping of sshToHttpsMappings) {
|
|
1123
|
-
if (typeof mapping.pattern === "string") {
|
|
1124
|
-
if (normalizedUrl.startsWith(mapping.pattern)) {
|
|
1125
|
-
normalizedUrl = normalizedUrl.replace(
|
|
1126
|
-
mapping.pattern,
|
|
1127
|
-
mapping.replacement
|
|
1128
|
-
);
|
|
1129
|
-
break;
|
|
1130
|
-
}
|
|
1131
|
-
} else {
|
|
1132
|
-
const match = normalizedUrl.match(mapping.pattern);
|
|
1133
|
-
if (match) {
|
|
1134
|
-
normalizedUrl = normalizedUrl.replace(
|
|
1135
|
-
mapping.pattern,
|
|
1136
|
-
mapping.replacement
|
|
1137
|
-
);
|
|
1138
|
-
break;
|
|
1139
|
-
}
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
if (normalizedUrl.startsWith("https://") || normalizedUrl.startsWith("http://")) {
|
|
1143
|
-
normalizedUrl = normalizedUrl.replace(/^(https?:\/\/)([^@/]+@)/, "$1");
|
|
1144
|
-
}
|
|
1145
|
-
return normalizedUrl;
|
|
1146
|
-
}
|
|
1147
|
-
/**
|
|
1148
|
-
* Gets all remote repository URLs (equivalent to 'git remote -v')
|
|
1149
|
-
*/
|
|
1150
|
-
async getRepoUrls() {
|
|
1151
|
-
this.log("[GitService] Getting all remote repository URLs", "debug");
|
|
1152
|
-
try {
|
|
1153
|
-
const remotes = await this.git.remote(["-v"]);
|
|
1154
|
-
if (!remotes) {
|
|
1155
|
-
return {};
|
|
1156
|
-
}
|
|
1157
|
-
const remoteMap = {};
|
|
1158
|
-
remotes.split("\n").forEach((line) => {
|
|
1159
|
-
if (!line.trim()) return;
|
|
1160
|
-
const [remoteName, url, type2] = line.split(/\s+/);
|
|
1161
|
-
if (!remoteName || !url || !type2) return;
|
|
1162
|
-
if (!remoteMap[remoteName]) {
|
|
1163
|
-
remoteMap[remoteName] = { fetch: "", push: "" };
|
|
1164
|
-
}
|
|
1165
|
-
const normalizedUrl = this.normalizeGitUrl(url);
|
|
1166
|
-
const remote = remoteMap[remoteName];
|
|
1167
|
-
if (type2 === "(fetch)") {
|
|
1168
|
-
remote.fetch = normalizedUrl;
|
|
1169
|
-
} else if (type2 === "(push)") {
|
|
1170
|
-
remote.push = normalizedUrl;
|
|
1171
|
-
}
|
|
1172
|
-
});
|
|
1173
|
-
this.log("[GitService] Remote repository URLs retrieved", "debug", {
|
|
1174
|
-
remotes: remoteMap
|
|
1175
|
-
});
|
|
1176
|
-
return remoteMap;
|
|
1177
|
-
} catch (error) {
|
|
1178
|
-
const errorMessage = `Failed to get remote repository URLs: ${error.message}`;
|
|
1179
|
-
this.log(`[GitService] ${errorMessage}`, "error", { error });
|
|
1180
|
-
throw new Error(errorMessage);
|
|
1181
|
-
}
|
|
1182
|
-
}
|
|
1183
1144
|
/**
|
|
1184
1145
|
* Fetches the contents of the .gitignore file from the repository
|
|
1185
1146
|
* @returns The contents of the .gitignore file as a string, or null if the file doesn't exist
|
|
@@ -2237,9 +2198,10 @@ var GetPromptSummaryDocument = `
|
|
|
2237
2198
|
goal
|
|
2238
2199
|
developersPlan
|
|
2239
2200
|
aiImplementationDetails
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2201
|
+
developersPushbacks
|
|
2202
|
+
importantInstructionsAndDecisions
|
|
2203
|
+
backAndForthLevel {
|
|
2204
|
+
level
|
|
2243
2205
|
justification
|
|
2244
2206
|
}
|
|
2245
2207
|
}
|
|
@@ -7700,6 +7662,7 @@ var REPORT_DEFAULT_FILE_NAME = "report.json";
|
|
|
7700
7662
|
init_env();
|
|
7701
7663
|
|
|
7702
7664
|
// src/features/analysis/scm/github/GithubSCMLib.ts
|
|
7665
|
+
import pLimit from "p-limit";
|
|
7703
7666
|
import { z as z21 } from "zod";
|
|
7704
7667
|
|
|
7705
7668
|
// src/features/analysis/scm/github/github.ts
|
|
@@ -8625,6 +8588,7 @@ function getGithubSdk(params = {}) {
|
|
|
8625
8588
|
}
|
|
8626
8589
|
|
|
8627
8590
|
// src/features/analysis/scm/github/GithubSCMLib.ts
|
|
8591
|
+
var GITHUB_COMMIT_FETCH_CONCURRENCY = parseInt(process.env["GITHUB_COMMIT_CONCURRENCY"] || "10", 10) || 10;
|
|
8628
8592
|
function determinePrStatus(state, isDraft) {
|
|
8629
8593
|
switch (state) {
|
|
8630
8594
|
case "CLOSED":
|
|
@@ -8991,12 +8955,15 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
8991
8955
|
}),
|
|
8992
8956
|
this.getPrDiff({ pull_number: prNumber })
|
|
8993
8957
|
]);
|
|
8958
|
+
const limit = pLimit(GITHUB_COMMIT_FETCH_CONCURRENCY);
|
|
8994
8959
|
const commits = await Promise.all(
|
|
8995
8960
|
commitsRes.data.map(
|
|
8996
|
-
(commit) =>
|
|
8997
|
-
|
|
8998
|
-
|
|
8999
|
-
|
|
8961
|
+
(commit) => limit(
|
|
8962
|
+
() => this.getCommitDiff(commit.sha, {
|
|
8963
|
+
repositoryCreatedAt,
|
|
8964
|
+
parentCommitTimestamps
|
|
8965
|
+
})
|
|
8966
|
+
)
|
|
9000
8967
|
)
|
|
9001
8968
|
);
|
|
9002
8969
|
const diffLines = filesRes ? await this._attributeLinesViaBlame(pr.head.ref, filesRes.data, commits) : [];
|
|
@@ -13848,6 +13815,7 @@ import path11 from "path";
|
|
|
13848
13815
|
import chalk9 from "chalk";
|
|
13849
13816
|
import { withFile } from "tmp-promise";
|
|
13850
13817
|
import z31 from "zod";
|
|
13818
|
+
init_GitService();
|
|
13851
13819
|
|
|
13852
13820
|
// src/utils/computerName.ts
|
|
13853
13821
|
import { execSync } from "child_process";
|
|
@@ -14119,6 +14087,19 @@ var PromptItemZ = z31.object({
|
|
|
14119
14087
|
}).optional()
|
|
14120
14088
|
});
|
|
14121
14089
|
var PromptItemArrayZ = z31.array(PromptItemZ);
|
|
14090
|
+
async function getRepositoryUrl() {
|
|
14091
|
+
try {
|
|
14092
|
+
const gitService = new GitService(process.cwd());
|
|
14093
|
+
const isRepo = await gitService.isGitRepository();
|
|
14094
|
+
if (!isRepo) {
|
|
14095
|
+
return null;
|
|
14096
|
+
}
|
|
14097
|
+
const remoteUrl = await gitService.getRemoteUrl();
|
|
14098
|
+
return isGitHubUrl(remoteUrl) ? remoteUrl : null;
|
|
14099
|
+
} catch {
|
|
14100
|
+
return null;
|
|
14101
|
+
}
|
|
14102
|
+
}
|
|
14122
14103
|
function getSystemInfo() {
|
|
14123
14104
|
let userName;
|
|
14124
14105
|
try {
|
|
@@ -14215,7 +14196,8 @@ async function uploadAiBlameHandlerFromExtension(args) {
|
|
|
14215
14196
|
args: uploadArgs,
|
|
14216
14197
|
exitOnError: false,
|
|
14217
14198
|
apiUrl: args.apiUrl,
|
|
14218
|
-
webAppUrl: args.webAppUrl
|
|
14199
|
+
webAppUrl: args.webAppUrl,
|
|
14200
|
+
repositoryUrl: args.repositoryUrl
|
|
14219
14201
|
});
|
|
14220
14202
|
});
|
|
14221
14203
|
});
|
|
@@ -14251,6 +14233,7 @@ async function uploadAiBlameHandler(options) {
|
|
|
14251
14233
|
}
|
|
14252
14234
|
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
14253
14235
|
const { computerName, userName } = getSystemInfo();
|
|
14236
|
+
const repositoryUrl = options.repositoryUrl !== void 0 ? options.repositoryUrl : await getRepositoryUrl();
|
|
14254
14237
|
const sessions = [];
|
|
14255
14238
|
for (let i = 0; i < prompts.length; i++) {
|
|
14256
14239
|
const promptPath = String(prompts[i]);
|
|
@@ -14277,7 +14260,8 @@ async function uploadAiBlameHandler(options) {
|
|
|
14277
14260
|
blameType: blameTypes[i] || "CHAT" /* Chat */,
|
|
14278
14261
|
computerName,
|
|
14279
14262
|
userName,
|
|
14280
|
-
sessionId: sessionIds[i]
|
|
14263
|
+
sessionId: sessionIds[i],
|
|
14264
|
+
repositoryUrl
|
|
14281
14265
|
});
|
|
14282
14266
|
}
|
|
14283
14267
|
const authenticatedClient = await getAuthenticatedGQLClient({
|
|
@@ -14333,7 +14317,8 @@ async function uploadAiBlameHandler(options) {
|
|
|
14333
14317
|
blameType: s.blameType,
|
|
14334
14318
|
computerName: s.computerName,
|
|
14335
14319
|
userName: s.userName,
|
|
14336
|
-
sessionId: s.sessionId
|
|
14320
|
+
sessionId: s.sessionId,
|
|
14321
|
+
repositoryUrl: s.repositoryUrl
|
|
14337
14322
|
};
|
|
14338
14323
|
});
|
|
14339
14324
|
try {
|
|
@@ -22440,11 +22425,7 @@ Call this tool instead of ${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES} when you only
|
|
|
22440
22425
|
if (!gitValidation.isValid) {
|
|
22441
22426
|
throw new Error(`Invalid git repository: ${gitValidation.error}`);
|
|
22442
22427
|
}
|
|
22443
|
-
const
|
|
22444
|
-
if (Object.keys(repoUrls).length > 0 && !repoUrls["origin"]) {
|
|
22445
|
-
throw new Error("Repository must have an origin remote");
|
|
22446
|
-
}
|
|
22447
|
-
const originUrl = repoUrls["origin"]?.fetch;
|
|
22428
|
+
const originUrl = await gitService.getRemoteUrl();
|
|
22448
22429
|
if (!originUrl) {
|
|
22449
22430
|
throw new Error("No origin URL found for the repository");
|
|
22450
22431
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mobbdev",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.35",
|
|
4
4
|
"description": "Automated secure code remediation tool",
|
|
5
5
|
"repository": "git+https://github.com/mobb-dev/bugsy.git",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -86,6 +86,7 @@
|
|
|
86
86
|
"node-stream-zip": "1.15.0",
|
|
87
87
|
"octokit": "3.2.1",
|
|
88
88
|
"open": "8.4.2",
|
|
89
|
+
"p-limit": "3.1.0",
|
|
89
90
|
"parse-diff": "0.11.1",
|
|
90
91
|
"sax": "1.4.3",
|
|
91
92
|
"semver": "7.7.3",
|