mobbdev 1.4.9 → 1.4.11
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 +20 -1
- package/dist/args/commands/upload_ai_blame.mjs +78 -15
- package/dist/index.mjs +298 -117
- package/package.json +1 -1
|
@@ -206,6 +206,25 @@ declare const PromptItemArrayZ: z.ZodArray<z.ZodObject<{
|
|
|
206
206
|
}[] | undefined;
|
|
207
207
|
}>, "many">;
|
|
208
208
|
type PromptItemArray = z.infer<typeof PromptItemArrayZ>;
|
|
209
|
+
type RepoState = {
|
|
210
|
+
repositoryUrl: string | null;
|
|
211
|
+
branch: string | null;
|
|
212
|
+
commitSha: string | null;
|
|
213
|
+
};
|
|
214
|
+
/**
|
|
215
|
+
* Reads git state for tracy event attribution: repo URL, current branch, and
|
|
216
|
+
* HEAD commit SHA. Each field is read fresh — no caching across calls. Detached
|
|
217
|
+
* HEAD (rebase, bisect) returns `branch: null` rather than the literal string
|
|
218
|
+
* "HEAD" that `git rev-parse --abbrev-ref HEAD` would produce.
|
|
219
|
+
*
|
|
220
|
+
* Both the CLI daemon and the VS Code extension flow through the shared
|
|
221
|
+
* `GitService.getCurrentRepoState()` so detached-HEAD handling and SHA
|
|
222
|
+
* normalization stay in lockstep across the two clients.
|
|
223
|
+
*
|
|
224
|
+
* Never throws — non-existent dirs, missing git binaries, and unrecognized
|
|
225
|
+
* remotes all resolve to nulls so the daemon hot path can rely on a value.
|
|
226
|
+
*/
|
|
227
|
+
declare function readRepoState(workingDir?: string): Promise<RepoState>;
|
|
209
228
|
/**
|
|
210
229
|
* Gets the normalized GitHub repository URL from the current working directory.
|
|
211
230
|
* Returns null if not in a git repository or if not a GitHub repository.
|
|
@@ -265,4 +284,4 @@ type UploadAiBlameHandlerOptions = {
|
|
|
265
284
|
declare function uploadAiBlameHandler(options: UploadAiBlameHandlerOptions): Promise<void>;
|
|
266
285
|
declare function uploadAiBlameCommandHandler(args: UploadAiBlameOptions): Promise<void>;
|
|
267
286
|
|
|
268
|
-
export { type PromptItem, type PromptItemArray, type UploadAiBlameOptions, type UploadAiBlameResult, getRepositoryUrl, getSystemInfo, uploadAiBlameBuilder, uploadAiBlameCommandHandler, uploadAiBlameHandler, uploadAiBlameHandlerFromExtension };
|
|
287
|
+
export { type PromptItem, type PromptItemArray, type RepoState, type UploadAiBlameOptions, type UploadAiBlameResult, getRepositoryUrl, getSystemInfo, readRepoState, uploadAiBlameBuilder, uploadAiBlameCommandHandler, uploadAiBlameHandler, uploadAiBlameHandlerFromExtension };
|
|
@@ -464,6 +464,9 @@ var init_client_generates = __esm({
|
|
|
464
464
|
... on FixData {
|
|
465
465
|
patch
|
|
466
466
|
patchOriginalEncodingBase64
|
|
467
|
+
questions {
|
|
468
|
+
name
|
|
469
|
+
}
|
|
467
470
|
extraContext {
|
|
468
471
|
extraContext {
|
|
469
472
|
key
|
|
@@ -1342,7 +1345,7 @@ var init_shared = __esm({
|
|
|
1342
1345
|
|
|
1343
1346
|
// src/features/analysis/scm/shared/src/types/fix.ts
|
|
1344
1347
|
import { z as z2 } from "zod";
|
|
1345
|
-
var PackageInfoZ, ManifestActionRequiredZ, ExtraContextInternalZ, FixExtraContextZ, PatchAndQuestionsZ, FixRatingZ, IssueSharedStateZ, FixSharedStateZ, FixQueryZ, FixPartsForFixScreenZ;
|
|
1348
|
+
var PackageInfoZ, ManifestActionRequiredZ, ExtraContextInternalZ, FixExtraContextZ, PatchAndQuestionsZ, FixRatingZ, IssueRatingZ, IssueSharedStateZ, FixSharedStateZ, FixQueryZ, FixPartsForFixScreenZ;
|
|
1346
1349
|
var init_fix = __esm({
|
|
1347
1350
|
"src/features/analysis/scm/shared/src/types/fix.ts"() {
|
|
1348
1351
|
"use strict";
|
|
@@ -1403,6 +1406,15 @@ var init_fix = __esm({
|
|
|
1403
1406
|
name: z2.string()
|
|
1404
1407
|
})
|
|
1405
1408
|
});
|
|
1409
|
+
IssueRatingZ = z2.object({
|
|
1410
|
+
voteScore: z2.number(),
|
|
1411
|
+
comment: z2.string().nullable().default(null),
|
|
1412
|
+
updatedDate: z2.string().nullable(),
|
|
1413
|
+
user: z2.object({
|
|
1414
|
+
email: z2.string(),
|
|
1415
|
+
name: z2.string()
|
|
1416
|
+
})
|
|
1417
|
+
});
|
|
1406
1418
|
IssueSharedStateZ = z2.object({
|
|
1407
1419
|
id: z2.string(),
|
|
1408
1420
|
createdAt: z2.string(),
|
|
@@ -1412,7 +1424,8 @@ var init_fix = __esm({
|
|
|
1412
1424
|
z2.object({
|
|
1413
1425
|
url: z2.string()
|
|
1414
1426
|
})
|
|
1415
|
-
)
|
|
1427
|
+
),
|
|
1428
|
+
issueRatings: z2.array(IssueRatingZ).default([])
|
|
1416
1429
|
}).nullable();
|
|
1417
1430
|
FixSharedStateZ = z2.object({
|
|
1418
1431
|
state: z2.nativeEnum(Fix_State_Enum),
|
|
@@ -1518,7 +1531,7 @@ var init_analysis = __esm({
|
|
|
1518
1531
|
|
|
1519
1532
|
// src/features/analysis/scm/shared/src/types/issue.ts
|
|
1520
1533
|
import { z as z4 } from "zod";
|
|
1521
|
-
var MAX_SOURCE_CODE_FILE_SIZE_IN_BYTES, VulnerabilityReportIssueSharedStateZ, BaseIssuePartsZ, FalsePositivePartsZ, IssuePartsWithFixZ, IssuePartsFpZ, GeneralIssueZ, IssuePartsZ, GetIssueIndexesZ, GetIssueScreenDataZ, IssueBucketZ, mapBucketTypeToCategory;
|
|
1534
|
+
var MAX_SOURCE_CODE_FILE_SIZE_IN_BYTES, VulnerabilityReportIssueRatingZ, VulnerabilityReportIssueSharedStateZ, BaseIssuePartsZ, FalsePositivePartsZ, IssuePartsWithFixZ, IssuePartsFpZ, GeneralIssueZ, IssuePartsZ, GetIssueIndexesZ, GetIssueScreenDataZ, IssueBucketZ, mapBucketTypeToCategory;
|
|
1522
1535
|
var init_issue = __esm({
|
|
1523
1536
|
"src/features/analysis/scm/shared/src/types/issue.ts"() {
|
|
1524
1537
|
"use strict";
|
|
@@ -1527,6 +1540,15 @@ var init_issue = __esm({
|
|
|
1527
1540
|
init_fix();
|
|
1528
1541
|
init_shared();
|
|
1529
1542
|
MAX_SOURCE_CODE_FILE_SIZE_IN_BYTES = 1e5;
|
|
1543
|
+
VulnerabilityReportIssueRatingZ = z4.object({
|
|
1544
|
+
voteScore: z4.number(),
|
|
1545
|
+
comment: z4.string().nullable().default(null),
|
|
1546
|
+
updatedDate: z4.string().nullable(),
|
|
1547
|
+
user: z4.object({
|
|
1548
|
+
email: z4.string(),
|
|
1549
|
+
name: z4.string()
|
|
1550
|
+
})
|
|
1551
|
+
});
|
|
1530
1552
|
VulnerabilityReportIssueSharedStateZ = z4.object({
|
|
1531
1553
|
id: z4.string().uuid(),
|
|
1532
1554
|
createdAt: z4.string(),
|
|
@@ -1536,7 +1558,8 @@ var init_issue = __esm({
|
|
|
1536
1558
|
z4.object({
|
|
1537
1559
|
url: z4.string()
|
|
1538
1560
|
})
|
|
1539
|
-
)
|
|
1561
|
+
),
|
|
1562
|
+
issueRatings: z4.array(VulnerabilityReportIssueRatingZ).default([])
|
|
1540
1563
|
}).nullish();
|
|
1541
1564
|
BaseIssuePartsZ = z4.object({
|
|
1542
1565
|
id: z4.string().uuid(),
|
|
@@ -3845,6 +3868,31 @@ var init_GitService = __esm({
|
|
|
3845
3868
|
throw new Error(errorMessage);
|
|
3846
3869
|
}
|
|
3847
3870
|
}
|
|
3871
|
+
/**
|
|
3872
|
+
* Reads `{ branch, commitSha }` for tracy event attribution. Detached-HEAD
|
|
3873
|
+
* (rebase, bisect, "open this commit") returns `branch: null` rather than
|
|
3874
|
+
* the literal string `"HEAD"` that `getCurrentBranch()` produces — that
|
|
3875
|
+
* literal would silently corrupt downstream branch dashboards.
|
|
3876
|
+
*
|
|
3877
|
+
* The two reads run in parallel so the wall-time cost is one `git`
|
|
3878
|
+
* round-trip rather than two. Never throws — failures resolve to nulls so
|
|
3879
|
+
* the daemon hot path can rely on a value, not an exception.
|
|
3880
|
+
*/
|
|
3881
|
+
async getCurrentRepoState() {
|
|
3882
|
+
const branchPromise = this.git.raw(["symbolic-ref", "--short", "-q", "HEAD"]).then((s) => {
|
|
3883
|
+
const trimmed = s.trim();
|
|
3884
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
3885
|
+
}).catch(() => null);
|
|
3886
|
+
const commitShaPromise = this.git.raw(["rev-parse", "HEAD"]).then((s) => {
|
|
3887
|
+
const trimmed = s.trim().toLowerCase();
|
|
3888
|
+
return /^[0-9a-f]{40}$/.test(trimmed) ? trimmed : null;
|
|
3889
|
+
}).catch(() => null);
|
|
3890
|
+
const [branch, commitSha] = await Promise.all([
|
|
3891
|
+
branchPromise,
|
|
3892
|
+
commitShaPromise
|
|
3893
|
+
]);
|
|
3894
|
+
return { branch, commitSha };
|
|
3895
|
+
}
|
|
3848
3896
|
/**
|
|
3849
3897
|
* Gets both the current commit hash and current branch name
|
|
3850
3898
|
*/
|
|
@@ -8095,19 +8143,33 @@ var PromptItemZ = z27.object({
|
|
|
8095
8143
|
}).optional()
|
|
8096
8144
|
});
|
|
8097
8145
|
var PromptItemArrayZ = z27.array(PromptItemZ);
|
|
8098
|
-
|
|
8146
|
+
var NULL_REPO_STATE = {
|
|
8147
|
+
repositoryUrl: null,
|
|
8148
|
+
branch: null,
|
|
8149
|
+
commitSha: null
|
|
8150
|
+
};
|
|
8151
|
+
async function readRepoState(workingDir) {
|
|
8152
|
+
const dir = workingDir ?? process.cwd();
|
|
8153
|
+
let gitService;
|
|
8099
8154
|
try {
|
|
8100
|
-
|
|
8101
|
-
const isRepo = await gitService.isGitRepository();
|
|
8102
|
-
if (!isRepo) {
|
|
8103
|
-
return null;
|
|
8104
|
-
}
|
|
8105
|
-
const remoteUrl = await gitService.getRemoteUrl();
|
|
8106
|
-
const parsed = parseScmURL(remoteUrl);
|
|
8107
|
-
return parsed?.scmType && parsed.scmType !== "Unknown" ? remoteUrl : null;
|
|
8155
|
+
gitService = new GitService(dir);
|
|
8108
8156
|
} catch {
|
|
8109
|
-
return
|
|
8110
|
-
}
|
|
8157
|
+
return NULL_REPO_STATE;
|
|
8158
|
+
}
|
|
8159
|
+
const repoStatePromise = gitService.getCurrentRepoState().catch(() => ({ branch: null, commitSha: null }));
|
|
8160
|
+
const repositoryUrlPromise = gitService.getRemoteUrl().then((url) => {
|
|
8161
|
+
if (!url) return null;
|
|
8162
|
+
const parsed = parseScmURL(url);
|
|
8163
|
+
return parsed?.scmType && parsed.scmType !== "Unknown" ? url : null;
|
|
8164
|
+
}).catch(() => null);
|
|
8165
|
+
const [{ branch, commitSha }, repositoryUrl] = await Promise.all([
|
|
8166
|
+
repoStatePromise,
|
|
8167
|
+
repositoryUrlPromise
|
|
8168
|
+
]);
|
|
8169
|
+
return { repositoryUrl, branch, commitSha };
|
|
8170
|
+
}
|
|
8171
|
+
async function getRepositoryUrl(workingDir) {
|
|
8172
|
+
return (await readRepoState(workingDir)).repositoryUrl;
|
|
8111
8173
|
}
|
|
8112
8174
|
function getSystemInfo() {
|
|
8113
8175
|
let userName;
|
|
@@ -8389,6 +8451,7 @@ async function uploadAiBlameCommandHandler(args) {
|
|
|
8389
8451
|
export {
|
|
8390
8452
|
getRepositoryUrl,
|
|
8391
8453
|
getSystemInfo,
|
|
8454
|
+
readRepoState,
|
|
8392
8455
|
uploadAiBlameBuilder,
|
|
8393
8456
|
uploadAiBlameCommandHandler,
|
|
8394
8457
|
uploadAiBlameHandler,
|
package/dist/index.mjs
CHANGED
|
@@ -464,6 +464,9 @@ var init_client_generates = __esm({
|
|
|
464
464
|
... on FixData {
|
|
465
465
|
patch
|
|
466
466
|
patchOriginalEncodingBase64
|
|
467
|
+
questions {
|
|
468
|
+
name
|
|
469
|
+
}
|
|
467
470
|
extraContext {
|
|
468
471
|
extraContext {
|
|
469
472
|
key
|
|
@@ -1563,7 +1566,7 @@ var init_shared = __esm({
|
|
|
1563
1566
|
|
|
1564
1567
|
// src/features/analysis/scm/shared/src/types/fix.ts
|
|
1565
1568
|
import { z as z7 } from "zod";
|
|
1566
|
-
var PackageInfoZ, ManifestActionRequiredZ, ExtraContextInternalZ, FixExtraContextZ, PatchAndQuestionsZ, FixRatingZ, IssueSharedStateZ, FixSharedStateZ, FixQueryZ, FixPartsForFixScreenZ;
|
|
1569
|
+
var PackageInfoZ, ManifestActionRequiredZ, ExtraContextInternalZ, FixExtraContextZ, PatchAndQuestionsZ, FixRatingZ, IssueRatingZ, IssueSharedStateZ, FixSharedStateZ, FixQueryZ, FixPartsForFixScreenZ;
|
|
1567
1570
|
var init_fix = __esm({
|
|
1568
1571
|
"src/features/analysis/scm/shared/src/types/fix.ts"() {
|
|
1569
1572
|
"use strict";
|
|
@@ -1624,6 +1627,15 @@ var init_fix = __esm({
|
|
|
1624
1627
|
name: z7.string()
|
|
1625
1628
|
})
|
|
1626
1629
|
});
|
|
1630
|
+
IssueRatingZ = z7.object({
|
|
1631
|
+
voteScore: z7.number(),
|
|
1632
|
+
comment: z7.string().nullable().default(null),
|
|
1633
|
+
updatedDate: z7.string().nullable(),
|
|
1634
|
+
user: z7.object({
|
|
1635
|
+
email: z7.string(),
|
|
1636
|
+
name: z7.string()
|
|
1637
|
+
})
|
|
1638
|
+
});
|
|
1627
1639
|
IssueSharedStateZ = z7.object({
|
|
1628
1640
|
id: z7.string(),
|
|
1629
1641
|
createdAt: z7.string(),
|
|
@@ -1633,7 +1645,8 @@ var init_fix = __esm({
|
|
|
1633
1645
|
z7.object({
|
|
1634
1646
|
url: z7.string()
|
|
1635
1647
|
})
|
|
1636
|
-
)
|
|
1648
|
+
),
|
|
1649
|
+
issueRatings: z7.array(IssueRatingZ).default([])
|
|
1637
1650
|
}).nullable();
|
|
1638
1651
|
FixSharedStateZ = z7.object({
|
|
1639
1652
|
state: z7.nativeEnum(Fix_State_Enum),
|
|
@@ -1739,7 +1752,7 @@ var init_analysis = __esm({
|
|
|
1739
1752
|
|
|
1740
1753
|
// src/features/analysis/scm/shared/src/types/issue.ts
|
|
1741
1754
|
import { z as z9 } from "zod";
|
|
1742
|
-
var MAX_SOURCE_CODE_FILE_SIZE_IN_BYTES, VulnerabilityReportIssueSharedStateZ, BaseIssuePartsZ, FalsePositivePartsZ, IssuePartsWithFixZ, IssuePartsFpZ, GeneralIssueZ, IssuePartsZ, GetIssueIndexesZ, GetIssueScreenDataZ, IssueBucketZ, mapCategoryToBucket, mapBucketTypeToCategory;
|
|
1755
|
+
var MAX_SOURCE_CODE_FILE_SIZE_IN_BYTES, VulnerabilityReportIssueRatingZ, VulnerabilityReportIssueSharedStateZ, BaseIssuePartsZ, FalsePositivePartsZ, IssuePartsWithFixZ, IssuePartsFpZ, GeneralIssueZ, IssuePartsZ, GetIssueIndexesZ, GetIssueScreenDataZ, IssueBucketZ, mapCategoryToBucket, mapBucketTypeToCategory;
|
|
1743
1756
|
var init_issue = __esm({
|
|
1744
1757
|
"src/features/analysis/scm/shared/src/types/issue.ts"() {
|
|
1745
1758
|
"use strict";
|
|
@@ -1748,6 +1761,15 @@ var init_issue = __esm({
|
|
|
1748
1761
|
init_fix();
|
|
1749
1762
|
init_shared();
|
|
1750
1763
|
MAX_SOURCE_CODE_FILE_SIZE_IN_BYTES = 1e5;
|
|
1764
|
+
VulnerabilityReportIssueRatingZ = z9.object({
|
|
1765
|
+
voteScore: z9.number(),
|
|
1766
|
+
comment: z9.string().nullable().default(null),
|
|
1767
|
+
updatedDate: z9.string().nullable(),
|
|
1768
|
+
user: z9.object({
|
|
1769
|
+
email: z9.string(),
|
|
1770
|
+
name: z9.string()
|
|
1771
|
+
})
|
|
1772
|
+
});
|
|
1751
1773
|
VulnerabilityReportIssueSharedStateZ = z9.object({
|
|
1752
1774
|
id: z9.string().uuid(),
|
|
1753
1775
|
createdAt: z9.string(),
|
|
@@ -1757,7 +1779,8 @@ var init_issue = __esm({
|
|
|
1757
1779
|
z9.object({
|
|
1758
1780
|
url: z9.string()
|
|
1759
1781
|
})
|
|
1760
|
-
)
|
|
1782
|
+
),
|
|
1783
|
+
issueRatings: z9.array(VulnerabilityReportIssueRatingZ).default([])
|
|
1761
1784
|
}).nullish();
|
|
1762
1785
|
BaseIssuePartsZ = z9.object({
|
|
1763
1786
|
id: z9.string().uuid(),
|
|
@@ -3897,6 +3920,31 @@ var init_GitService = __esm({
|
|
|
3897
3920
|
throw new Error(errorMessage);
|
|
3898
3921
|
}
|
|
3899
3922
|
}
|
|
3923
|
+
/**
|
|
3924
|
+
* Reads `{ branch, commitSha }` for tracy event attribution. Detached-HEAD
|
|
3925
|
+
* (rebase, bisect, "open this commit") returns `branch: null` rather than
|
|
3926
|
+
* the literal string `"HEAD"` that `getCurrentBranch()` produces — that
|
|
3927
|
+
* literal would silently corrupt downstream branch dashboards.
|
|
3928
|
+
*
|
|
3929
|
+
* The two reads run in parallel so the wall-time cost is one `git`
|
|
3930
|
+
* round-trip rather than two. Never throws — failures resolve to nulls so
|
|
3931
|
+
* the daemon hot path can rely on a value, not an exception.
|
|
3932
|
+
*/
|
|
3933
|
+
async getCurrentRepoState() {
|
|
3934
|
+
const branchPromise = this.git.raw(["symbolic-ref", "--short", "-q", "HEAD"]).then((s) => {
|
|
3935
|
+
const trimmed = s.trim();
|
|
3936
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
3937
|
+
}).catch(() => null);
|
|
3938
|
+
const commitShaPromise = this.git.raw(["rev-parse", "HEAD"]).then((s) => {
|
|
3939
|
+
const trimmed = s.trim().toLowerCase();
|
|
3940
|
+
return /^[0-9a-f]{40}$/.test(trimmed) ? trimmed : null;
|
|
3941
|
+
}).catch(() => null);
|
|
3942
|
+
const [branch, commitSha] = await Promise.all([
|
|
3943
|
+
branchPromise,
|
|
3944
|
+
commitShaPromise
|
|
3945
|
+
]);
|
|
3946
|
+
return { branch, commitSha };
|
|
3947
|
+
}
|
|
3900
3948
|
/**
|
|
3901
3949
|
* Gets both the current commit hash and current branch name
|
|
3902
3950
|
*/
|
|
@@ -9260,6 +9308,52 @@ async function executeBatchGraphQL(octokit, owner, repo, config2) {
|
|
|
9260
9308
|
}
|
|
9261
9309
|
function getGithubSdk(params = {}) {
|
|
9262
9310
|
const octokit = getOctoKit(params);
|
|
9311
|
+
async function openPrWithFiles(params2) {
|
|
9312
|
+
const { owner, repo } = parseGithubOwnerAndRepo(params2.userRepoUrl);
|
|
9313
|
+
const { data: repository } = await octokit.rest.repos.get({ owner, repo });
|
|
9314
|
+
const defaultBranch = repository.default_branch;
|
|
9315
|
+
const baseSha = await octokit.rest.git.getRef({ owner, repo, ref: `heads/${defaultBranch}` }).then((r) => r.data.object.sha);
|
|
9316
|
+
await octokit.rest.git.createRef({
|
|
9317
|
+
owner,
|
|
9318
|
+
repo,
|
|
9319
|
+
ref: `refs/heads/${params2.branch}`,
|
|
9320
|
+
sha: baseSha
|
|
9321
|
+
});
|
|
9322
|
+
const tree = await octokit.rest.git.createTree({
|
|
9323
|
+
owner,
|
|
9324
|
+
repo,
|
|
9325
|
+
base_tree: baseSha,
|
|
9326
|
+
tree: params2.files.map((f) => ({
|
|
9327
|
+
path: f.path,
|
|
9328
|
+
mode: "100644",
|
|
9329
|
+
type: "blob",
|
|
9330
|
+
content: f.content
|
|
9331
|
+
}))
|
|
9332
|
+
});
|
|
9333
|
+
const commit = await octokit.rest.git.createCommit({
|
|
9334
|
+
owner,
|
|
9335
|
+
repo,
|
|
9336
|
+
message: params2.commitMessage ?? params2.title,
|
|
9337
|
+
tree: tree.data.sha,
|
|
9338
|
+
parents: [baseSha]
|
|
9339
|
+
});
|
|
9340
|
+
await octokit.rest.git.updateRef({
|
|
9341
|
+
owner,
|
|
9342
|
+
repo,
|
|
9343
|
+
ref: `heads/${params2.branch}`,
|
|
9344
|
+
sha: commit.data.sha
|
|
9345
|
+
});
|
|
9346
|
+
const pr = await octokit.rest.pulls.create({
|
|
9347
|
+
owner,
|
|
9348
|
+
repo,
|
|
9349
|
+
title: params2.title,
|
|
9350
|
+
head: params2.branch,
|
|
9351
|
+
...params2.headRepo ? { head_repo: params2.headRepo } : {},
|
|
9352
|
+
body: safeBody(params2.body, MAX_GH_PR_BODY_LENGTH),
|
|
9353
|
+
base: defaultBranch
|
|
9354
|
+
});
|
|
9355
|
+
return { pull_request_url: pr.data.html_url };
|
|
9356
|
+
}
|
|
9263
9357
|
return {
|
|
9264
9358
|
async postPrComment(params2) {
|
|
9265
9359
|
return octokit.request(POST_COMMENT_PATH, params2);
|
|
@@ -9556,86 +9650,26 @@ function getGithubSdk(params = {}) {
|
|
|
9556
9650
|
async createPr(params2) {
|
|
9557
9651
|
const { sourceRepoUrl, filesPaths, userRepoUrl, title, body } = params2;
|
|
9558
9652
|
const { owner: sourceOwner, repo: sourceRepo } = parseGithubOwnerAndRepo(sourceRepoUrl);
|
|
9559
|
-
const
|
|
9560
|
-
|
|
9561
|
-
|
|
9562
|
-
|
|
9563
|
-
|
|
9564
|
-
|
|
9565
|
-
|
|
9566
|
-
|
|
9567
|
-
|
|
9568
|
-
|
|
9569
|
-
|
|
9570
|
-
|
|
9571
|
-
|
|
9572
|
-
|
|
9573
|
-
|
|
9574
|
-
});
|
|
9575
|
-
const decodedContent = Buffer.from(
|
|
9576
|
-
// Check if file content exists and handle different response types
|
|
9577
|
-
typeof sourceFileContentResponse.data === "object" && !Array.isArray(sourceFileContentResponse.data) && "content" in sourceFileContentResponse.data && typeof sourceFileContentResponse.data.content === "string" ? sourceFileContentResponse.data.content : "",
|
|
9578
|
-
"base64"
|
|
9579
|
-
).toString("utf-8");
|
|
9580
|
-
const tree = [
|
|
9581
|
-
{
|
|
9582
|
-
path: sourceFilePath,
|
|
9583
|
-
mode: "100644",
|
|
9584
|
-
type: "blob",
|
|
9585
|
-
content: decodedContent
|
|
9586
|
-
}
|
|
9587
|
-
];
|
|
9588
|
-
if (secondFilePath) {
|
|
9589
|
-
const secondFileContentResponse = await octokit.rest.repos.getContent({
|
|
9590
|
-
owner: sourceOwner,
|
|
9591
|
-
repo: sourceRepo,
|
|
9592
|
-
path: `/${secondFilePath}`
|
|
9593
|
-
});
|
|
9594
|
-
const secondDecodedContent = Buffer.from(
|
|
9595
|
-
// Check if file content exists and handle different response types
|
|
9596
|
-
typeof secondFileContentResponse.data === "object" && !Array.isArray(secondFileContentResponse.data) && "content" in secondFileContentResponse.data && typeof secondFileContentResponse.data.content === "string" ? secondFileContentResponse.data.content : "",
|
|
9597
|
-
"base64"
|
|
9598
|
-
).toString("utf-8");
|
|
9599
|
-
tree.push({
|
|
9600
|
-
path: secondFilePath,
|
|
9601
|
-
mode: "100644",
|
|
9602
|
-
type: "blob",
|
|
9603
|
-
content: secondDecodedContent
|
|
9604
|
-
});
|
|
9605
|
-
}
|
|
9606
|
-
const createTreeResponse = await octokit.rest.git.createTree({
|
|
9607
|
-
owner,
|
|
9608
|
-
repo,
|
|
9609
|
-
base_tree: await octokit.rest.git.getRef({ owner, repo, ref: `heads/${defaultBranch}` }).then((response) => response.data.object.sha),
|
|
9610
|
-
tree
|
|
9611
|
-
});
|
|
9612
|
-
const createCommitResponse = await octokit.rest.git.createCommit({
|
|
9613
|
-
owner,
|
|
9614
|
-
repo,
|
|
9615
|
-
message: "Add new yaml file",
|
|
9616
|
-
tree: createTreeResponse.data.sha,
|
|
9617
|
-
parents: [
|
|
9618
|
-
await octokit.rest.git.getRef({ owner, repo, ref: `heads/${defaultBranch}` }).then((response) => response.data.object.sha)
|
|
9619
|
-
]
|
|
9620
|
-
});
|
|
9621
|
-
await octokit.rest.git.updateRef({
|
|
9622
|
-
owner,
|
|
9623
|
-
repo,
|
|
9624
|
-
ref: `heads/${newBranchName}`,
|
|
9625
|
-
sha: createCommitResponse.data.sha
|
|
9626
|
-
});
|
|
9627
|
-
const createPRResponse = await octokit.rest.pulls.create({
|
|
9628
|
-
owner,
|
|
9629
|
-
repo,
|
|
9653
|
+
const files = await Promise.all(
|
|
9654
|
+
filesPaths.map(async (filePath) => {
|
|
9655
|
+
const response = await octokit.rest.repos.getContent({
|
|
9656
|
+
owner: sourceOwner,
|
|
9657
|
+
repo: sourceRepo,
|
|
9658
|
+
path: `/${filePath}`
|
|
9659
|
+
});
|
|
9660
|
+
const content = typeof response.data === "object" && !Array.isArray(response.data) && "content" in response.data && typeof response.data.content === "string" ? Buffer.from(response.data.content, "base64").toString("utf-8") : "";
|
|
9661
|
+
return { path: filePath, content };
|
|
9662
|
+
})
|
|
9663
|
+
);
|
|
9664
|
+
return openPrWithFiles({
|
|
9665
|
+
userRepoUrl,
|
|
9666
|
+
files,
|
|
9667
|
+
branch: `mobb/workflow-${Date.now()}`,
|
|
9630
9668
|
title,
|
|
9631
|
-
|
|
9632
|
-
|
|
9633
|
-
|
|
9634
|
-
base: defaultBranch
|
|
9669
|
+
body,
|
|
9670
|
+
commitMessage: "Add new yaml file",
|
|
9671
|
+
headRepo: sourceRepo
|
|
9635
9672
|
});
|
|
9636
|
-
return {
|
|
9637
|
-
pull_request_url: createPRResponse.data.html_url
|
|
9638
|
-
};
|
|
9639
9673
|
},
|
|
9640
9674
|
async getGithubBranchList(repoUrl) {
|
|
9641
9675
|
const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
|
|
@@ -9646,6 +9680,35 @@ function getGithubSdk(params = {}) {
|
|
|
9646
9680
|
page: 1
|
|
9647
9681
|
});
|
|
9648
9682
|
},
|
|
9683
|
+
// T-500 — open a PR adding a single inline file. Used by the
|
|
9684
|
+
// openSecuritySkillPR resolver to deliver `.claude/skills/<slug>/SKILL.md`.
|
|
9685
|
+
async createPrWithContent(params2) {
|
|
9686
|
+
return openPrWithFiles({
|
|
9687
|
+
userRepoUrl: params2.userRepoUrl,
|
|
9688
|
+
files: [{ path: params2.filePath, content: params2.content }],
|
|
9689
|
+
branch: params2.branch,
|
|
9690
|
+
title: params2.title,
|
|
9691
|
+
body: params2.body
|
|
9692
|
+
});
|
|
9693
|
+
},
|
|
9694
|
+
// T-500 — best-effort branch cleanup for openSecuritySkillPR retry.
|
|
9695
|
+
// Swallows 422/404 so callers can call it unconditionally before
|
|
9696
|
+
// a fresh PR-creation attempt.
|
|
9697
|
+
async deleteBranchIfExists(params2) {
|
|
9698
|
+
const { owner, repo } = parseGithubOwnerAndRepo(params2.userRepoUrl);
|
|
9699
|
+
try {
|
|
9700
|
+
await octokit.rest.git.deleteRef({
|
|
9701
|
+
owner,
|
|
9702
|
+
repo,
|
|
9703
|
+
ref: `heads/${params2.branch}`
|
|
9704
|
+
});
|
|
9705
|
+
} catch (err) {
|
|
9706
|
+
if (err instanceof RequestError && (err.status === 422 || err.status === 404)) {
|
|
9707
|
+
return;
|
|
9708
|
+
}
|
|
9709
|
+
throw err;
|
|
9710
|
+
}
|
|
9711
|
+
},
|
|
9649
9712
|
async createPullRequest(options) {
|
|
9650
9713
|
const { owner, repo } = parseGithubOwnerAndRepo(options.repoUrl);
|
|
9651
9714
|
return octokit.rest.pulls.create({
|
|
@@ -10016,6 +10079,20 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
10016
10079
|
});
|
|
10017
10080
|
return { pull_request_url };
|
|
10018
10081
|
}
|
|
10082
|
+
// T-500 — sibling of `createPullRequestWithNewFile` that takes inline
|
|
10083
|
+
// content rather than reading from a source repo. Used by
|
|
10084
|
+
// openSecuritySkillPR to deliver `.claude/skills/<slug>/SKILL.md`.
|
|
10085
|
+
async createPullRequestWithInlineFile(params) {
|
|
10086
|
+
const { pull_request_url } = await this.githubSdk.createPrWithContent(params);
|
|
10087
|
+
return { pull_request_url };
|
|
10088
|
+
}
|
|
10089
|
+
// T-500 — used by the openSecuritySkillPR resolver to clean up a
|
|
10090
|
+
// branch left behind by a prior failed PR-creation attempt before
|
|
10091
|
+
// retrying. Swallows missing-branch responses; only real network
|
|
10092
|
+
// errors propagate.
|
|
10093
|
+
async deleteBranchIfExists(params) {
|
|
10094
|
+
return this.githubSdk.deleteBranchIfExists(params);
|
|
10095
|
+
}
|
|
10019
10096
|
async validateParams() {
|
|
10020
10097
|
return await githubValidateParams(this.url, this.accessToken);
|
|
10021
10098
|
}
|
|
@@ -14237,19 +14314,33 @@ var PromptItemZ = z27.object({
|
|
|
14237
14314
|
}).optional()
|
|
14238
14315
|
});
|
|
14239
14316
|
var PromptItemArrayZ = z27.array(PromptItemZ);
|
|
14240
|
-
|
|
14317
|
+
var NULL_REPO_STATE = {
|
|
14318
|
+
repositoryUrl: null,
|
|
14319
|
+
branch: null,
|
|
14320
|
+
commitSha: null
|
|
14321
|
+
};
|
|
14322
|
+
async function readRepoState(workingDir) {
|
|
14323
|
+
const dir = workingDir ?? process.cwd();
|
|
14324
|
+
let gitService;
|
|
14241
14325
|
try {
|
|
14242
|
-
|
|
14243
|
-
const isRepo = await gitService.isGitRepository();
|
|
14244
|
-
if (!isRepo) {
|
|
14245
|
-
return null;
|
|
14246
|
-
}
|
|
14247
|
-
const remoteUrl = await gitService.getRemoteUrl();
|
|
14248
|
-
const parsed = parseScmURL(remoteUrl);
|
|
14249
|
-
return parsed?.scmType && parsed.scmType !== "Unknown" ? remoteUrl : null;
|
|
14326
|
+
gitService = new GitService(dir);
|
|
14250
14327
|
} catch {
|
|
14251
|
-
return
|
|
14252
|
-
}
|
|
14328
|
+
return NULL_REPO_STATE;
|
|
14329
|
+
}
|
|
14330
|
+
const repoStatePromise = gitService.getCurrentRepoState().catch(() => ({ branch: null, commitSha: null }));
|
|
14331
|
+
const repositoryUrlPromise = gitService.getRemoteUrl().then((url) => {
|
|
14332
|
+
if (!url) return null;
|
|
14333
|
+
const parsed = parseScmURL(url);
|
|
14334
|
+
return parsed?.scmType && parsed.scmType !== "Unknown" ? url : null;
|
|
14335
|
+
}).catch(() => null);
|
|
14336
|
+
const [{ branch, commitSha }, repositoryUrl] = await Promise.all([
|
|
14337
|
+
repoStatePromise,
|
|
14338
|
+
repositoryUrlPromise
|
|
14339
|
+
]);
|
|
14340
|
+
return { repositoryUrl, branch, commitSha };
|
|
14341
|
+
}
|
|
14342
|
+
async function getRepositoryUrl(workingDir) {
|
|
14343
|
+
return (await readRepoState(workingDir)).repositoryUrl;
|
|
14253
14344
|
}
|
|
14254
14345
|
function getSystemInfo() {
|
|
14255
14346
|
let userName;
|
|
@@ -14582,7 +14673,7 @@ async function prepareAndSendTracyRecords(client, rawRecords, workingDir, option
|
|
|
14582
14673
|
const { computerName, userName } = getSystemInfo();
|
|
14583
14674
|
const defaultClientVersion = packageJson.version;
|
|
14584
14675
|
const shouldSanitize = options?.sanitize ?? true;
|
|
14585
|
-
const
|
|
14676
|
+
const defaults = workingDir != null ? await readRepoState(workingDir) : { repositoryUrl: null, branch: null, commitSha: null };
|
|
14586
14677
|
debug10(
|
|
14587
14678
|
"[step:sanitize] %s %d records",
|
|
14588
14679
|
shouldSanitize ? "Sanitizing" : "Serializing",
|
|
@@ -14602,7 +14693,9 @@ async function prepareAndSendTracyRecords(client, rawRecords, workingDir, option
|
|
|
14602
14693
|
const { rawData: _rawData, ...rest } = record;
|
|
14603
14694
|
results.push({
|
|
14604
14695
|
...rest,
|
|
14605
|
-
repositoryUrl: record.repositoryUrl ??
|
|
14696
|
+
repositoryUrl: record.repositoryUrl ?? defaults.repositoryUrl ?? void 0,
|
|
14697
|
+
branch: record.branch ?? defaults.branch ?? void 0,
|
|
14698
|
+
commitSha: record.commitSha ?? defaults.commitSha ?? void 0,
|
|
14606
14699
|
computerName,
|
|
14607
14700
|
userName,
|
|
14608
14701
|
clientVersion: record.clientVersion ?? defaultClientVersion
|
|
@@ -18740,6 +18833,8 @@ async function uploadContextRecords(opts) {
|
|
|
18740
18833
|
now,
|
|
18741
18834
|
platform: platform2,
|
|
18742
18835
|
repositoryUrl,
|
|
18836
|
+
branch,
|
|
18837
|
+
commitSha,
|
|
18743
18838
|
clientVersion,
|
|
18744
18839
|
onFileError,
|
|
18745
18840
|
onSkillError
|
|
@@ -18750,6 +18845,8 @@ async function uploadContextRecords(opts) {
|
|
|
18750
18845
|
const limit = pLimit7(UPLOAD_CONCURRENCY);
|
|
18751
18846
|
const extraFields = {
|
|
18752
18847
|
...repositoryUrl !== void 0 && { repositoryUrl },
|
|
18848
|
+
...branch !== void 0 && { branch },
|
|
18849
|
+
...commitSha !== void 0 && { commitSha },
|
|
18753
18850
|
...clientVersion !== void 0 && { clientVersion }
|
|
18754
18851
|
};
|
|
18755
18852
|
const tasks = [
|
|
@@ -18835,6 +18932,8 @@ async function runContextFileUploadPipeline(opts) {
|
|
|
18835
18932
|
uploadFieldsJSON,
|
|
18836
18933
|
keyPrefix,
|
|
18837
18934
|
repositoryUrl,
|
|
18935
|
+
branch,
|
|
18936
|
+
commitSha,
|
|
18838
18937
|
clientVersion,
|
|
18839
18938
|
submitRecords,
|
|
18840
18939
|
onFileError,
|
|
@@ -18857,6 +18956,8 @@ async function runContextFileUploadPipeline(opts) {
|
|
|
18857
18956
|
now,
|
|
18858
18957
|
platform: platform2,
|
|
18859
18958
|
repositoryUrl,
|
|
18959
|
+
branch,
|
|
18960
|
+
commitSha,
|
|
18860
18961
|
clientVersion,
|
|
18861
18962
|
onFileError,
|
|
18862
18963
|
onSkillError
|
|
@@ -19212,7 +19313,7 @@ function createLogger(config2) {
|
|
|
19212
19313
|
|
|
19213
19314
|
// src/features/claude_code/hook_logger.ts
|
|
19214
19315
|
var DD_RUM_TOKEN = true ? "pubf59c0182545bfb4c299175119f1abf9b" : "";
|
|
19215
|
-
var CLI_VERSION = true ? "1.4.
|
|
19316
|
+
var CLI_VERSION = true ? "1.4.11" : "unknown";
|
|
19216
19317
|
var NAMESPACE = "mobbdev-claude-code-hook-logs";
|
|
19217
19318
|
var claudeCodeVersion;
|
|
19218
19319
|
function buildDdTags() {
|
|
@@ -19679,6 +19780,7 @@ async function processTranscript(input, sessionStore, log2, maxEntries = DAEMON_
|
|
|
19679
19780
|
}
|
|
19680
19781
|
const cursorForModel = sessionStore.get(cursorKey);
|
|
19681
19782
|
let lastSeenModel = cursorForModel?.lastModel ?? null;
|
|
19783
|
+
const sampledRepoState = await readRepoState(input.cwd);
|
|
19682
19784
|
const records = entries.map((entry) => {
|
|
19683
19785
|
const { _recordId, ...rawEntry } = entry;
|
|
19684
19786
|
const message = rawEntry["message"];
|
|
@@ -19700,7 +19802,10 @@ async function processTranscript(input, sessionStore, log2, maxEntries = DAEMON_
|
|
|
19700
19802
|
recordId: _recordId,
|
|
19701
19803
|
recordTimestamp: entry.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
19702
19804
|
blameType: "CHAT" /* Chat */,
|
|
19703
|
-
rawData: rawEntry
|
|
19805
|
+
rawData: rawEntry,
|
|
19806
|
+
repositoryUrl: sampledRepoState.repositoryUrl ?? void 0,
|
|
19807
|
+
branch: sampledRepoState.branch,
|
|
19808
|
+
commitSha: sampledRepoState.commitSha
|
|
19704
19809
|
};
|
|
19705
19810
|
});
|
|
19706
19811
|
let totalRawDataBytes = 0;
|
|
@@ -20694,10 +20799,15 @@ var FixExtraContextResponseSchema = z33.object({
|
|
|
20694
20799
|
extraContext: z33.array(UnstructuredFixExtraContextSchema),
|
|
20695
20800
|
fixDescription: z33.string()
|
|
20696
20801
|
});
|
|
20802
|
+
var FixQuestionSchema = z33.object({
|
|
20803
|
+
__typename: z33.literal("FixQuestion").optional(),
|
|
20804
|
+
name: z33.string()
|
|
20805
|
+
});
|
|
20697
20806
|
var FixDataSchema = z33.object({
|
|
20698
20807
|
__typename: z33.literal("FixData"),
|
|
20699
20808
|
patch: z33.string(),
|
|
20700
20809
|
patchOriginalEncodingBase64: z33.string(),
|
|
20810
|
+
questions: z33.array(FixQuestionSchema),
|
|
20701
20811
|
extraContext: FixExtraContextResponseSchema
|
|
20702
20812
|
});
|
|
20703
20813
|
var GetFixNoFixErrorSchema = z33.object({
|
|
@@ -20789,6 +20899,48 @@ var GetLatestReportByRepoUrlResponseSchema = z33.object({
|
|
|
20789
20899
|
expiredReport: z33.array(ExpiredReportSchema)
|
|
20790
20900
|
});
|
|
20791
20901
|
|
|
20902
|
+
// src/mcp/services/InteractiveFixFilter.ts
|
|
20903
|
+
var isFilterDisabled = () => {
|
|
20904
|
+
const raw = process.env["MOBB_MCP_DISABLE_INTERACTIVE_FILTER"];
|
|
20905
|
+
return raw === "1" || raw === "true";
|
|
20906
|
+
};
|
|
20907
|
+
var isInteractiveFix = (fix) => {
|
|
20908
|
+
if (fix.patchAndQuestions.__typename !== "FixData") {
|
|
20909
|
+
return false;
|
|
20910
|
+
}
|
|
20911
|
+
return fix.patchAndQuestions.questions.length > 0;
|
|
20912
|
+
};
|
|
20913
|
+
var ruleIdFor = (fix) => fix.safeIssueType ?? "UNKNOWN";
|
|
20914
|
+
var countByRule = (ruleIds) => {
|
|
20915
|
+
const counts = {};
|
|
20916
|
+
for (const ruleId of ruleIds) {
|
|
20917
|
+
counts[ruleId] = (counts[ruleId] ?? 0) + 1;
|
|
20918
|
+
}
|
|
20919
|
+
return counts;
|
|
20920
|
+
};
|
|
20921
|
+
var partitionInteractiveFixes = (fixes) => {
|
|
20922
|
+
if (isFilterDisabled()) {
|
|
20923
|
+
return { applicableFixes: fixes, skippedRuleIds: [] };
|
|
20924
|
+
}
|
|
20925
|
+
const applicableFixes = [];
|
|
20926
|
+
const skippedRuleIds = [];
|
|
20927
|
+
for (const fix of fixes) {
|
|
20928
|
+
if (isInteractiveFix(fix)) {
|
|
20929
|
+
skippedRuleIds.push(ruleIdFor(fix));
|
|
20930
|
+
} else {
|
|
20931
|
+
applicableFixes.push(fix);
|
|
20932
|
+
}
|
|
20933
|
+
}
|
|
20934
|
+
if (skippedRuleIds.length > 0) {
|
|
20935
|
+
logInfo("[InteractiveFixFilter] Skipped interactive fixes", {
|
|
20936
|
+
totalFixes: fixes.length,
|
|
20937
|
+
skippedCount: skippedRuleIds.length,
|
|
20938
|
+
skippedByRule: countByRule(skippedRuleIds)
|
|
20939
|
+
});
|
|
20940
|
+
}
|
|
20941
|
+
return { applicableFixes, skippedRuleIds };
|
|
20942
|
+
};
|
|
20943
|
+
|
|
20792
20944
|
// src/mcp/services/McpGQLClient.ts
|
|
20793
20945
|
var McpGQLClient = class extends GQLClient {
|
|
20794
20946
|
constructor(args) {
|
|
@@ -21071,7 +21223,7 @@ var McpGQLClient = class extends GQLClient {
|
|
|
21071
21223
|
reportData,
|
|
21072
21224
|
limit
|
|
21073
21225
|
}) {
|
|
21074
|
-
if (!reportData) return [];
|
|
21226
|
+
if (!reportData) return { applicableFixes: [], skippedRuleIds: [] };
|
|
21075
21227
|
const reportMetadata = {
|
|
21076
21228
|
id: reportData.id,
|
|
21077
21229
|
organizationId: reportData.vulnerabilityReport?.project?.organizationId,
|
|
@@ -21107,7 +21259,12 @@ var McpGQLClient = class extends GQLClient {
|
|
|
21107
21259
|
fixMap.set(fix.id, fixWithUrl);
|
|
21108
21260
|
}
|
|
21109
21261
|
}
|
|
21110
|
-
|
|
21262
|
+
const merged = Array.from(fixMap.values());
|
|
21263
|
+
const { applicableFixes, skippedRuleIds } = partitionInteractiveFixes(merged);
|
|
21264
|
+
return {
|
|
21265
|
+
applicableFixes: applicableFixes.slice(0, limit),
|
|
21266
|
+
skippedRuleIds
|
|
21267
|
+
};
|
|
21111
21268
|
}
|
|
21112
21269
|
async updateFixesDownloadStatus(fixIds) {
|
|
21113
21270
|
if (fixIds.length > 0) {
|
|
@@ -21211,14 +21368,15 @@ var McpGQLClient = class extends GQLClient {
|
|
|
21211
21368
|
reportCount: resp.fixReport?.length || 0
|
|
21212
21369
|
});
|
|
21213
21370
|
const latestReport = resp.fixReport?.[0] && FixReportSummarySchema.parse(resp.fixReport?.[0]);
|
|
21214
|
-
const
|
|
21371
|
+
const { applicableFixes, skippedRuleIds } = this.mergeUserAndSystemFixes({
|
|
21215
21372
|
reportData: latestReport,
|
|
21216
21373
|
limit
|
|
21217
21374
|
});
|
|
21218
21375
|
return {
|
|
21219
21376
|
fixReport: latestReport ? {
|
|
21220
21377
|
...latestReport,
|
|
21221
|
-
fixes
|
|
21378
|
+
fixes: applicableFixes,
|
|
21379
|
+
skippedRuleIds
|
|
21222
21380
|
} : null,
|
|
21223
21381
|
expiredReport: resp.expiredReport?.[0] || null
|
|
21224
21382
|
};
|
|
@@ -21288,13 +21446,17 @@ var McpGQLClient = class extends GQLClient {
|
|
|
21288
21446
|
return null;
|
|
21289
21447
|
}
|
|
21290
21448
|
const latestReport = FixReportSummarySchema.parse(res.fixReport?.[0]);
|
|
21291
|
-
const
|
|
21449
|
+
const { applicableFixes, skippedRuleIds } = this.mergeUserAndSystemFixes({
|
|
21292
21450
|
reportData: latestReport,
|
|
21293
21451
|
limit
|
|
21294
21452
|
});
|
|
21295
|
-
logDebug("[GraphQL] GetReportFixes response parsed", {
|
|
21453
|
+
logDebug("[GraphQL] GetReportFixes response parsed", {
|
|
21454
|
+
fixes: applicableFixes,
|
|
21455
|
+
skippedCount: skippedRuleIds.length
|
|
21456
|
+
});
|
|
21296
21457
|
return {
|
|
21297
|
-
fixes,
|
|
21458
|
+
fixes: applicableFixes,
|
|
21459
|
+
skippedRuleIds,
|
|
21298
21460
|
totalCount: res.fixReport?.[0]?.filteredFixesCount?.aggregate?.count || 0,
|
|
21299
21461
|
expiredReport: res.expiredReport?.[0] || null,
|
|
21300
21462
|
fixReport: res.fixReport?.[0] ? {
|
|
@@ -24362,6 +24524,17 @@ function friendlyType(s) {
|
|
|
24362
24524
|
}
|
|
24363
24525
|
var noFixesReturnedForParameters = `No fixes returned for the given offset and limit parameters.
|
|
24364
24526
|
`;
|
|
24527
|
+
var skippedInteractiveFixesNotice = (skippedCount) => {
|
|
24528
|
+
if (skippedCount <= 0) return "";
|
|
24529
|
+
const s = skippedCount === 1 ? "" : "es";
|
|
24530
|
+
const verb = skippedCount === 1 ? "requires" : "require";
|
|
24531
|
+
const wasWere = skippedCount === 1 ? "was" : "were";
|
|
24532
|
+
return `
|
|
24533
|
+
## Skipped fixes
|
|
24534
|
+
|
|
24535
|
+
${skippedCount} fix${s} ${verb} user input that is not available over MCP and ${wasWere} skipped. Mention this to the user when summarizing results.
|
|
24536
|
+
`;
|
|
24537
|
+
};
|
|
24365
24538
|
var noFixesReturnedForParametersWithGuidance = ({
|
|
24366
24539
|
offset,
|
|
24367
24540
|
limit,
|
|
@@ -24608,11 +24781,12 @@ var fixesFoundPrompt = ({
|
|
|
24608
24781
|
fixReport,
|
|
24609
24782
|
offset,
|
|
24610
24783
|
limit,
|
|
24611
|
-
gqlClient
|
|
24784
|
+
gqlClient,
|
|
24785
|
+
skippedInteractiveCount = 0
|
|
24612
24786
|
}) => {
|
|
24613
24787
|
const totalFixes = fixReport.filteredFixesCount.aggregate?.count || 0;
|
|
24614
24788
|
if (totalFixes === 0) {
|
|
24615
|
-
return noFixesAvailablePrompt;
|
|
24789
|
+
return noFixesAvailablePrompt + skippedInteractiveFixesNotice(skippedInteractiveCount);
|
|
24616
24790
|
}
|
|
24617
24791
|
const criticalFixes = fixReport.CRITICAL?.aggregate?.count || 0;
|
|
24618
24792
|
const highFixes = fixReport.HIGH?.aggregate?.count || 0;
|
|
@@ -24655,7 +24829,7 @@ ${applyFixesPrompt({
|
|
|
24655
24829
|
offset,
|
|
24656
24830
|
limit,
|
|
24657
24831
|
gqlClient
|
|
24658
|
-
})}`;
|
|
24832
|
+
})}${skippedInteractiveFixesNotice(skippedInteractiveCount)}`;
|
|
24659
24833
|
};
|
|
24660
24834
|
var nextStepsPrompt = ({ scannedFiles }) => `
|
|
24661
24835
|
### \u{1F4C1} Scanned Files
|
|
@@ -24701,10 +24875,11 @@ var fixesPrompt = ({
|
|
|
24701
24875
|
offset,
|
|
24702
24876
|
scannedFiles,
|
|
24703
24877
|
limit,
|
|
24704
|
-
gqlClient
|
|
24878
|
+
gqlClient,
|
|
24879
|
+
skippedInteractiveCount = 0
|
|
24705
24880
|
}) => {
|
|
24706
24881
|
if (totalCount === 0) {
|
|
24707
|
-
return noFixesFoundPrompt({ scannedFiles });
|
|
24882
|
+
return noFixesFoundPrompt({ scannedFiles }) + skippedInteractiveFixesNotice(skippedInteractiveCount);
|
|
24708
24883
|
}
|
|
24709
24884
|
const shownCount = fixes.length;
|
|
24710
24885
|
const nextOffset = offset + shownCount;
|
|
@@ -24722,7 +24897,7 @@ ${applyFixesPrompt({
|
|
|
24722
24897
|
limit,
|
|
24723
24898
|
gqlClient
|
|
24724
24899
|
})}
|
|
24725
|
-
|
|
24900
|
+
${skippedInteractiveFixesNotice(skippedInteractiveCount)}
|
|
24726
24901
|
${nextStepsPrompt({ scannedFiles })}
|
|
24727
24902
|
`;
|
|
24728
24903
|
};
|
|
@@ -24795,7 +24970,8 @@ For assistance:
|
|
|
24795
24970
|
var freshFixesPrompt = ({
|
|
24796
24971
|
fixes,
|
|
24797
24972
|
limit,
|
|
24798
|
-
gqlClient
|
|
24973
|
+
gqlClient,
|
|
24974
|
+
skippedInteractiveCount = 0
|
|
24799
24975
|
}) => {
|
|
24800
24976
|
return `Here are the fresh fixes to the vulnerabilities discovered by Mobb MCP
|
|
24801
24977
|
|
|
@@ -24810,6 +24986,7 @@ ${applyFixesPrompt({
|
|
|
24810
24986
|
limit,
|
|
24811
24987
|
gqlClient
|
|
24812
24988
|
})}
|
|
24989
|
+
${skippedInteractiveFixesNotice(skippedInteractiveCount)}
|
|
24813
24990
|
`;
|
|
24814
24991
|
};
|
|
24815
24992
|
function extractTargetFileFromPatch(patch) {
|
|
@@ -24828,7 +25005,8 @@ function formatSeverity(severityText, severityValue) {
|
|
|
24828
25005
|
}
|
|
24829
25006
|
var appliedFixesSummaryPrompt = ({
|
|
24830
25007
|
fixes,
|
|
24831
|
-
gqlClient
|
|
25008
|
+
gqlClient,
|
|
25009
|
+
skippedInteractiveCount = 0
|
|
24832
25010
|
}) => {
|
|
24833
25011
|
const fixIds = fixes.map((fix) => fix.id);
|
|
24834
25012
|
void gqlClient.updateFixesDownloadStatus(fixIds);
|
|
@@ -24863,11 +25041,11 @@ ${fixes.map((fix, index) => {
|
|
|
24863
25041
|
${continuousMonitoringSection}
|
|
24864
25042
|
|
|
24865
25043
|
${autoFixSettingsSection}
|
|
24866
|
-
|
|
25044
|
+
${skippedInteractiveFixesNotice(skippedInteractiveCount)}
|
|
24867
25045
|
## \u{1F4CB} Next Steps
|
|
24868
25046
|
|
|
24869
25047
|
1. **Review the changes** - Check the modified files to understand what was fixed
|
|
24870
|
-
2. **Test your application** - Ensure the fixes don't break existing functionality
|
|
25048
|
+
2. **Test your application** - Ensure the fixes don't break existing functionality
|
|
24871
25049
|
3. **Commit the changes** - Add and commit the security fixes to your repository
|
|
24872
25050
|
4. **Continue coding** - Mobb will keep protecting your code automatically
|
|
24873
25051
|
|
|
@@ -27841,7 +28019,8 @@ var _FetchAvailableFixesService = class _FetchAvailableFixesService {
|
|
|
27841
28019
|
fixReport,
|
|
27842
28020
|
offset: effectiveOffset,
|
|
27843
28021
|
limit,
|
|
27844
|
-
gqlClient
|
|
28022
|
+
gqlClient,
|
|
28023
|
+
skippedInteractiveCount: fixReport.skippedRuleIds?.length ?? 0
|
|
27845
28024
|
});
|
|
27846
28025
|
this.currentOffset = effectiveOffset + (fixReport.fixes?.length || 0);
|
|
27847
28026
|
return prompt;
|
|
@@ -28176,7 +28355,8 @@ var _ScanAndFixVulnerabilitiesService = class _ScanAndFixVulnerabilitiesService
|
|
|
28176
28355
|
offset: effectiveOffset,
|
|
28177
28356
|
scannedFiles: [...fileList],
|
|
28178
28357
|
limit: effectiveLimit,
|
|
28179
|
-
gqlClient: this.gqlClient
|
|
28358
|
+
gqlClient: this.gqlClient,
|
|
28359
|
+
skippedInteractiveCount: fixes.skippedRuleIds.length
|
|
28180
28360
|
});
|
|
28181
28361
|
this.currentOffset = effectiveOffset + (fixes.fixes?.length || 0);
|
|
28182
28362
|
return prompt;
|
|
@@ -28220,7 +28400,8 @@ var _ScanAndFixVulnerabilitiesService = class _ScanAndFixVulnerabilitiesService
|
|
|
28220
28400
|
logDebug(`${fixes?.fixes?.length} fixes retrieved`);
|
|
28221
28401
|
return {
|
|
28222
28402
|
fixes: fixes?.fixes || [],
|
|
28223
|
-
totalCount: fixes?.totalCount || 0
|
|
28403
|
+
totalCount: fixes?.totalCount || 0,
|
|
28404
|
+
skippedRuleIds: fixes?.skippedRuleIds || []
|
|
28224
28405
|
};
|
|
28225
28406
|
}
|
|
28226
28407
|
};
|