mobbdev 1.2.50 → 1.2.52
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.mjs +7 -2
- package/dist/index.mjs +551 -192
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -4170,6 +4170,9 @@ import multimatch from "multimatch";
|
|
|
4170
4170
|
import StreamZip from "node-stream-zip";
|
|
4171
4171
|
import tmp from "tmp";
|
|
4172
4172
|
|
|
4173
|
+
// src/features/analysis/scm/ado/ado.ts
|
|
4174
|
+
import pLimit from "p-limit";
|
|
4175
|
+
|
|
4173
4176
|
// src/features/analysis/scm/errors.ts
|
|
4174
4177
|
var InvalidAccessTokenError = class extends Error {
|
|
4175
4178
|
constructor(m, scmType) {
|
|
@@ -7043,7 +7046,7 @@ async function getAdoSdk(params) {
|
|
|
7043
7046
|
const url = new URL(repoUrl);
|
|
7044
7047
|
const origin2 = url.origin.toLowerCase().endsWith(".visualstudio.com") ? DEFUALT_ADO_ORIGIN : url.origin.toLowerCase();
|
|
7045
7048
|
const params2 = `path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=commit&versionDescriptor[version]=${branch}&resolveLfs=true&$format=zip&api-version=5.0&download=true`;
|
|
7046
|
-
const
|
|
7049
|
+
const path27 = [
|
|
7047
7050
|
prefixPath,
|
|
7048
7051
|
owner,
|
|
7049
7052
|
projectName,
|
|
@@ -7054,7 +7057,7 @@ async function getAdoSdk(params) {
|
|
|
7054
7057
|
"items",
|
|
7055
7058
|
"items"
|
|
7056
7059
|
].filter(Boolean).join("/");
|
|
7057
|
-
return new URL(`${
|
|
7060
|
+
return new URL(`${path27}?${params2}`, origin2).toString();
|
|
7058
7061
|
},
|
|
7059
7062
|
async getAdoBranchList({ repoUrl }) {
|
|
7060
7063
|
try {
|
|
@@ -7094,6 +7097,136 @@ async function getAdoSdk(params) {
|
|
|
7094
7097
|
);
|
|
7095
7098
|
return res.pullRequestId;
|
|
7096
7099
|
},
|
|
7100
|
+
async getAdoPullRequestMetadata({
|
|
7101
|
+
repoUrl,
|
|
7102
|
+
prNumber
|
|
7103
|
+
}) {
|
|
7104
|
+
const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
7105
|
+
const git = await api2.getGitApi();
|
|
7106
|
+
const pr = await git.getPullRequest(repo, prNumber, projectName);
|
|
7107
|
+
if (!pr) {
|
|
7108
|
+
throw new Error(`Pull request #${prNumber} not found`);
|
|
7109
|
+
}
|
|
7110
|
+
return {
|
|
7111
|
+
title: pr.title,
|
|
7112
|
+
targetBranch: (pr.targetRefName || "").replace("refs/heads/", ""),
|
|
7113
|
+
sourceBranch: (pr.sourceRefName || "").replace("refs/heads/", ""),
|
|
7114
|
+
headCommitSha: pr.lastMergeSourceCommit?.commitId || pr.lastMergeCommit?.commitId || ""
|
|
7115
|
+
};
|
|
7116
|
+
},
|
|
7117
|
+
async getAdoPrFiles({
|
|
7118
|
+
repoUrl,
|
|
7119
|
+
prNumber
|
|
7120
|
+
}) {
|
|
7121
|
+
const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
7122
|
+
const git = await api2.getGitApi();
|
|
7123
|
+
const iterations = await git.getPullRequestIterations(
|
|
7124
|
+
repo,
|
|
7125
|
+
prNumber,
|
|
7126
|
+
projectName
|
|
7127
|
+
);
|
|
7128
|
+
if (!iterations || iterations.length === 0) {
|
|
7129
|
+
return [];
|
|
7130
|
+
}
|
|
7131
|
+
const lastIteration = iterations[iterations.length - 1];
|
|
7132
|
+
if (!lastIteration?.id) {
|
|
7133
|
+
return [];
|
|
7134
|
+
}
|
|
7135
|
+
const iterationId = lastIteration.id;
|
|
7136
|
+
const changes = await git.getPullRequestIterationChanges(
|
|
7137
|
+
repo,
|
|
7138
|
+
prNumber,
|
|
7139
|
+
iterationId,
|
|
7140
|
+
projectName
|
|
7141
|
+
);
|
|
7142
|
+
if (!changes?.changeEntries) {
|
|
7143
|
+
return [];
|
|
7144
|
+
}
|
|
7145
|
+
return changes.changeEntries.filter((entry) => {
|
|
7146
|
+
const changeType = entry.changeType;
|
|
7147
|
+
return changeType !== 16 && entry.item?.path;
|
|
7148
|
+
}).map((entry) => {
|
|
7149
|
+
const path27 = entry.item.path;
|
|
7150
|
+
return path27.startsWith("/") ? path27.slice(1) : path27;
|
|
7151
|
+
});
|
|
7152
|
+
},
|
|
7153
|
+
async searchAdoPullRequests({
|
|
7154
|
+
repoUrl,
|
|
7155
|
+
status,
|
|
7156
|
+
skip,
|
|
7157
|
+
top
|
|
7158
|
+
}) {
|
|
7159
|
+
const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
7160
|
+
const git = await api2.getGitApi();
|
|
7161
|
+
const searchCriteria = {
|
|
7162
|
+
// Cast to number to avoid TypeScript enum compatibility issues between
|
|
7163
|
+
// our AdoPullRequestStatus and azure-devops-node-api's PullRequestStatus
|
|
7164
|
+
status: status ?? 4 /* All */
|
|
7165
|
+
};
|
|
7166
|
+
const prs = await git.getPullRequests(
|
|
7167
|
+
repo,
|
|
7168
|
+
searchCriteria,
|
|
7169
|
+
projectName,
|
|
7170
|
+
void 0,
|
|
7171
|
+
// maxCommentLength
|
|
7172
|
+
skip,
|
|
7173
|
+
top
|
|
7174
|
+
);
|
|
7175
|
+
return prs;
|
|
7176
|
+
},
|
|
7177
|
+
async getAdoPullRequestMetrics({
|
|
7178
|
+
repoUrl,
|
|
7179
|
+
prNumber
|
|
7180
|
+
}) {
|
|
7181
|
+
const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
7182
|
+
const git = await api2.getGitApi();
|
|
7183
|
+
const pr = await git.getPullRequest(repo, prNumber, projectName);
|
|
7184
|
+
if (!pr) {
|
|
7185
|
+
throw new Error(`Pull request #${prNumber} not found`);
|
|
7186
|
+
}
|
|
7187
|
+
const threads = await git.getThreads(repo, prNumber, projectName);
|
|
7188
|
+
const commentIds = (threads || []).filter((t) => t.id && t.comments && t.comments.length > 0).map((t) => String(t.id));
|
|
7189
|
+
return {
|
|
7190
|
+
pr,
|
|
7191
|
+
commentIds,
|
|
7192
|
+
linesAdded: 0
|
|
7193
|
+
};
|
|
7194
|
+
},
|
|
7195
|
+
async getAdoRecentCommits({
|
|
7196
|
+
repoUrl,
|
|
7197
|
+
since
|
|
7198
|
+
}) {
|
|
7199
|
+
const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
7200
|
+
const git = await api2.getGitApi();
|
|
7201
|
+
const repository = await git.getRepository(
|
|
7202
|
+
decodeURI(repo),
|
|
7203
|
+
projectName ? decodeURI(projectName) : void 0
|
|
7204
|
+
);
|
|
7205
|
+
const defaultBranch = repository.defaultBranch?.replace("refs/heads/", "");
|
|
7206
|
+
const commits = await git.getCommits(
|
|
7207
|
+
repo,
|
|
7208
|
+
{
|
|
7209
|
+
fromDate: since,
|
|
7210
|
+
itemVersion: defaultBranch ? { version: defaultBranch } : void 0,
|
|
7211
|
+
$top: 100
|
|
7212
|
+
},
|
|
7213
|
+
projectName
|
|
7214
|
+
);
|
|
7215
|
+
return commits;
|
|
7216
|
+
},
|
|
7217
|
+
async getAdoPrCommits({
|
|
7218
|
+
repoUrl,
|
|
7219
|
+
prNumber
|
|
7220
|
+
}) {
|
|
7221
|
+
const { repo, projectName } = parseAdoOwnerAndRepo(repoUrl);
|
|
7222
|
+
const git = await api2.getGitApi();
|
|
7223
|
+
const commits = await git.getPullRequestCommits(
|
|
7224
|
+
repo,
|
|
7225
|
+
prNumber,
|
|
7226
|
+
projectName
|
|
7227
|
+
);
|
|
7228
|
+
return (commits || []).filter((c) => c.commitId).map((c) => c.commitId);
|
|
7229
|
+
},
|
|
7097
7230
|
async getAdoRepoDefaultBranch({
|
|
7098
7231
|
repoUrl
|
|
7099
7232
|
}) {
|
|
@@ -7232,28 +7365,38 @@ async function getAdoRepoList({
|
|
|
7232
7365
|
});
|
|
7233
7366
|
const gitOrg = await orgApi.getGitApi();
|
|
7234
7367
|
const orgRepos = await gitOrg.getRepositories();
|
|
7368
|
+
const repoLimit = pLimit(5);
|
|
7235
7369
|
const repoInfoList = (await Promise.allSettled(
|
|
7236
|
-
orgRepos.map(
|
|
7237
|
-
|
|
7238
|
-
|
|
7239
|
-
|
|
7240
|
-
|
|
7241
|
-
|
|
7242
|
-
|
|
7243
|
-
|
|
7244
|
-
|
|
7245
|
-
|
|
7246
|
-
|
|
7247
|
-
|
|
7248
|
-
|
|
7249
|
-
|
|
7250
|
-
|
|
7251
|
-
|
|
7252
|
-
|
|
7253
|
-
|
|
7254
|
-
|
|
7255
|
-
|
|
7256
|
-
|
|
7370
|
+
orgRepos.map(
|
|
7371
|
+
(repo) => repoLimit(async () => {
|
|
7372
|
+
if (!repo.name || !repo.remoteUrl || !repo.defaultBranch) {
|
|
7373
|
+
throw new InvalidRepoUrlError("bad repo");
|
|
7374
|
+
}
|
|
7375
|
+
const branch = await gitOrg.getBranch(
|
|
7376
|
+
repo.name,
|
|
7377
|
+
repo.defaultBranch.replace(/^refs\/heads\//, ""),
|
|
7378
|
+
repo.project?.name
|
|
7379
|
+
);
|
|
7380
|
+
return {
|
|
7381
|
+
repoName: repo.name,
|
|
7382
|
+
repoUrl: repo.remoteUrl.replace(
|
|
7383
|
+
/^[hH][tT][tT][pP][sS]:\/\/[^/]+@/,
|
|
7384
|
+
"https://"
|
|
7385
|
+
),
|
|
7386
|
+
repoOwner: org,
|
|
7387
|
+
repoIsPublic: repo.project?.visibility === 2 /* Public */,
|
|
7388
|
+
repoLanguages: [],
|
|
7389
|
+
repoUpdatedAt: (
|
|
7390
|
+
// Use the latest available timestamp.
|
|
7391
|
+
// branch.commit.committer.date = last commit on default branch.
|
|
7392
|
+
// project.lastUpdateTime = last project-level change (may be stale).
|
|
7393
|
+
// ADO doesn't expose a per-repo "last pushed" date like GitHub does,
|
|
7394
|
+
// so feature branch pushes won't be reflected until merged.
|
|
7395
|
+
branch.commit?.committer?.date?.toISOString() || repo.project?.lastUpdateTime?.toISOString() || (/* @__PURE__ */ new Date()).toISOString()
|
|
7396
|
+
)
|
|
7397
|
+
};
|
|
7398
|
+
})
|
|
7399
|
+
)
|
|
7257
7400
|
)).reduce((acc, res) => {
|
|
7258
7401
|
if (res.status === "fulfilled") {
|
|
7259
7402
|
acc.push(res.value);
|
|
@@ -7273,6 +7416,8 @@ async function getAdoRepoList({
|
|
|
7273
7416
|
|
|
7274
7417
|
// src/features/analysis/scm/ado/AdoSCMLib.ts
|
|
7275
7418
|
import { setTimeout as setTimeout2 } from "timers/promises";
|
|
7419
|
+
import pLimit2 from "p-limit";
|
|
7420
|
+
init_client_generates();
|
|
7276
7421
|
|
|
7277
7422
|
// src/features/analysis/scm/scmSubmit/index.ts
|
|
7278
7423
|
init_GitService();
|
|
@@ -7407,6 +7552,19 @@ var SCMLib = class {
|
|
|
7407
7552
|
}
|
|
7408
7553
|
};
|
|
7409
7554
|
|
|
7555
|
+
// src/features/analysis/scm/utils/cursorValidation.ts
|
|
7556
|
+
var MAX_CURSOR_VALUE = 1e5;
|
|
7557
|
+
function parseCursorSafe(cursor, defaultValue = 0, maxValue = MAX_CURSOR_VALUE) {
|
|
7558
|
+
if (cursor === null || cursor === void 0 || cursor === "") {
|
|
7559
|
+
return defaultValue;
|
|
7560
|
+
}
|
|
7561
|
+
const parsed = parseInt(cursor, 10);
|
|
7562
|
+
if (isNaN(parsed) || parsed < 0 || parsed > maxValue) {
|
|
7563
|
+
return defaultValue;
|
|
7564
|
+
}
|
|
7565
|
+
return parsed;
|
|
7566
|
+
}
|
|
7567
|
+
|
|
7410
7568
|
// src/features/analysis/scm/ado/AdoSCMLib.ts
|
|
7411
7569
|
async function initAdoSdk(params) {
|
|
7412
7570
|
const { url, accessToken, scmOrg } = params;
|
|
@@ -7599,28 +7757,190 @@ var AdoSCMLib = class extends SCMLib {
|
|
|
7599
7757
|
markdownComment: comment
|
|
7600
7758
|
});
|
|
7601
7759
|
}
|
|
7602
|
-
async getSubmitRequestMetadata(
|
|
7603
|
-
|
|
7760
|
+
async getSubmitRequestMetadata(submitRequestId) {
|
|
7761
|
+
this._validateAccessTokenAndUrl();
|
|
7762
|
+
const adoSdk = await this.getAdoSdk();
|
|
7763
|
+
return adoSdk.getAdoPullRequestMetadata({
|
|
7764
|
+
repoUrl: this.url,
|
|
7765
|
+
prNumber: Number(submitRequestId)
|
|
7766
|
+
});
|
|
7604
7767
|
}
|
|
7605
|
-
async getPrFiles(
|
|
7606
|
-
|
|
7768
|
+
async getPrFiles(prNumber) {
|
|
7769
|
+
this._validateAccessTokenAndUrl();
|
|
7770
|
+
const adoSdk = await this.getAdoSdk();
|
|
7771
|
+
return adoSdk.getAdoPrFiles({
|
|
7772
|
+
repoUrl: this.url,
|
|
7773
|
+
prNumber
|
|
7774
|
+
});
|
|
7607
7775
|
}
|
|
7608
|
-
async searchSubmitRequests(
|
|
7609
|
-
|
|
7776
|
+
async searchSubmitRequests(params) {
|
|
7777
|
+
this._validateAccessToken();
|
|
7778
|
+
const adoSdk = await this.getAdoSdk();
|
|
7779
|
+
const skip = parseCursorSafe(params.cursor, 0);
|
|
7780
|
+
const top = params.limit || 10;
|
|
7781
|
+
let status = 4 /* All */;
|
|
7782
|
+
if (params.filters?.state === "open") {
|
|
7783
|
+
status = 1 /* Active */;
|
|
7784
|
+
} else if (params.filters?.state === "closed") {
|
|
7785
|
+
status = 4 /* All */;
|
|
7786
|
+
}
|
|
7787
|
+
const prs = await adoSdk.searchAdoPullRequests({
|
|
7788
|
+
repoUrl: params.repoUrl,
|
|
7789
|
+
status,
|
|
7790
|
+
skip,
|
|
7791
|
+
top: top + 1
|
|
7792
|
+
// Fetch one extra to determine hasMore
|
|
7793
|
+
});
|
|
7794
|
+
const apiHasMore = prs.length > top;
|
|
7795
|
+
const prsPage = prs.slice(0, top);
|
|
7796
|
+
const getAdoPrUpdatedDate = (pr) => pr.closedDate || pr.lastMergeSourceCommit?.committer?.date || pr.creationDate || /* @__PURE__ */ new Date();
|
|
7797
|
+
let filtered = prsPage;
|
|
7798
|
+
if (params.filters?.updatedAfter) {
|
|
7799
|
+
const afterDate = params.filters.updatedAfter;
|
|
7800
|
+
filtered = prsPage.filter((pr) => getAdoPrUpdatedDate(pr) > afterDate);
|
|
7801
|
+
}
|
|
7802
|
+
if (params.filters?.state === "closed") {
|
|
7803
|
+
filtered = filtered.filter(
|
|
7804
|
+
(pr) => pr.status === 3 /* Completed */ || pr.status === 2 /* Abandoned */
|
|
7805
|
+
);
|
|
7806
|
+
}
|
|
7807
|
+
const results = filtered.map((pr) => {
|
|
7808
|
+
let prStatus = "open";
|
|
7809
|
+
if (pr.status === 3 /* Completed */) {
|
|
7810
|
+
prStatus = "merged";
|
|
7811
|
+
} else if (pr.status === 2 /* Abandoned */) {
|
|
7812
|
+
prStatus = "closed";
|
|
7813
|
+
}
|
|
7814
|
+
return {
|
|
7815
|
+
submitRequestId: String(pr.pullRequestId),
|
|
7816
|
+
submitRequestNumber: pr.pullRequestId || 0,
|
|
7817
|
+
title: pr.title || "",
|
|
7818
|
+
status: prStatus,
|
|
7819
|
+
sourceBranch: (pr.sourceRefName || "").replace("refs/heads/", ""),
|
|
7820
|
+
targetBranch: (pr.targetRefName || "").replace("refs/heads/", ""),
|
|
7821
|
+
authorName: pr.createdBy?.displayName,
|
|
7822
|
+
authorEmail: pr.createdBy?.uniqueName,
|
|
7823
|
+
createdAt: pr.creationDate || /* @__PURE__ */ new Date(),
|
|
7824
|
+
updatedAt: getAdoPrUpdatedDate(pr),
|
|
7825
|
+
description: pr.description,
|
|
7826
|
+
tickets: [],
|
|
7827
|
+
changedLines: { added: 0, removed: 0 }
|
|
7828
|
+
};
|
|
7829
|
+
});
|
|
7830
|
+
return {
|
|
7831
|
+
results,
|
|
7832
|
+
nextCursor: apiHasMore ? String(skip + top) : void 0,
|
|
7833
|
+
hasMore: apiHasMore
|
|
7834
|
+
};
|
|
7610
7835
|
}
|
|
7611
|
-
|
|
7612
|
-
|
|
7836
|
+
// TODO: Performance — this fetches ALL repositories on every call, then paginates
|
|
7837
|
+
// in-memory. For orgs with thousands of repos this can be slow and wasteful,
|
|
7838
|
+
// especially when the UI pages through results (each page triggers a full re-fetch).
|
|
7839
|
+
// Consider caching the fetched list with a short TTL, or using ADO's
|
|
7840
|
+
// getRepositoriesPaged() API per-project for true server-side pagination.
|
|
7841
|
+
async searchRepos(params) {
|
|
7842
|
+
this._validateAccessToken();
|
|
7843
|
+
if (this.url && new URL(this.url).origin !== scmCloudUrl.Ado) {
|
|
7844
|
+
throw new Error(
|
|
7845
|
+
`Oauth token is not supported for ADO on prem - ${this.url}`
|
|
7846
|
+
);
|
|
7847
|
+
}
|
|
7848
|
+
const allRepos = await getAdoRepoList({
|
|
7849
|
+
orgName: params.scmOrg,
|
|
7850
|
+
accessToken: this.accessToken,
|
|
7851
|
+
tokenOrg: this.scmOrg
|
|
7852
|
+
});
|
|
7853
|
+
allRepos.sort((a, b) => {
|
|
7854
|
+
const dateA = a.repoUpdatedAt ? new Date(a.repoUpdatedAt).getTime() : 0;
|
|
7855
|
+
const dateB = b.repoUpdatedAt ? new Date(b.repoUpdatedAt).getTime() : 0;
|
|
7856
|
+
return dateB - dateA;
|
|
7857
|
+
});
|
|
7858
|
+
const page = parseCursorSafe(params.cursor, 0);
|
|
7859
|
+
const limit = params.limit || 100;
|
|
7860
|
+
const start = page;
|
|
7861
|
+
const pageResults = allRepos.slice(start, start + limit);
|
|
7862
|
+
const hasMore = start + limit < allRepos.length;
|
|
7863
|
+
return {
|
|
7864
|
+
results: pageResults,
|
|
7865
|
+
nextCursor: hasMore ? String(start + limit) : void 0,
|
|
7866
|
+
hasMore
|
|
7867
|
+
};
|
|
7613
7868
|
}
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
|
|
7617
|
-
|
|
7869
|
+
async getPrCommitsBatch(repoUrl, prNumbers) {
|
|
7870
|
+
this._validateAccessToken();
|
|
7871
|
+
const adoSdk = await this.getAdoSdk();
|
|
7872
|
+
const result = /* @__PURE__ */ new Map();
|
|
7873
|
+
const limit = pLimit2(5);
|
|
7874
|
+
await Promise.all(
|
|
7875
|
+
prNumbers.map(
|
|
7876
|
+
(prNumber) => limit(async () => {
|
|
7877
|
+
try {
|
|
7878
|
+
const commits = await adoSdk.getAdoPrCommits({
|
|
7879
|
+
repoUrl,
|
|
7880
|
+
prNumber
|
|
7881
|
+
});
|
|
7882
|
+
result.set(prNumber, commits);
|
|
7883
|
+
} catch (error) {
|
|
7884
|
+
console.warn(
|
|
7885
|
+
`[AdoSCMLib.getPrCommitsBatch] Failed to fetch commits for PR #${prNumber}:`,
|
|
7886
|
+
error instanceof Error ? error.message : String(error)
|
|
7887
|
+
);
|
|
7888
|
+
result.set(prNumber, []);
|
|
7889
|
+
}
|
|
7890
|
+
})
|
|
7891
|
+
)
|
|
7892
|
+
);
|
|
7893
|
+
return result;
|
|
7618
7894
|
}
|
|
7619
|
-
async
|
|
7620
|
-
|
|
7895
|
+
async getPullRequestMetrics(prNumber) {
|
|
7896
|
+
this._validateAccessTokenAndUrl();
|
|
7897
|
+
const adoSdk = await this.getAdoSdk();
|
|
7898
|
+
const { pr, commentIds, linesAdded } = await adoSdk.getAdoPullRequestMetrics({
|
|
7899
|
+
repoUrl: this.url,
|
|
7900
|
+
prNumber
|
|
7901
|
+
});
|
|
7902
|
+
let prStatus = "ACTIVE" /* Active */;
|
|
7903
|
+
if (pr.status === 3) {
|
|
7904
|
+
prStatus = "MERGED" /* Merged */;
|
|
7905
|
+
} else if (pr.status === 2) {
|
|
7906
|
+
prStatus = "CLOSED" /* Closed */;
|
|
7907
|
+
} else if (pr.isDraft) {
|
|
7908
|
+
prStatus = "DRAFT" /* Draft */;
|
|
7909
|
+
}
|
|
7910
|
+
return {
|
|
7911
|
+
prId: String(prNumber),
|
|
7912
|
+
repositoryUrl: this.url,
|
|
7913
|
+
prCreatedAt: pr.creationDate || /* @__PURE__ */ new Date(),
|
|
7914
|
+
prMergedAt: pr.closedDate && pr.status === 3 ? pr.closedDate : null,
|
|
7915
|
+
linesAdded,
|
|
7916
|
+
prStatus,
|
|
7917
|
+
commentIds
|
|
7918
|
+
};
|
|
7919
|
+
}
|
|
7920
|
+
async getRecentCommits(since) {
|
|
7921
|
+
this._validateAccessTokenAndUrl();
|
|
7922
|
+
const adoSdk = await this.getAdoSdk();
|
|
7923
|
+
const commits = await adoSdk.getAdoRecentCommits({
|
|
7924
|
+
repoUrl: this.url,
|
|
7925
|
+
since
|
|
7926
|
+
});
|
|
7927
|
+
return {
|
|
7928
|
+
data: commits.map((c) => ({
|
|
7929
|
+
sha: c.commitId || "",
|
|
7930
|
+
commit: {
|
|
7931
|
+
committer: c.committer?.date ? { date: c.committer.date.toISOString() } : void 0,
|
|
7932
|
+
author: c.author ? { email: c.author.email, name: c.author.name } : void 0,
|
|
7933
|
+
message: c.comment
|
|
7934
|
+
},
|
|
7935
|
+
parents: c.parents?.map((sha) => ({ sha }))
|
|
7936
|
+
}))
|
|
7937
|
+
};
|
|
7621
7938
|
}
|
|
7622
7939
|
async getRateLimitStatus() {
|
|
7623
|
-
return
|
|
7940
|
+
return {
|
|
7941
|
+
remaining: 1e4,
|
|
7942
|
+
reset: new Date(Date.now() + 36e5)
|
|
7943
|
+
};
|
|
7624
7944
|
}
|
|
7625
7945
|
};
|
|
7626
7946
|
|
|
@@ -8218,19 +8538,6 @@ init_env();
|
|
|
8218
8538
|
import { z as z22 } from "zod";
|
|
8219
8539
|
init_client_generates();
|
|
8220
8540
|
|
|
8221
|
-
// src/features/analysis/scm/utils/cursorValidation.ts
|
|
8222
|
-
var MAX_CURSOR_VALUE = 1e5;
|
|
8223
|
-
function parseCursorSafe(cursor, defaultValue = 0, maxValue = MAX_CURSOR_VALUE) {
|
|
8224
|
-
if (cursor === null || cursor === void 0 || cursor === "") {
|
|
8225
|
-
return defaultValue;
|
|
8226
|
-
}
|
|
8227
|
-
const parsed = parseInt(cursor, 10);
|
|
8228
|
-
if (isNaN(parsed) || parsed < 0 || parsed > maxValue) {
|
|
8229
|
-
return defaultValue;
|
|
8230
|
-
}
|
|
8231
|
-
return parsed;
|
|
8232
|
-
}
|
|
8233
|
-
|
|
8234
8541
|
// src/features/analysis/scm/github/github.ts
|
|
8235
8542
|
import { RequestError } from "@octokit/request-error";
|
|
8236
8543
|
|
|
@@ -9597,7 +9904,7 @@ import {
|
|
|
9597
9904
|
Gitlab
|
|
9598
9905
|
} from "@gitbeaker/rest";
|
|
9599
9906
|
import Debug3 from "debug";
|
|
9600
|
-
import
|
|
9907
|
+
import pLimit3 from "p-limit";
|
|
9601
9908
|
import {
|
|
9602
9909
|
Agent,
|
|
9603
9910
|
fetch as undiciFetch,
|
|
@@ -10026,7 +10333,7 @@ async function getGitlabMrCommitsBatch({
|
|
|
10026
10333
|
url: repoUrl,
|
|
10027
10334
|
gitlabAuthToken: accessToken
|
|
10028
10335
|
});
|
|
10029
|
-
const limit =
|
|
10336
|
+
const limit = pLimit3(GITLAB_API_CONCURRENCY);
|
|
10030
10337
|
const results = await Promise.all(
|
|
10031
10338
|
mrNumbers.map(
|
|
10032
10339
|
(mrNumber) => limit(async () => {
|
|
@@ -10065,7 +10372,7 @@ async function getGitlabMrDataBatch({
|
|
|
10065
10372
|
url: repoUrl,
|
|
10066
10373
|
gitlabAuthToken: accessToken
|
|
10067
10374
|
});
|
|
10068
|
-
const limit =
|
|
10375
|
+
const limit = pLimit3(GITLAB_API_CONCURRENCY);
|
|
10069
10376
|
const results = await Promise.all(
|
|
10070
10377
|
mrNumbers.map(
|
|
10071
10378
|
(mrNumber) => limit(async () => {
|
|
@@ -13060,7 +13367,7 @@ async function getRepositoryUrl() {
|
|
|
13060
13367
|
}
|
|
13061
13368
|
const remoteUrl = await gitService.getRemoteUrl();
|
|
13062
13369
|
const parsed = parseScmURL(remoteUrl);
|
|
13063
|
-
return parsed?.scmType
|
|
13370
|
+
return parsed?.scmType && parsed.scmType !== "Unknown" ? remoteUrl : null;
|
|
13064
13371
|
} catch {
|
|
13065
13372
|
return null;
|
|
13066
13373
|
}
|
|
@@ -13867,7 +14174,7 @@ async function postIssueComment(params) {
|
|
|
13867
14174
|
fpDescription
|
|
13868
14175
|
} = params;
|
|
13869
14176
|
const {
|
|
13870
|
-
path:
|
|
14177
|
+
path: path27,
|
|
13871
14178
|
startLine,
|
|
13872
14179
|
vulnerabilityReportIssue: {
|
|
13873
14180
|
vulnerabilityReportIssueTags,
|
|
@@ -13882,7 +14189,7 @@ async function postIssueComment(params) {
|
|
|
13882
14189
|
Refresh the page in order to see the changes.`,
|
|
13883
14190
|
pull_number: pullRequest,
|
|
13884
14191
|
commit_id: commitSha,
|
|
13885
|
-
path:
|
|
14192
|
+
path: path27,
|
|
13886
14193
|
line: startLine
|
|
13887
14194
|
});
|
|
13888
14195
|
const commentId = commentRes.data.id;
|
|
@@ -13916,7 +14223,7 @@ async function postFixComment(params) {
|
|
|
13916
14223
|
scanner
|
|
13917
14224
|
} = params;
|
|
13918
14225
|
const {
|
|
13919
|
-
path:
|
|
14226
|
+
path: path27,
|
|
13920
14227
|
startLine,
|
|
13921
14228
|
vulnerabilityReportIssue: { fixId, vulnerabilityReportIssueTags, category },
|
|
13922
14229
|
vulnerabilityReportIssueId
|
|
@@ -13934,7 +14241,7 @@ async function postFixComment(params) {
|
|
|
13934
14241
|
Refresh the page in order to see the changes.`,
|
|
13935
14242
|
pull_number: pullRequest,
|
|
13936
14243
|
commit_id: commitSha,
|
|
13937
|
-
path:
|
|
14244
|
+
path: path27,
|
|
13938
14245
|
line: startLine
|
|
13939
14246
|
});
|
|
13940
14247
|
const commentId = commentRes.data.id;
|
|
@@ -15857,6 +16164,47 @@ init_client_generates();
|
|
|
15857
16164
|
init_GitService();
|
|
15858
16165
|
init_urlParser2();
|
|
15859
16166
|
|
|
16167
|
+
// src/utils/computeGitDiffAdditions.ts
|
|
16168
|
+
import { mkdtemp, rm, writeFile } from "fs/promises";
|
|
16169
|
+
import { tmpdir } from "os";
|
|
16170
|
+
import path13 from "path";
|
|
16171
|
+
import { simpleGit as simpleGit4 } from "simple-git";
|
|
16172
|
+
async function computeGitDiffAdditions(oldStr, newStr) {
|
|
16173
|
+
const tmpDir = await mkdtemp(path13.join(tmpdir(), "diff-"));
|
|
16174
|
+
const oldFile = path13.join(tmpDir, "old");
|
|
16175
|
+
const newFile = path13.join(tmpDir, "new");
|
|
16176
|
+
try {
|
|
16177
|
+
await writeFile(oldFile, oldStr);
|
|
16178
|
+
await writeFile(newFile, newStr);
|
|
16179
|
+
const git = simpleGit4();
|
|
16180
|
+
let result;
|
|
16181
|
+
try {
|
|
16182
|
+
result = await git.raw([
|
|
16183
|
+
"diff",
|
|
16184
|
+
"--no-index",
|
|
16185
|
+
"--unified=0",
|
|
16186
|
+
oldFile,
|
|
16187
|
+
newFile
|
|
16188
|
+
]);
|
|
16189
|
+
} catch (err) {
|
|
16190
|
+
if (err instanceof Error && "stdOut" in err) {
|
|
16191
|
+
result = err.stdOut;
|
|
16192
|
+
} else {
|
|
16193
|
+
throw err;
|
|
16194
|
+
}
|
|
16195
|
+
}
|
|
16196
|
+
const additions = [];
|
|
16197
|
+
for (const line of result.split("\n")) {
|
|
16198
|
+
if (line.startsWith("+") && !line.startsWith("+++")) {
|
|
16199
|
+
additions.push(line.slice(1));
|
|
16200
|
+
}
|
|
16201
|
+
}
|
|
16202
|
+
return additions.join("\n");
|
|
16203
|
+
} finally {
|
|
16204
|
+
await rm(tmpDir, { recursive: true, force: true });
|
|
16205
|
+
}
|
|
16206
|
+
}
|
|
16207
|
+
|
|
15860
16208
|
// src/features/claude_code/transcript_parser.ts
|
|
15861
16209
|
import fsPromises4 from "fs/promises";
|
|
15862
16210
|
function processTranscriptLine(entry) {
|
|
@@ -16041,29 +16389,40 @@ async function readStdinData() {
|
|
|
16041
16389
|
function validateHookData(data) {
|
|
16042
16390
|
return HookDataSchema.parse(data);
|
|
16043
16391
|
}
|
|
16044
|
-
function
|
|
16392
|
+
function extractStructuredPatchAdditions(hookData) {
|
|
16393
|
+
const editResponse = hookData.tool_response;
|
|
16394
|
+
const additions = [];
|
|
16395
|
+
for (const patch of editResponse.structuredPatch) {
|
|
16396
|
+
for (const line of patch.lines) {
|
|
16397
|
+
if (line.startsWith("+")) {
|
|
16398
|
+
additions.push(line.slice(1));
|
|
16399
|
+
}
|
|
16400
|
+
}
|
|
16401
|
+
}
|
|
16402
|
+
return additions.join("\n");
|
|
16403
|
+
}
|
|
16404
|
+
async function extractInference(hookData) {
|
|
16045
16405
|
if (hookData.tool_name === "Write") {
|
|
16046
16406
|
const writeInput = hookData.tool_input;
|
|
16047
16407
|
return writeInput.content || "";
|
|
16048
16408
|
}
|
|
16049
16409
|
if (hookData.tool_name === "Edit") {
|
|
16050
|
-
const
|
|
16051
|
-
|
|
16052
|
-
|
|
16053
|
-
|
|
16054
|
-
|
|
16055
|
-
|
|
16056
|
-
|
|
16057
|
-
|
|
16410
|
+
const editInput = hookData.tool_input;
|
|
16411
|
+
try {
|
|
16412
|
+
return await computeGitDiffAdditions(
|
|
16413
|
+
editInput.old_string,
|
|
16414
|
+
editInput.new_string
|
|
16415
|
+
);
|
|
16416
|
+
} catch {
|
|
16417
|
+
return extractStructuredPatchAdditions(hookData);
|
|
16058
16418
|
}
|
|
16059
|
-
return additions.join("\n");
|
|
16060
16419
|
}
|
|
16061
16420
|
return "";
|
|
16062
16421
|
}
|
|
16063
16422
|
async function collectHookData() {
|
|
16064
16423
|
const rawData = await readStdinData();
|
|
16065
16424
|
const hookData = validateHookData(rawData);
|
|
16066
|
-
const inference = extractInference(hookData);
|
|
16425
|
+
const inference = await extractInference(hookData);
|
|
16067
16426
|
let tracePayload;
|
|
16068
16427
|
try {
|
|
16069
16428
|
tracePayload = await parseTranscriptAndCreateTrace(
|
|
@@ -16148,9 +16507,9 @@ async function processAndUploadHookData() {
|
|
|
16148
16507
|
// src/features/claude_code/install_hook.ts
|
|
16149
16508
|
import fsPromises5 from "fs/promises";
|
|
16150
16509
|
import os4 from "os";
|
|
16151
|
-
import
|
|
16510
|
+
import path14 from "path";
|
|
16152
16511
|
import chalk11 from "chalk";
|
|
16153
|
-
var CLAUDE_SETTINGS_PATH =
|
|
16512
|
+
var CLAUDE_SETTINGS_PATH = path14.join(os4.homedir(), ".claude", "settings.json");
|
|
16154
16513
|
async function claudeSettingsExists() {
|
|
16155
16514
|
try {
|
|
16156
16515
|
await fsPromises5.access(CLAUDE_SETTINGS_PATH);
|
|
@@ -16335,8 +16694,8 @@ var WorkspaceService = class {
|
|
|
16335
16694
|
* Sets a known workspace path that was discovered through successful validation
|
|
16336
16695
|
* @param path The validated workspace path to store
|
|
16337
16696
|
*/
|
|
16338
|
-
static setKnownWorkspacePath(
|
|
16339
|
-
this.knownWorkspacePath =
|
|
16697
|
+
static setKnownWorkspacePath(path27) {
|
|
16698
|
+
this.knownWorkspacePath = path27;
|
|
16340
16699
|
}
|
|
16341
16700
|
/**
|
|
16342
16701
|
* Gets the known workspace path that was previously validated
|
|
@@ -17197,7 +17556,7 @@ async function createAuthenticatedMcpGQLClient({
|
|
|
17197
17556
|
import { execSync as execSync2 } from "child_process";
|
|
17198
17557
|
import fs13 from "fs";
|
|
17199
17558
|
import os5 from "os";
|
|
17200
|
-
import
|
|
17559
|
+
import path15 from "path";
|
|
17201
17560
|
var IDEs = ["cursor", "windsurf", "webstorm", "vscode", "claude"];
|
|
17202
17561
|
var runCommand = (cmd) => {
|
|
17203
17562
|
try {
|
|
@@ -17212,7 +17571,7 @@ var gitInfo = {
|
|
|
17212
17571
|
};
|
|
17213
17572
|
var getClaudeWorkspacePaths = () => {
|
|
17214
17573
|
const home = os5.homedir();
|
|
17215
|
-
const claudeIdePath =
|
|
17574
|
+
const claudeIdePath = path15.join(home, ".claude", "ide");
|
|
17216
17575
|
const workspacePaths = [];
|
|
17217
17576
|
if (!fs13.existsSync(claudeIdePath)) {
|
|
17218
17577
|
return workspacePaths;
|
|
@@ -17220,7 +17579,7 @@ var getClaudeWorkspacePaths = () => {
|
|
|
17220
17579
|
try {
|
|
17221
17580
|
const lockFiles = fs13.readdirSync(claudeIdePath).filter((file) => file.endsWith(".lock"));
|
|
17222
17581
|
for (const lockFile of lockFiles) {
|
|
17223
|
-
const lockFilePath =
|
|
17582
|
+
const lockFilePath = path15.join(claudeIdePath, lockFile);
|
|
17224
17583
|
try {
|
|
17225
17584
|
const lockContent = JSON.parse(fs13.readFileSync(lockFilePath, "utf8"));
|
|
17226
17585
|
if (lockContent.workspaceFolders && Array.isArray(lockContent.workspaceFolders)) {
|
|
@@ -17245,24 +17604,24 @@ var getMCPConfigPaths = (hostName) => {
|
|
|
17245
17604
|
switch (hostName.toLowerCase()) {
|
|
17246
17605
|
case "cursor":
|
|
17247
17606
|
return [
|
|
17248
|
-
|
|
17607
|
+
path15.join(currentDir, ".cursor", "mcp.json"),
|
|
17249
17608
|
// local first
|
|
17250
|
-
|
|
17609
|
+
path15.join(home, ".cursor", "mcp.json")
|
|
17251
17610
|
];
|
|
17252
17611
|
case "windsurf":
|
|
17253
17612
|
return [
|
|
17254
|
-
|
|
17613
|
+
path15.join(currentDir, ".codeium", "mcp_config.json"),
|
|
17255
17614
|
// local first
|
|
17256
|
-
|
|
17615
|
+
path15.join(home, ".codeium", "windsurf", "mcp_config.json")
|
|
17257
17616
|
];
|
|
17258
17617
|
case "webstorm":
|
|
17259
17618
|
return [];
|
|
17260
17619
|
case "visualstudiocode":
|
|
17261
17620
|
case "vscode":
|
|
17262
17621
|
return [
|
|
17263
|
-
|
|
17622
|
+
path15.join(currentDir, ".vscode", "mcp.json"),
|
|
17264
17623
|
// local first
|
|
17265
|
-
process.platform === "win32" ?
|
|
17624
|
+
process.platform === "win32" ? path15.join(home, "AppData", "Roaming", "Code", "User", "mcp.json") : path15.join(
|
|
17266
17625
|
home,
|
|
17267
17626
|
"Library",
|
|
17268
17627
|
"Application Support",
|
|
@@ -17273,13 +17632,13 @@ var getMCPConfigPaths = (hostName) => {
|
|
|
17273
17632
|
];
|
|
17274
17633
|
case "claude": {
|
|
17275
17634
|
const claudePaths = [
|
|
17276
|
-
|
|
17635
|
+
path15.join(currentDir, ".claude.json"),
|
|
17277
17636
|
// local first
|
|
17278
|
-
|
|
17637
|
+
path15.join(home, ".claude.json")
|
|
17279
17638
|
];
|
|
17280
17639
|
const workspacePaths = getClaudeWorkspacePaths();
|
|
17281
17640
|
for (const workspacePath of workspacePaths) {
|
|
17282
|
-
claudePaths.push(
|
|
17641
|
+
claudePaths.push(path15.join(workspacePath, ".mcp.json"));
|
|
17283
17642
|
}
|
|
17284
17643
|
return claudePaths;
|
|
17285
17644
|
}
|
|
@@ -17440,10 +17799,10 @@ var getHostInfo = (additionalMcpList) => {
|
|
|
17440
17799
|
const ideConfigPaths = /* @__PURE__ */ new Set();
|
|
17441
17800
|
for (const ide of IDEs) {
|
|
17442
17801
|
const configPaths = getMCPConfigPaths(ide);
|
|
17443
|
-
configPaths.forEach((
|
|
17802
|
+
configPaths.forEach((path27) => ideConfigPaths.add(path27));
|
|
17444
17803
|
}
|
|
17445
17804
|
const uniqueAdditionalPaths = additionalMcpList.filter(
|
|
17446
|
-
(
|
|
17805
|
+
(path27) => !ideConfigPaths.has(path27)
|
|
17447
17806
|
);
|
|
17448
17807
|
for (const ide of IDEs) {
|
|
17449
17808
|
const cfg = readMCPConfig(ide);
|
|
@@ -17565,7 +17924,7 @@ init_configs();
|
|
|
17565
17924
|
init_configs();
|
|
17566
17925
|
import fs14 from "fs";
|
|
17567
17926
|
import os6 from "os";
|
|
17568
|
-
import
|
|
17927
|
+
import path16 from "path";
|
|
17569
17928
|
var MAX_DEPTH = 2;
|
|
17570
17929
|
var patterns = ["mcp", "claude"];
|
|
17571
17930
|
var isFileMatch = (fileName) => {
|
|
@@ -17585,7 +17944,7 @@ var searchDir = async (dir, depth = 0) => {
|
|
|
17585
17944
|
if (depth > MAX_DEPTH) return results;
|
|
17586
17945
|
const entries = await fs14.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
17587
17946
|
for (const entry of entries) {
|
|
17588
|
-
const fullPath =
|
|
17947
|
+
const fullPath = path16.join(dir, entry.name);
|
|
17589
17948
|
if (entry.isFile() && isFileMatch(entry.name)) {
|
|
17590
17949
|
results.push(fullPath);
|
|
17591
17950
|
} else if (entry.isDirectory()) {
|
|
@@ -17602,14 +17961,14 @@ var findSystemMCPConfigs = async () => {
|
|
|
17602
17961
|
const home = os6.homedir();
|
|
17603
17962
|
const platform2 = os6.platform();
|
|
17604
17963
|
const knownDirs = platform2 === "win32" ? [
|
|
17605
|
-
|
|
17606
|
-
|
|
17607
|
-
|
|
17964
|
+
path16.join(home, ".cursor"),
|
|
17965
|
+
path16.join(home, "Documents"),
|
|
17966
|
+
path16.join(home, "Downloads")
|
|
17608
17967
|
] : [
|
|
17609
|
-
|
|
17610
|
-
process.env["XDG_CONFIG_HOME"] ||
|
|
17611
|
-
|
|
17612
|
-
|
|
17968
|
+
path16.join(home, ".cursor"),
|
|
17969
|
+
process.env["XDG_CONFIG_HOME"] || path16.join(home, ".config"),
|
|
17970
|
+
path16.join(home, "Documents"),
|
|
17971
|
+
path16.join(home, "Downloads")
|
|
17613
17972
|
];
|
|
17614
17973
|
const timeoutPromise = new Promise(
|
|
17615
17974
|
(resolve) => setTimeout(() => {
|
|
@@ -20025,13 +20384,13 @@ For a complete security audit workflow, use the \`full-security-audit\` prompt.
|
|
|
20025
20384
|
// src/mcp/services/McpDetectionService/CursorMcpDetectionService.ts
|
|
20026
20385
|
import * as fs17 from "fs";
|
|
20027
20386
|
import * as os9 from "os";
|
|
20028
|
-
import * as
|
|
20387
|
+
import * as path18 from "path";
|
|
20029
20388
|
|
|
20030
20389
|
// src/mcp/services/McpDetectionService/BaseMcpDetectionService.ts
|
|
20031
20390
|
init_configs();
|
|
20032
20391
|
import * as fs16 from "fs";
|
|
20033
20392
|
import fetch6 from "node-fetch";
|
|
20034
|
-
import * as
|
|
20393
|
+
import * as path17 from "path";
|
|
20035
20394
|
|
|
20036
20395
|
// src/mcp/services/McpDetectionService/McpDetectionServiceUtils.ts
|
|
20037
20396
|
import * as fs15 from "fs";
|
|
@@ -20040,14 +20399,14 @@ import * as os8 from "os";
|
|
|
20040
20399
|
// src/mcp/services/McpDetectionService/VscodeMcpDetectionService.ts
|
|
20041
20400
|
import * as fs18 from "fs";
|
|
20042
20401
|
import * as os10 from "os";
|
|
20043
|
-
import * as
|
|
20402
|
+
import * as path19 from "path";
|
|
20044
20403
|
|
|
20045
20404
|
// src/mcp/tools/checkForNewAvailableFixes/CheckForNewAvailableFixesTool.ts
|
|
20046
20405
|
import { z as z43 } from "zod";
|
|
20047
20406
|
|
|
20048
20407
|
// src/mcp/services/PathValidation.ts
|
|
20049
20408
|
import fs19 from "fs";
|
|
20050
|
-
import
|
|
20409
|
+
import path20 from "path";
|
|
20051
20410
|
async function validatePath(inputPath) {
|
|
20052
20411
|
logDebug("Validating MCP path", { inputPath });
|
|
20053
20412
|
if (/^\/[a-zA-Z]:\//.test(inputPath)) {
|
|
@@ -20079,7 +20438,7 @@ async function validatePath(inputPath) {
|
|
|
20079
20438
|
logError(error);
|
|
20080
20439
|
return { isValid: false, error, path: inputPath };
|
|
20081
20440
|
}
|
|
20082
|
-
const normalizedPath =
|
|
20441
|
+
const normalizedPath = path20.normalize(inputPath);
|
|
20083
20442
|
if (normalizedPath.includes("..")) {
|
|
20084
20443
|
const error = `Normalized path contains path traversal patterns: ${inputPath}`;
|
|
20085
20444
|
logError(error);
|
|
@@ -20731,7 +21090,7 @@ init_configs();
|
|
|
20731
21090
|
import fs20 from "fs/promises";
|
|
20732
21091
|
import nodePath from "path";
|
|
20733
21092
|
var getLocalFiles = async ({
|
|
20734
|
-
path:
|
|
21093
|
+
path: path27,
|
|
20735
21094
|
maxFileSize = MCP_MAX_FILE_SIZE,
|
|
20736
21095
|
maxFiles,
|
|
20737
21096
|
isAllFilesScan,
|
|
@@ -20739,17 +21098,17 @@ var getLocalFiles = async ({
|
|
|
20739
21098
|
scanRecentlyChangedFiles
|
|
20740
21099
|
}) => {
|
|
20741
21100
|
logDebug(`[${scanContext}] Starting getLocalFiles`, {
|
|
20742
|
-
path:
|
|
21101
|
+
path: path27,
|
|
20743
21102
|
maxFileSize,
|
|
20744
21103
|
maxFiles,
|
|
20745
21104
|
isAllFilesScan,
|
|
20746
21105
|
scanRecentlyChangedFiles
|
|
20747
21106
|
});
|
|
20748
21107
|
try {
|
|
20749
|
-
const resolvedRepoPath = await fs20.realpath(
|
|
21108
|
+
const resolvedRepoPath = await fs20.realpath(path27);
|
|
20750
21109
|
logDebug(`[${scanContext}] Resolved repository path`, {
|
|
20751
21110
|
resolvedRepoPath,
|
|
20752
|
-
originalPath:
|
|
21111
|
+
originalPath: path27
|
|
20753
21112
|
});
|
|
20754
21113
|
const gitService = new GitService(resolvedRepoPath, log);
|
|
20755
21114
|
const gitValidation = await gitService.validateRepository();
|
|
@@ -20762,7 +21121,7 @@ var getLocalFiles = async ({
|
|
|
20762
21121
|
if (!gitValidation.isValid || isAllFilesScan) {
|
|
20763
21122
|
try {
|
|
20764
21123
|
files = await FileUtils.getLastChangedFiles({
|
|
20765
|
-
dir:
|
|
21124
|
+
dir: path27,
|
|
20766
21125
|
maxFileSize,
|
|
20767
21126
|
maxFiles,
|
|
20768
21127
|
isAllFilesScan
|
|
@@ -20854,7 +21213,7 @@ var getLocalFiles = async ({
|
|
|
20854
21213
|
logError(`${scanContext}Unexpected error in getLocalFiles`, {
|
|
20855
21214
|
error: error instanceof Error ? error.message : String(error),
|
|
20856
21215
|
stack: error instanceof Error ? error.stack : void 0,
|
|
20857
|
-
path:
|
|
21216
|
+
path: path27
|
|
20858
21217
|
});
|
|
20859
21218
|
throw error;
|
|
20860
21219
|
}
|
|
@@ -20864,7 +21223,7 @@ var getLocalFiles = async ({
|
|
|
20864
21223
|
init_client_generates();
|
|
20865
21224
|
init_GitService();
|
|
20866
21225
|
import fs21 from "fs";
|
|
20867
|
-
import
|
|
21226
|
+
import path21 from "path";
|
|
20868
21227
|
import { z as z42 } from "zod";
|
|
20869
21228
|
function extractPathFromPatch(patch) {
|
|
20870
21229
|
const match = patch?.match(/diff --git a\/([^\s]+) b\//);
|
|
@@ -20950,7 +21309,7 @@ var LocalMobbFolderService = class {
|
|
|
20950
21309
|
"[LocalMobbFolderService] Non-git repository detected, skipping .gitignore operations"
|
|
20951
21310
|
);
|
|
20952
21311
|
}
|
|
20953
|
-
const mobbFolderPath =
|
|
21312
|
+
const mobbFolderPath = path21.join(
|
|
20954
21313
|
this.repoPath,
|
|
20955
21314
|
this.defaultMobbFolderName
|
|
20956
21315
|
);
|
|
@@ -21122,7 +21481,7 @@ var LocalMobbFolderService = class {
|
|
|
21122
21481
|
mobbFolderPath,
|
|
21123
21482
|
baseFileName
|
|
21124
21483
|
);
|
|
21125
|
-
const filePath =
|
|
21484
|
+
const filePath = path21.join(mobbFolderPath, uniqueFileName);
|
|
21126
21485
|
await fs21.promises.writeFile(filePath, patch, "utf8");
|
|
21127
21486
|
logInfo("[LocalMobbFolderService] Patch saved successfully", {
|
|
21128
21487
|
filePath,
|
|
@@ -21180,11 +21539,11 @@ var LocalMobbFolderService = class {
|
|
|
21180
21539
|
* @returns Unique filename that doesn't conflict with existing files
|
|
21181
21540
|
*/
|
|
21182
21541
|
getUniqueFileName(folderPath, baseFileName) {
|
|
21183
|
-
const baseName =
|
|
21184
|
-
const extension =
|
|
21542
|
+
const baseName = path21.parse(baseFileName).name;
|
|
21543
|
+
const extension = path21.parse(baseFileName).ext;
|
|
21185
21544
|
let uniqueFileName = baseFileName;
|
|
21186
21545
|
let index = 1;
|
|
21187
|
-
while (fs21.existsSync(
|
|
21546
|
+
while (fs21.existsSync(path21.join(folderPath, uniqueFileName))) {
|
|
21188
21547
|
uniqueFileName = `${baseName}-${index}${extension}`;
|
|
21189
21548
|
index++;
|
|
21190
21549
|
if (index > 1e3) {
|
|
@@ -21215,7 +21574,7 @@ var LocalMobbFolderService = class {
|
|
|
21215
21574
|
logDebug("[LocalMobbFolderService] Logging patch info", { fixId: fix.id });
|
|
21216
21575
|
try {
|
|
21217
21576
|
const mobbFolderPath = await this.getFolder();
|
|
21218
|
-
const patchInfoPath =
|
|
21577
|
+
const patchInfoPath = path21.join(mobbFolderPath, "patchInfo.md");
|
|
21219
21578
|
const markdownContent = this.generateFixMarkdown(fix, savedPatchFileName);
|
|
21220
21579
|
let existingContent = "";
|
|
21221
21580
|
if (fs21.existsSync(patchInfoPath)) {
|
|
@@ -21257,7 +21616,7 @@ var LocalMobbFolderService = class {
|
|
|
21257
21616
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
21258
21617
|
const patch = this.extractPatchFromFix(fix);
|
|
21259
21618
|
const relativePatchedFilePath = patch ? extractPathFromPatch(patch) : null;
|
|
21260
|
-
const patchedFilePath = relativePatchedFilePath ?
|
|
21619
|
+
const patchedFilePath = relativePatchedFilePath ? path21.resolve(this.repoPath, relativePatchedFilePath) : null;
|
|
21261
21620
|
const fixIdentifier = savedPatchFileName ? savedPatchFileName.replace(".patch", "") : fix.id;
|
|
21262
21621
|
let markdown = `# Fix ${fixIdentifier}
|
|
21263
21622
|
|
|
@@ -21601,14 +21960,14 @@ import {
|
|
|
21601
21960
|
} from "fs";
|
|
21602
21961
|
import fs22 from "fs/promises";
|
|
21603
21962
|
import parseDiff2 from "parse-diff";
|
|
21604
|
-
import
|
|
21963
|
+
import path22 from "path";
|
|
21605
21964
|
var PatchApplicationService = class {
|
|
21606
21965
|
/**
|
|
21607
21966
|
* Gets the appropriate comment syntax for a file based on its extension
|
|
21608
21967
|
*/
|
|
21609
21968
|
static getCommentSyntax(filePath) {
|
|
21610
|
-
const ext =
|
|
21611
|
-
const basename2 =
|
|
21969
|
+
const ext = path22.extname(filePath).toLowerCase();
|
|
21970
|
+
const basename2 = path22.basename(filePath);
|
|
21612
21971
|
const commentMap = {
|
|
21613
21972
|
// C-style languages (single line comments)
|
|
21614
21973
|
".js": "//",
|
|
@@ -21816,7 +22175,7 @@ var PatchApplicationService = class {
|
|
|
21816
22175
|
}
|
|
21817
22176
|
);
|
|
21818
22177
|
}
|
|
21819
|
-
const dirPath =
|
|
22178
|
+
const dirPath = path22.dirname(normalizedFilePath);
|
|
21820
22179
|
mkdirSync(dirPath, { recursive: true });
|
|
21821
22180
|
writeFileSync(normalizedFilePath, finalContent, "utf8");
|
|
21822
22181
|
return normalizedFilePath;
|
|
@@ -21825,9 +22184,9 @@ var PatchApplicationService = class {
|
|
|
21825
22184
|
repositoryPath,
|
|
21826
22185
|
targetPath
|
|
21827
22186
|
}) {
|
|
21828
|
-
const repoRoot =
|
|
21829
|
-
const normalizedPath =
|
|
21830
|
-
const repoRootWithSep = repoRoot.endsWith(
|
|
22187
|
+
const repoRoot = path22.resolve(repositoryPath);
|
|
22188
|
+
const normalizedPath = path22.resolve(repoRoot, targetPath);
|
|
22189
|
+
const repoRootWithSep = repoRoot.endsWith(path22.sep) ? repoRoot : `${repoRoot}${path22.sep}`;
|
|
21831
22190
|
if (normalizedPath !== repoRoot && !normalizedPath.startsWith(repoRootWithSep)) {
|
|
21832
22191
|
throw new Error(
|
|
21833
22192
|
`Security violation: target path ${targetPath} resolves outside repository`
|
|
@@ -21836,7 +22195,7 @@ var PatchApplicationService = class {
|
|
|
21836
22195
|
return {
|
|
21837
22196
|
repoRoot,
|
|
21838
22197
|
normalizedPath,
|
|
21839
|
-
relativePath:
|
|
22198
|
+
relativePath: path22.relative(repoRoot, normalizedPath)
|
|
21840
22199
|
};
|
|
21841
22200
|
}
|
|
21842
22201
|
/**
|
|
@@ -22118,7 +22477,7 @@ var PatchApplicationService = class {
|
|
|
22118
22477
|
continue;
|
|
22119
22478
|
}
|
|
22120
22479
|
try {
|
|
22121
|
-
const absolutePath =
|
|
22480
|
+
const absolutePath = path22.resolve(repositoryPath, targetFile);
|
|
22122
22481
|
if (existsSync6(absolutePath)) {
|
|
22123
22482
|
const stats = await fs22.stat(absolutePath);
|
|
22124
22483
|
const fileModTime = stats.mtime.getTime();
|
|
@@ -22344,7 +22703,7 @@ var PatchApplicationService = class {
|
|
|
22344
22703
|
fix,
|
|
22345
22704
|
scanContext
|
|
22346
22705
|
});
|
|
22347
|
-
appliedFiles.push(
|
|
22706
|
+
appliedFiles.push(path22.relative(repositoryPath, actualPath));
|
|
22348
22707
|
logDebug(`[${scanContext}] Created new file: ${relativePath}`);
|
|
22349
22708
|
}
|
|
22350
22709
|
/**
|
|
@@ -22393,7 +22752,7 @@ var PatchApplicationService = class {
|
|
|
22393
22752
|
fix,
|
|
22394
22753
|
scanContext
|
|
22395
22754
|
});
|
|
22396
|
-
appliedFiles.push(
|
|
22755
|
+
appliedFiles.push(path22.relative(repositoryPath, actualPath));
|
|
22397
22756
|
logDebug(`[${scanContext}] Modified file: ${relativePath}`);
|
|
22398
22757
|
}
|
|
22399
22758
|
}
|
|
@@ -22590,7 +22949,7 @@ init_configs();
|
|
|
22590
22949
|
// src/mcp/services/FileOperations.ts
|
|
22591
22950
|
init_FileUtils();
|
|
22592
22951
|
import fs23 from "fs";
|
|
22593
|
-
import
|
|
22952
|
+
import path23 from "path";
|
|
22594
22953
|
import AdmZip3 from "adm-zip";
|
|
22595
22954
|
var FileOperations = class {
|
|
22596
22955
|
/**
|
|
@@ -22610,10 +22969,10 @@ var FileOperations = class {
|
|
|
22610
22969
|
let packedFilesCount = 0;
|
|
22611
22970
|
const packedFiles = [];
|
|
22612
22971
|
const excludedFiles = [];
|
|
22613
|
-
const resolvedRepoPath =
|
|
22972
|
+
const resolvedRepoPath = path23.resolve(repositoryPath);
|
|
22614
22973
|
for (const filepath of fileList) {
|
|
22615
|
-
const absoluteFilepath =
|
|
22616
|
-
const resolvedFilePath =
|
|
22974
|
+
const absoluteFilepath = path23.join(repositoryPath, filepath);
|
|
22975
|
+
const resolvedFilePath = path23.resolve(absoluteFilepath);
|
|
22617
22976
|
if (!resolvedFilePath.startsWith(resolvedRepoPath)) {
|
|
22618
22977
|
const reason = "potential path traversal security risk";
|
|
22619
22978
|
logDebug(`[FileOperations] Skipping ${filepath} due to ${reason}`);
|
|
@@ -22660,11 +23019,11 @@ var FileOperations = class {
|
|
|
22660
23019
|
fileList,
|
|
22661
23020
|
repositoryPath
|
|
22662
23021
|
}) {
|
|
22663
|
-
const resolvedRepoPath =
|
|
23022
|
+
const resolvedRepoPath = path23.resolve(repositoryPath);
|
|
22664
23023
|
const validatedPaths = [];
|
|
22665
23024
|
for (const filepath of fileList) {
|
|
22666
|
-
const absoluteFilepath =
|
|
22667
|
-
const resolvedFilePath =
|
|
23025
|
+
const absoluteFilepath = path23.join(repositoryPath, filepath);
|
|
23026
|
+
const resolvedFilePath = path23.resolve(absoluteFilepath);
|
|
22668
23027
|
if (!resolvedFilePath.startsWith(resolvedRepoPath)) {
|
|
22669
23028
|
logDebug(
|
|
22670
23029
|
`[FileOperations] Rejecting ${filepath} - path traversal attempt detected`
|
|
@@ -22692,7 +23051,7 @@ var FileOperations = class {
|
|
|
22692
23051
|
for (const absolutePath of filePaths) {
|
|
22693
23052
|
try {
|
|
22694
23053
|
const content = await fs23.promises.readFile(absolutePath);
|
|
22695
|
-
const relativePath =
|
|
23054
|
+
const relativePath = path23.basename(absolutePath);
|
|
22696
23055
|
fileDataArray.push({
|
|
22697
23056
|
relativePath,
|
|
22698
23057
|
absolutePath,
|
|
@@ -23004,14 +23363,14 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
23004
23363
|
* since the last scan.
|
|
23005
23364
|
*/
|
|
23006
23365
|
async scanForSecurityVulnerabilities({
|
|
23007
|
-
path:
|
|
23366
|
+
path: path27,
|
|
23008
23367
|
isAllDetectionRulesScan,
|
|
23009
23368
|
isAllFilesScan,
|
|
23010
23369
|
scanContext
|
|
23011
23370
|
}) {
|
|
23012
23371
|
this.hasAuthenticationFailed = false;
|
|
23013
23372
|
logDebug(`[${scanContext}] Scanning for new security vulnerabilities`, {
|
|
23014
|
-
path:
|
|
23373
|
+
path: path27
|
|
23015
23374
|
});
|
|
23016
23375
|
if (!this.gqlClient) {
|
|
23017
23376
|
logInfo(`[${scanContext}] No GQL client found, skipping scan`);
|
|
@@ -23027,11 +23386,11 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
23027
23386
|
}
|
|
23028
23387
|
logDebug(
|
|
23029
23388
|
`[${scanContext}] Connected to the API, assembling list of files to scan`,
|
|
23030
|
-
{ path:
|
|
23389
|
+
{ path: path27 }
|
|
23031
23390
|
);
|
|
23032
23391
|
const isBackgroundScan = scanContext === ScanContext.BACKGROUND_INITIAL || scanContext === ScanContext.BACKGROUND_PERIODIC;
|
|
23033
23392
|
const files = await getLocalFiles({
|
|
23034
|
-
path:
|
|
23393
|
+
path: path27,
|
|
23035
23394
|
isAllFilesScan,
|
|
23036
23395
|
scanContext,
|
|
23037
23396
|
scanRecentlyChangedFiles: !isBackgroundScan
|
|
@@ -23057,13 +23416,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
23057
23416
|
});
|
|
23058
23417
|
const { fixReportId, projectId } = await scanFiles({
|
|
23059
23418
|
fileList: filesToScan.map((file) => file.relativePath),
|
|
23060
|
-
repositoryPath:
|
|
23419
|
+
repositoryPath: path27,
|
|
23061
23420
|
gqlClient: this.gqlClient,
|
|
23062
23421
|
isAllDetectionRulesScan,
|
|
23063
23422
|
scanContext
|
|
23064
23423
|
});
|
|
23065
23424
|
logInfo(
|
|
23066
|
-
`[${scanContext}] Security scan completed for ${
|
|
23425
|
+
`[${scanContext}] Security scan completed for ${path27} reportId: ${fixReportId} projectId: ${projectId}`
|
|
23067
23426
|
);
|
|
23068
23427
|
if (isAllFilesScan) {
|
|
23069
23428
|
return;
|
|
@@ -23357,13 +23716,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
23357
23716
|
});
|
|
23358
23717
|
return scannedFiles.some((file) => file.relativePath === fixFile);
|
|
23359
23718
|
}
|
|
23360
|
-
async getFreshFixes({ path:
|
|
23719
|
+
async getFreshFixes({ path: path27 }) {
|
|
23361
23720
|
const scanContext = ScanContext.USER_REQUEST;
|
|
23362
|
-
logDebug(`[${scanContext}] Getting fresh fixes`, { path:
|
|
23363
|
-
if (this.path !==
|
|
23364
|
-
this.path =
|
|
23721
|
+
logDebug(`[${scanContext}] Getting fresh fixes`, { path: path27 });
|
|
23722
|
+
if (this.path !== path27) {
|
|
23723
|
+
this.path = path27;
|
|
23365
23724
|
this.reset();
|
|
23366
|
-
logInfo(`[${scanContext}] Reset service state for new path`, { path:
|
|
23725
|
+
logInfo(`[${scanContext}] Reset service state for new path`, { path: path27 });
|
|
23367
23726
|
}
|
|
23368
23727
|
try {
|
|
23369
23728
|
const loginContext = createMcpLoginContext("check_new_fixes");
|
|
@@ -23382,7 +23741,7 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
23382
23741
|
}
|
|
23383
23742
|
throw error;
|
|
23384
23743
|
}
|
|
23385
|
-
this.triggerScan({ path:
|
|
23744
|
+
this.triggerScan({ path: path27, gqlClient: this.gqlClient });
|
|
23386
23745
|
let isMvsAutoFixEnabled = null;
|
|
23387
23746
|
try {
|
|
23388
23747
|
isMvsAutoFixEnabled = await this.gqlClient.getMvsAutoFixSettings();
|
|
@@ -23416,33 +23775,33 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
23416
23775
|
return noFreshFixesPrompt;
|
|
23417
23776
|
}
|
|
23418
23777
|
triggerScan({
|
|
23419
|
-
path:
|
|
23778
|
+
path: path27,
|
|
23420
23779
|
gqlClient
|
|
23421
23780
|
}) {
|
|
23422
|
-
if (this.path !==
|
|
23423
|
-
this.path =
|
|
23781
|
+
if (this.path !== path27) {
|
|
23782
|
+
this.path = path27;
|
|
23424
23783
|
this.reset();
|
|
23425
|
-
logInfo(`Reset service state for new path in triggerScan`, { path:
|
|
23784
|
+
logInfo(`Reset service state for new path in triggerScan`, { path: path27 });
|
|
23426
23785
|
}
|
|
23427
23786
|
this.gqlClient = gqlClient;
|
|
23428
23787
|
if (!this.intervalId) {
|
|
23429
|
-
this.startPeriodicScanning(
|
|
23430
|
-
this.executeInitialScan(
|
|
23431
|
-
void this.executeInitialFullScan(
|
|
23788
|
+
this.startPeriodicScanning(path27);
|
|
23789
|
+
this.executeInitialScan(path27);
|
|
23790
|
+
void this.executeInitialFullScan(path27);
|
|
23432
23791
|
}
|
|
23433
23792
|
}
|
|
23434
|
-
startPeriodicScanning(
|
|
23793
|
+
startPeriodicScanning(path27) {
|
|
23435
23794
|
const scanContext = ScanContext.BACKGROUND_PERIODIC;
|
|
23436
23795
|
logDebug(
|
|
23437
23796
|
`[${scanContext}] Starting periodic scan for new security vulnerabilities`,
|
|
23438
23797
|
{
|
|
23439
|
-
path:
|
|
23798
|
+
path: path27
|
|
23440
23799
|
}
|
|
23441
23800
|
);
|
|
23442
23801
|
this.intervalId = setInterval(() => {
|
|
23443
|
-
logDebug(`[${scanContext}] Triggering periodic security scan`, { path:
|
|
23802
|
+
logDebug(`[${scanContext}] Triggering periodic security scan`, { path: path27 });
|
|
23444
23803
|
this.scanForSecurityVulnerabilities({
|
|
23445
|
-
path:
|
|
23804
|
+
path: path27,
|
|
23446
23805
|
scanContext
|
|
23447
23806
|
}).catch((error) => {
|
|
23448
23807
|
logError(`[${scanContext}] Error during periodic security scan`, {
|
|
@@ -23451,45 +23810,45 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
23451
23810
|
});
|
|
23452
23811
|
}, MCP_PERIODIC_CHECK_INTERVAL);
|
|
23453
23812
|
}
|
|
23454
|
-
async executeInitialFullScan(
|
|
23813
|
+
async executeInitialFullScan(path27) {
|
|
23455
23814
|
const scanContext = ScanContext.FULL_SCAN;
|
|
23456
|
-
logDebug(`[${scanContext}] Triggering initial full security scan`, { path:
|
|
23815
|
+
logDebug(`[${scanContext}] Triggering initial full security scan`, { path: path27 });
|
|
23457
23816
|
logDebug(`[${scanContext}] Full scan paths scanned`, {
|
|
23458
23817
|
fullScanPathsScanned: this.fullScanPathsScanned
|
|
23459
23818
|
});
|
|
23460
|
-
if (this.fullScanPathsScanned.includes(
|
|
23819
|
+
if (this.fullScanPathsScanned.includes(path27)) {
|
|
23461
23820
|
logDebug(`[${scanContext}] Full scan already executed for this path`, {
|
|
23462
|
-
path:
|
|
23821
|
+
path: path27
|
|
23463
23822
|
});
|
|
23464
23823
|
return;
|
|
23465
23824
|
}
|
|
23466
23825
|
configStore.set("fullScanPathsScanned", [
|
|
23467
23826
|
...this.fullScanPathsScanned,
|
|
23468
|
-
|
|
23827
|
+
path27
|
|
23469
23828
|
]);
|
|
23470
23829
|
try {
|
|
23471
23830
|
await this.scanForSecurityVulnerabilities({
|
|
23472
|
-
path:
|
|
23831
|
+
path: path27,
|
|
23473
23832
|
isAllFilesScan: true,
|
|
23474
23833
|
isAllDetectionRulesScan: true,
|
|
23475
23834
|
scanContext: ScanContext.FULL_SCAN
|
|
23476
23835
|
});
|
|
23477
|
-
if (!this.fullScanPathsScanned.includes(
|
|
23478
|
-
this.fullScanPathsScanned.push(
|
|
23836
|
+
if (!this.fullScanPathsScanned.includes(path27)) {
|
|
23837
|
+
this.fullScanPathsScanned.push(path27);
|
|
23479
23838
|
configStore.set("fullScanPathsScanned", this.fullScanPathsScanned);
|
|
23480
23839
|
}
|
|
23481
|
-
logInfo(`[${scanContext}] Full scan completed`, { path:
|
|
23840
|
+
logInfo(`[${scanContext}] Full scan completed`, { path: path27 });
|
|
23482
23841
|
} catch (error) {
|
|
23483
23842
|
logError(`[${scanContext}] Error during initial full security scan`, {
|
|
23484
23843
|
error
|
|
23485
23844
|
});
|
|
23486
23845
|
}
|
|
23487
23846
|
}
|
|
23488
|
-
executeInitialScan(
|
|
23847
|
+
executeInitialScan(path27) {
|
|
23489
23848
|
const scanContext = ScanContext.BACKGROUND_INITIAL;
|
|
23490
|
-
logDebug(`[${scanContext}] Triggering initial security scan`, { path:
|
|
23849
|
+
logDebug(`[${scanContext}] Triggering initial security scan`, { path: path27 });
|
|
23491
23850
|
this.scanForSecurityVulnerabilities({
|
|
23492
|
-
path:
|
|
23851
|
+
path: path27,
|
|
23493
23852
|
scanContext: ScanContext.BACKGROUND_INITIAL
|
|
23494
23853
|
}).catch((error) => {
|
|
23495
23854
|
logError(`[${scanContext}] Error during initial security scan`, { error });
|
|
@@ -23586,9 +23945,9 @@ Example payload:
|
|
|
23586
23945
|
`Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
|
|
23587
23946
|
);
|
|
23588
23947
|
}
|
|
23589
|
-
const
|
|
23948
|
+
const path27 = pathValidationResult.path;
|
|
23590
23949
|
const resultText = await this.newFixesService.getFreshFixes({
|
|
23591
|
-
path:
|
|
23950
|
+
path: path27
|
|
23592
23951
|
});
|
|
23593
23952
|
logInfo("CheckForNewAvailableFixesTool execution completed", {
|
|
23594
23953
|
resultText
|
|
@@ -23766,8 +24125,8 @@ Call this tool instead of ${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES} when you only
|
|
|
23766
24125
|
`Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
|
|
23767
24126
|
);
|
|
23768
24127
|
}
|
|
23769
|
-
const
|
|
23770
|
-
const gitService = new GitService(
|
|
24128
|
+
const path27 = pathValidationResult.path;
|
|
24129
|
+
const gitService = new GitService(path27, log);
|
|
23771
24130
|
const gitValidation = await gitService.validateRepository();
|
|
23772
24131
|
if (!gitValidation.isValid) {
|
|
23773
24132
|
throw new Error(`Invalid git repository: ${gitValidation.error}`);
|
|
@@ -24152,9 +24511,9 @@ Example payload:
|
|
|
24152
24511
|
`Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
|
|
24153
24512
|
);
|
|
24154
24513
|
}
|
|
24155
|
-
const
|
|
24514
|
+
const path27 = pathValidationResult.path;
|
|
24156
24515
|
const files = await getLocalFiles({
|
|
24157
|
-
path:
|
|
24516
|
+
path: path27,
|
|
24158
24517
|
maxFileSize: MCP_MAX_FILE_SIZE,
|
|
24159
24518
|
maxFiles: args.maxFiles,
|
|
24160
24519
|
scanContext: ScanContext.USER_REQUEST,
|
|
@@ -24174,7 +24533,7 @@ Example payload:
|
|
|
24174
24533
|
try {
|
|
24175
24534
|
const fixResult = await this.vulnerabilityFixService.processVulnerabilities({
|
|
24176
24535
|
fileList: files.map((file) => file.relativePath),
|
|
24177
|
-
repositoryPath:
|
|
24536
|
+
repositoryPath: path27,
|
|
24178
24537
|
offset: args.offset,
|
|
24179
24538
|
limit: args.limit,
|
|
24180
24539
|
isRescan: args.rescan || !!args.maxFiles
|
|
@@ -24414,10 +24773,10 @@ init_client_generates();
|
|
|
24414
24773
|
init_urlParser2();
|
|
24415
24774
|
|
|
24416
24775
|
// src/features/codeium_intellij/codeium_language_server_grpc_client.ts
|
|
24417
|
-
import
|
|
24776
|
+
import path24 from "path";
|
|
24418
24777
|
import * as grpc from "@grpc/grpc-js";
|
|
24419
24778
|
import * as protoLoader from "@grpc/proto-loader";
|
|
24420
|
-
var PROTO_PATH =
|
|
24779
|
+
var PROTO_PATH = path24.join(
|
|
24421
24780
|
getModuleRootDir(),
|
|
24422
24781
|
"src/features/codeium_intellij/proto/exa/language_server_pb/language_server.proto"
|
|
24423
24782
|
);
|
|
@@ -24429,7 +24788,7 @@ function loadProto() {
|
|
|
24429
24788
|
defaults: true,
|
|
24430
24789
|
oneofs: true,
|
|
24431
24790
|
includeDirs: [
|
|
24432
|
-
|
|
24791
|
+
path24.join(getModuleRootDir(), "src/features/codeium_intellij/proto")
|
|
24433
24792
|
]
|
|
24434
24793
|
});
|
|
24435
24794
|
return grpc.loadPackageDefinition(
|
|
@@ -24485,28 +24844,28 @@ async function getGrpcClient(port, csrf3) {
|
|
|
24485
24844
|
// src/features/codeium_intellij/parse_intellij_logs.ts
|
|
24486
24845
|
import fs25 from "fs";
|
|
24487
24846
|
import os11 from "os";
|
|
24488
|
-
import
|
|
24847
|
+
import path25 from "path";
|
|
24489
24848
|
function getLogsDir() {
|
|
24490
24849
|
if (process.platform === "darwin") {
|
|
24491
|
-
return
|
|
24850
|
+
return path25.join(os11.homedir(), "Library/Logs/JetBrains");
|
|
24492
24851
|
} else if (process.platform === "win32") {
|
|
24493
|
-
return
|
|
24494
|
-
process.env["LOCALAPPDATA"] ||
|
|
24852
|
+
return path25.join(
|
|
24853
|
+
process.env["LOCALAPPDATA"] || path25.join(os11.homedir(), "AppData/Local"),
|
|
24495
24854
|
"JetBrains"
|
|
24496
24855
|
);
|
|
24497
24856
|
} else {
|
|
24498
|
-
return
|
|
24857
|
+
return path25.join(os11.homedir(), ".cache/JetBrains");
|
|
24499
24858
|
}
|
|
24500
24859
|
}
|
|
24501
24860
|
function parseIdeLogDir(ideLogDir) {
|
|
24502
24861
|
const logFiles = fs25.readdirSync(ideLogDir).filter((f) => /^idea(\.\d+)?\.log$/.test(f)).map((f) => ({
|
|
24503
24862
|
name: f,
|
|
24504
|
-
mtime: fs25.statSync(
|
|
24863
|
+
mtime: fs25.statSync(path25.join(ideLogDir, f)).mtimeMs
|
|
24505
24864
|
})).sort((a, b) => a.mtime - b.mtime).map((f) => f.name);
|
|
24506
24865
|
let latestCsrf = null;
|
|
24507
24866
|
let latestPort = null;
|
|
24508
24867
|
for (const logFile of logFiles) {
|
|
24509
|
-
const lines = fs25.readFileSync(
|
|
24868
|
+
const lines = fs25.readFileSync(path25.join(ideLogDir, logFile), "utf-8").split("\n");
|
|
24510
24869
|
for (const line of lines) {
|
|
24511
24870
|
if (!line.includes(
|
|
24512
24871
|
"com.codeium.intellij.language_server.LanguageServerProcessHandler"
|
|
@@ -24534,9 +24893,9 @@ function findRunningCodeiumLanguageServers() {
|
|
|
24534
24893
|
const logsDir = getLogsDir();
|
|
24535
24894
|
if (!fs25.existsSync(logsDir)) return results;
|
|
24536
24895
|
for (const ide of fs25.readdirSync(logsDir)) {
|
|
24537
|
-
let ideLogDir =
|
|
24896
|
+
let ideLogDir = path25.join(logsDir, ide);
|
|
24538
24897
|
if (process.platform !== "darwin") {
|
|
24539
|
-
ideLogDir =
|
|
24898
|
+
ideLogDir = path25.join(ideLogDir, "log");
|
|
24540
24899
|
}
|
|
24541
24900
|
if (!fs25.existsSync(ideLogDir) || !fs25.statSync(ideLogDir).isDirectory()) {
|
|
24542
24901
|
continue;
|
|
@@ -24719,10 +25078,10 @@ function processChatStepCodeAction(step) {
|
|
|
24719
25078
|
// src/features/codeium_intellij/install_hook.ts
|
|
24720
25079
|
import fsPromises6 from "fs/promises";
|
|
24721
25080
|
import os12 from "os";
|
|
24722
|
-
import
|
|
25081
|
+
import path26 from "path";
|
|
24723
25082
|
import chalk14 from "chalk";
|
|
24724
25083
|
function getCodeiumHooksPath() {
|
|
24725
|
-
return
|
|
25084
|
+
return path26.join(os12.homedir(), ".codeium", "hooks.json");
|
|
24726
25085
|
}
|
|
24727
25086
|
async function readCodeiumHooks() {
|
|
24728
25087
|
const hooksPath = getCodeiumHooksPath();
|
|
@@ -24735,7 +25094,7 @@ async function readCodeiumHooks() {
|
|
|
24735
25094
|
}
|
|
24736
25095
|
async function writeCodeiumHooks(config2) {
|
|
24737
25096
|
const hooksPath = getCodeiumHooksPath();
|
|
24738
|
-
const dir =
|
|
25097
|
+
const dir = path26.dirname(hooksPath);
|
|
24739
25098
|
await fsPromises6.mkdir(dir, { recursive: true });
|
|
24740
25099
|
await fsPromises6.writeFile(
|
|
24741
25100
|
hooksPath,
|