mobbdev 1.4.0 → 1.4.1
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 +40 -40
- package/dist/args/commands/upload_ai_blame.mjs +37 -4
- package/dist/index.mjs +451 -209
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -263,10 +263,12 @@ var init_client_generates = __esm({
|
|
|
263
263
|
IssueType_Enum2["ImproperExceptionHandling"] = "IMPROPER_EXCEPTION_HANDLING";
|
|
264
264
|
IssueType_Enum2["ImproperResourceShutdownOrRelease"] = "IMPROPER_RESOURCE_SHUTDOWN_OR_RELEASE";
|
|
265
265
|
IssueType_Enum2["ImproperStringFormatting"] = "IMPROPER_STRING_FORMATTING";
|
|
266
|
+
IssueType_Enum2["ImproperValidationOfArrayIndex"] = "IMPROPER_VALIDATION_OF_ARRAY_INDEX";
|
|
266
267
|
IssueType_Enum2["IncompleteHostnameRegex"] = "INCOMPLETE_HOSTNAME_REGEX";
|
|
267
268
|
IssueType_Enum2["IncompleteSanitization"] = "INCOMPLETE_SANITIZATION";
|
|
268
269
|
IssueType_Enum2["IncompleteUrlSanitization"] = "INCOMPLETE_URL_SANITIZATION";
|
|
269
270
|
IssueType_Enum2["IncompleteUrlSchemeCheck"] = "INCOMPLETE_URL_SCHEME_CHECK";
|
|
271
|
+
IssueType_Enum2["IncorrectIntegerConversion"] = "INCORRECT_INTEGER_CONVERSION";
|
|
270
272
|
IssueType_Enum2["IncorrectSqlApiUsage"] = "INCORRECT_SQL_API_USAGE";
|
|
271
273
|
IssueType_Enum2["InformationExposureViaHeaders"] = "INFORMATION_EXPOSURE_VIA_HEADERS";
|
|
272
274
|
IssueType_Enum2["InsecureBinderConfiguration"] = "INSECURE_BINDER_CONFIGURATION";
|
|
@@ -291,6 +293,7 @@ var init_client_generates = __esm({
|
|
|
291
293
|
IssueType_Enum2["MissingUser"] = "MISSING_USER";
|
|
292
294
|
IssueType_Enum2["MissingWhitespace"] = "MISSING_WHITESPACE";
|
|
293
295
|
IssueType_Enum2["MissingWorkflowPermissions"] = "MISSING_WORKFLOW_PERMISSIONS";
|
|
296
|
+
IssueType_Enum2["MissingXFrameOptions"] = "MISSING_X_FRAME_OPTIONS";
|
|
294
297
|
IssueType_Enum2["ModifiedDefaultParam"] = "MODIFIED_DEFAULT_PARAM";
|
|
295
298
|
IssueType_Enum2["NonFinalPublicStaticField"] = "NON_FINAL_PUBLIC_STATIC_FIELD";
|
|
296
299
|
IssueType_Enum2["NonReadonlyField"] = "NON_READONLY_FIELD";
|
|
@@ -408,6 +411,7 @@ var init_client_generates = __esm({
|
|
|
408
411
|
return Vulnerability_Report_Issue_Tag_Enum3;
|
|
409
412
|
})(Vulnerability_Report_Issue_Tag_Enum || {});
|
|
410
413
|
Vulnerability_Report_Vendor_Enum = /* @__PURE__ */ ((Vulnerability_Report_Vendor_Enum3) => {
|
|
414
|
+
Vulnerability_Report_Vendor_Enum3["BlackDuck"] = "blackDuck";
|
|
411
415
|
Vulnerability_Report_Vendor_Enum3["Checkmarx"] = "checkmarx";
|
|
412
416
|
Vulnerability_Report_Vendor_Enum3["CheckmarxXml"] = "checkmarxXml";
|
|
413
417
|
Vulnerability_Report_Vendor_Enum3["Codeql"] = "codeql";
|
|
@@ -1467,7 +1471,10 @@ var init_getIssueType = __esm({
|
|
|
1467
1471
|
["REDUNDANT_NIL_ERROR_CHECK" /* RedundantNilErrorCheck */]: "Redundant Nil Error Check",
|
|
1468
1472
|
["MISSING_WORKFLOW_PERMISSIONS" /* MissingWorkflowPermissions */]: "Missing Workflow Permissions",
|
|
1469
1473
|
["EXCESSIVE_SECRETS_EXPOSURE" /* ExcessiveSecretsExposure */]: "Excessive Secrets Exposure",
|
|
1470
|
-
["TAINTED_NUMERIC_CAST" /* TaintedNumericCast */]: "Tainted Numeric Cast"
|
|
1474
|
+
["TAINTED_NUMERIC_CAST" /* TaintedNumericCast */]: "Tainted Numeric Cast",
|
|
1475
|
+
["MISSING_X_FRAME_OPTIONS" /* MissingXFrameOptions */]: "Missing X-Frame-Options Header",
|
|
1476
|
+
["IMPROPER_VALIDATION_OF_ARRAY_INDEX" /* ImproperValidationOfArrayIndex */]: "Improper Validation of Array Index",
|
|
1477
|
+
["INCORRECT_INTEGER_CONVERSION" /* IncorrectIntegerConversion */]: "Incorrect Integer Conversion"
|
|
1471
1478
|
};
|
|
1472
1479
|
issueTypeZ = z.nativeEnum(IssueType_Enum);
|
|
1473
1480
|
getIssueTypeFriendlyString = (issueType) => {
|
|
@@ -4660,7 +4667,10 @@ var fixDetailsData = {
|
|
|
4660
4667
|
["REDUNDANT_NIL_ERROR_CHECK" /* RedundantNilErrorCheck */]: void 0,
|
|
4661
4668
|
["MISSING_WORKFLOW_PERMISSIONS" /* MissingWorkflowPermissions */]: void 0,
|
|
4662
4669
|
["EXCESSIVE_SECRETS_EXPOSURE" /* ExcessiveSecretsExposure */]: void 0,
|
|
4663
|
-
["TAINTED_NUMERIC_CAST" /* TaintedNumericCast */]: void 0
|
|
4670
|
+
["TAINTED_NUMERIC_CAST" /* TaintedNumericCast */]: void 0,
|
|
4671
|
+
["MISSING_X_FRAME_OPTIONS" /* MissingXFrameOptions */]: void 0,
|
|
4672
|
+
["IMPROPER_VALIDATION_OF_ARRAY_INDEX" /* ImproperValidationOfArrayIndex */]: void 0,
|
|
4673
|
+
["INCORRECT_INTEGER_CONVERSION" /* IncorrectIntegerConversion */]: void 0
|
|
4664
4674
|
};
|
|
4665
4675
|
|
|
4666
4676
|
// src/features/analysis/scm/shared/src/commitDescriptionMarkup.ts
|
|
@@ -5997,6 +6007,19 @@ var headerMaxAge = {
|
|
|
5997
6007
|
}
|
|
5998
6008
|
};
|
|
5999
6009
|
|
|
6010
|
+
// src/features/analysis/scm/shared/src/storedQuestionData/js/missingXFrameOptions.ts
|
|
6011
|
+
var xFrameOptionsValue = {
|
|
6012
|
+
xFrameOptionsValue: {
|
|
6013
|
+
content: () => "Please provide the value for the X-Frame-Options header",
|
|
6014
|
+
description: () => `The \`X-Frame-Options\` HTTP response header tells the browser whether the page is allowed to be rendered inside a \`<frame>\`, \`<iframe>\`, \`<embed>\` or \`<object>\`. Without it, attackers can embed your application in an invisible iframe and trick users into clicking on it \u2014 a class of attacks known as clickjacking (UI redressing).
|
|
6015
|
+
|
|
6016
|
+
**Allowed values:**
|
|
6017
|
+
- \`DENY\` \u2014 the page cannot be framed by any site, including your own. Recommended default for any page that does not need to be embedded.
|
|
6018
|
+
- \`SAMEORIGIN\` \u2014 the page can only be framed by pages served from the same origin. Use this only if your own application legitimately embeds this page in an iframe.`,
|
|
6019
|
+
guidance: () => ``
|
|
6020
|
+
}
|
|
6021
|
+
};
|
|
6022
|
+
|
|
6000
6023
|
// src/features/analysis/scm/shared/src/storedQuestionData/js/noLimitsOrThrottling.ts
|
|
6001
6024
|
var noLimitsOrThrottling2 = {
|
|
6002
6025
|
setGlobalLimiter: {
|
|
@@ -6141,6 +6164,7 @@ var vulnerabilities13 = {
|
|
|
6141
6164
|
["UNCHECKED_LOOP_CONDITION" /* UncheckedLoopCondition */]: uncheckedLoopCondition2,
|
|
6142
6165
|
["NO_LIMITS_OR_THROTTLING" /* NoLimitsOrThrottling */]: noLimitsOrThrottling2,
|
|
6143
6166
|
["MISSING_CSP_HEADER" /* MissingCspHeader */]: cspHeaderValue,
|
|
6167
|
+
["MISSING_X_FRAME_OPTIONS" /* MissingXFrameOptions */]: xFrameOptionsValue,
|
|
6144
6168
|
["HARDCODED_DOMAIN_IN_HTML" /* HardcodedDomainInHtml */]: hardcodedDomainInHtml,
|
|
6145
6169
|
["CSRF" /* Csrf */]: csrf2
|
|
6146
6170
|
};
|
|
@@ -6461,6 +6485,13 @@ var ReferenceType = /* @__PURE__ */ ((ReferenceType2) => {
|
|
|
6461
6485
|
ReferenceType2["TAG"] = "TAG";
|
|
6462
6486
|
return ReferenceType2;
|
|
6463
6487
|
})(ReferenceType || {});
|
|
6488
|
+
var GithubFullShaZ = z13.string().regex(/^[a-f0-9]{40}$/);
|
|
6489
|
+
var MergedPrSurvivalMetadataZ = z13.object({
|
|
6490
|
+
mergeCommitShas: z13.array(GithubFullShaZ).min(1).refine((shas) => new Set(shas).size === shas.length, {
|
|
6491
|
+
message: "mergeCommitShas must contain unique SHAs"
|
|
6492
|
+
}),
|
|
6493
|
+
targetBranch: z13.string().min(1)
|
|
6494
|
+
});
|
|
6464
6495
|
var ScmLibScmType = /* @__PURE__ */ ((ScmLibScmType2) => {
|
|
6465
6496
|
ScmLibScmType2["GITHUB"] = "GITHUB";
|
|
6466
6497
|
ScmLibScmType2["GITLAB"] = "GITLAB";
|
|
@@ -7147,7 +7178,7 @@ async function getAdoSdk(params) {
|
|
|
7147
7178
|
const url = new URL(repoUrl);
|
|
7148
7179
|
const origin = url.origin.toLowerCase().endsWith(".visualstudio.com") ? DEFUALT_ADO_ORIGIN : url.origin.toLowerCase();
|
|
7149
7180
|
const params2 = `path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=commit&versionDescriptor[version]=${branch}&resolveLfs=true&$format=zip&api-version=5.0&download=true`;
|
|
7150
|
-
const
|
|
7181
|
+
const path35 = [
|
|
7151
7182
|
prefixPath,
|
|
7152
7183
|
owner,
|
|
7153
7184
|
projectName,
|
|
@@ -7158,7 +7189,7 @@ async function getAdoSdk(params) {
|
|
|
7158
7189
|
"items",
|
|
7159
7190
|
"items"
|
|
7160
7191
|
].filter(Boolean).join("/");
|
|
7161
|
-
return new URL(`${
|
|
7192
|
+
return new URL(`${path35}?${params2}`, origin).toString();
|
|
7162
7193
|
},
|
|
7163
7194
|
async getAdoBranchList({ repoUrl }) {
|
|
7164
7195
|
try {
|
|
@@ -7247,8 +7278,8 @@ async function getAdoSdk(params) {
|
|
|
7247
7278
|
const changeType = entry.changeType;
|
|
7248
7279
|
return changeType !== 16 && entry.item?.path;
|
|
7249
7280
|
}).map((entry) => {
|
|
7250
|
-
const
|
|
7251
|
-
return
|
|
7281
|
+
const path35 = entry.item.path;
|
|
7282
|
+
return path35.startsWith("/") ? path35.slice(1) : path35;
|
|
7252
7283
|
});
|
|
7253
7284
|
},
|
|
7254
7285
|
async searchAdoPullRequests({
|
|
@@ -7649,6 +7680,12 @@ var SCMLib = class {
|
|
|
7649
7680
|
async getPrDataBatch(_repoUrl, _prNumbers) {
|
|
7650
7681
|
throw new Error("getPrDataBatch not implemented for this SCM provider");
|
|
7651
7682
|
}
|
|
7683
|
+
/**
|
|
7684
|
+
* GitHub: merge detection for main-branch survival. Other providers return null.
|
|
7685
|
+
*/
|
|
7686
|
+
async getMergedPrSurvivalMetadata(_prNumber) {
|
|
7687
|
+
return null;
|
|
7688
|
+
}
|
|
7652
7689
|
getAccessToken() {
|
|
7653
7690
|
return this.accessToken || "";
|
|
7654
7691
|
}
|
|
@@ -8910,6 +8947,24 @@ async function encryptSecret(secret, key) {
|
|
|
8910
8947
|
return sodium.to_base64(encBytes, sodium.base64_variants.ORIGINAL);
|
|
8911
8948
|
}
|
|
8912
8949
|
|
|
8950
|
+
// src/features/analysis/scm/github/utils/mergeCommitShas.ts
|
|
8951
|
+
async function commitShasBetweenBaseAndMerge(githubSdk, args) {
|
|
8952
|
+
let compare;
|
|
8953
|
+
try {
|
|
8954
|
+
compare = await githubSdk.compareCommitsBasehead({
|
|
8955
|
+
owner: args.owner,
|
|
8956
|
+
repo: args.repo,
|
|
8957
|
+
basehead: `${args.baseSha}...${args.mergeCommitSha}`
|
|
8958
|
+
});
|
|
8959
|
+
} catch (err) {
|
|
8960
|
+
throw new Error(
|
|
8961
|
+
`Failed to compare commits ${args.baseSha}...${args.mergeCommitSha}: ${err instanceof Error ? err.message : String(err)}`
|
|
8962
|
+
);
|
|
8963
|
+
}
|
|
8964
|
+
const shas = compare.data.commits.map((c) => c.sha);
|
|
8965
|
+
return shas.length > 0 ? shas : [args.mergeCommitSha];
|
|
8966
|
+
}
|
|
8967
|
+
|
|
8913
8968
|
// src/features/analysis/scm/github/utils/utils.ts
|
|
8914
8969
|
import { Octokit } from "octokit";
|
|
8915
8970
|
import { fetch as fetch2, ProxyAgent } from "undici";
|
|
@@ -9642,6 +9697,12 @@ function getGithubSdk(params = {}) {
|
|
|
9642
9697
|
);
|
|
9643
9698
|
return res;
|
|
9644
9699
|
},
|
|
9700
|
+
async listPullRequestCommits(params2) {
|
|
9701
|
+
return octokit.rest.pulls.listCommits(params2);
|
|
9702
|
+
},
|
|
9703
|
+
async compareCommitsBasehead(params2) {
|
|
9704
|
+
return octokit.rest.repos.compareCommitsWithBasehead(params2);
|
|
9705
|
+
},
|
|
9645
9706
|
/**
|
|
9646
9707
|
* List PRs using GitHub's REST `/repos/{owner}/{repo}/pulls` endpoint.
|
|
9647
9708
|
* https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#list-pull-requests
|
|
@@ -10456,6 +10517,34 @@ var GithubSCMLib = class extends SCMLib {
|
|
|
10456
10517
|
commentIds
|
|
10457
10518
|
};
|
|
10458
10519
|
}
|
|
10520
|
+
/**
|
|
10521
|
+
* Detect merge strategy and SHAs on the target branch for main-branch survival (GitHub only).
|
|
10522
|
+
*/
|
|
10523
|
+
async getMergedPrSurvivalMetadata(prNumber) {
|
|
10524
|
+
this._validateAccessTokenAndUrl();
|
|
10525
|
+
const { owner, repo } = parseGithubOwnerAndRepo(this.url);
|
|
10526
|
+
const pr = await this.githubSdk.getPr({
|
|
10527
|
+
owner,
|
|
10528
|
+
repo,
|
|
10529
|
+
pull_number: prNumber
|
|
10530
|
+
});
|
|
10531
|
+
if (pr.data.merged !== true || !pr.data.merge_commit_sha) {
|
|
10532
|
+
return null;
|
|
10533
|
+
}
|
|
10534
|
+
const mergeCommitSha = pr.data.merge_commit_sha;
|
|
10535
|
+
const targetBranch = pr.data.base.ref;
|
|
10536
|
+
const baseSha = pr.data.base.sha;
|
|
10537
|
+
const mergeCommitShas = await commitShasBetweenBaseAndMerge(
|
|
10538
|
+
this.githubSdk,
|
|
10539
|
+
{
|
|
10540
|
+
owner,
|
|
10541
|
+
repo,
|
|
10542
|
+
baseSha,
|
|
10543
|
+
mergeCommitSha
|
|
10544
|
+
}
|
|
10545
|
+
);
|
|
10546
|
+
return { mergeCommitShas, targetBranch };
|
|
10547
|
+
}
|
|
10459
10548
|
};
|
|
10460
10549
|
|
|
10461
10550
|
// src/features/analysis/scm/gitlab/gitlab.ts
|
|
@@ -12462,7 +12551,8 @@ var SCANNERS = {
|
|
|
12462
12551
|
Snyk: "snyk",
|
|
12463
12552
|
Sonarqube: "sonarqube",
|
|
12464
12553
|
Semgrep: "semgrep",
|
|
12465
|
-
Datadog: "datadog"
|
|
12554
|
+
Datadog: "datadog",
|
|
12555
|
+
BlackDuck: "blackduck"
|
|
12466
12556
|
};
|
|
12467
12557
|
var scannerToVulnerabilityReportVendorEnum = {
|
|
12468
12558
|
[SCANNERS.Checkmarx]: "checkmarx" /* Checkmarx */,
|
|
@@ -12471,7 +12561,8 @@ var scannerToVulnerabilityReportVendorEnum = {
|
|
|
12471
12561
|
[SCANNERS.Codeql]: "codeql" /* Codeql */,
|
|
12472
12562
|
[SCANNERS.Fortify]: "fortify" /* Fortify */,
|
|
12473
12563
|
[SCANNERS.Semgrep]: "semgrep" /* Semgrep */,
|
|
12474
|
-
[SCANNERS.Datadog]: "datadog" /* Datadog
|
|
12564
|
+
[SCANNERS.Datadog]: "datadog" /* Datadog */,
|
|
12565
|
+
[SCANNERS.BlackDuck]: "blackDuck" /* BlackDuck */
|
|
12475
12566
|
};
|
|
12476
12567
|
var SupportedScannersZ = z25.enum([SCANNERS.Checkmarx, SCANNERS.Snyk]);
|
|
12477
12568
|
var envVariablesSchema = z25.object({
|
|
@@ -14890,7 +14981,8 @@ var scannerToFriendlyString = {
|
|
|
14890
14981
|
snyk: "Snyk",
|
|
14891
14982
|
sonarqube: "Sonarqube",
|
|
14892
14983
|
semgrep: "Semgrep",
|
|
14893
|
-
datadog: "Datadog"
|
|
14984
|
+
datadog: "Datadog",
|
|
14985
|
+
blackduck: "Black Duck"
|
|
14894
14986
|
};
|
|
14895
14987
|
|
|
14896
14988
|
// src/features/analysis/add_fix_comments_for_pr/utils/buildCommentBody.ts
|
|
@@ -15080,7 +15172,7 @@ async function postIssueComment(params) {
|
|
|
15080
15172
|
fpDescription
|
|
15081
15173
|
} = params;
|
|
15082
15174
|
const {
|
|
15083
|
-
path:
|
|
15175
|
+
path: path35,
|
|
15084
15176
|
startLine,
|
|
15085
15177
|
vulnerabilityReportIssue: {
|
|
15086
15178
|
vulnerabilityReportIssueTags,
|
|
@@ -15095,7 +15187,7 @@ async function postIssueComment(params) {
|
|
|
15095
15187
|
Refresh the page in order to see the changes.`,
|
|
15096
15188
|
pull_number: pullRequest,
|
|
15097
15189
|
commit_id: commitSha,
|
|
15098
|
-
path:
|
|
15190
|
+
path: path35,
|
|
15099
15191
|
line: startLine
|
|
15100
15192
|
});
|
|
15101
15193
|
const commentId = commentRes.data.id;
|
|
@@ -15129,7 +15221,7 @@ async function postFixComment(params) {
|
|
|
15129
15221
|
scanner
|
|
15130
15222
|
} = params;
|
|
15131
15223
|
const {
|
|
15132
|
-
path:
|
|
15224
|
+
path: path35,
|
|
15133
15225
|
startLine,
|
|
15134
15226
|
vulnerabilityReportIssue: { fixId, vulnerabilityReportIssueTags, category },
|
|
15135
15227
|
vulnerabilityReportIssueId
|
|
@@ -15147,7 +15239,7 @@ async function postFixComment(params) {
|
|
|
15147
15239
|
Refresh the page in order to see the changes.`,
|
|
15148
15240
|
pull_number: pullRequest,
|
|
15149
15241
|
commit_id: commitSha,
|
|
15150
|
-
path:
|
|
15242
|
+
path: path35,
|
|
15151
15243
|
line: startLine
|
|
15152
15244
|
});
|
|
15153
15245
|
const commentId = commentRes.data.id;
|
|
@@ -16998,7 +17090,7 @@ function analyzeBuilder(yargs2) {
|
|
|
16998
17090
|
alias: "scan-file",
|
|
16999
17091
|
type: "string",
|
|
17000
17092
|
describe: chalk10.bold(
|
|
17001
|
-
"Select the vulnerability report to analyze (Checkmarx, Snyk, Fortify, CodeQL, Sonarqube, Semgrep, Datadog)"
|
|
17093
|
+
"Select the vulnerability report to analyze (Checkmarx, Snyk, Fortify, CodeQL, Sonarqube, Semgrep, Datadog, Black Duck)"
|
|
17002
17094
|
)
|
|
17003
17095
|
}).option("repo", repoOption).option("p", {
|
|
17004
17096
|
alias: "src-path",
|
|
@@ -17069,7 +17161,7 @@ import { spawn } from "child_process";
|
|
|
17069
17161
|
|
|
17070
17162
|
// src/features/claude_code/daemon.ts
|
|
17071
17163
|
import { readFileSync, writeFileSync as writeFileSync2 } from "fs";
|
|
17072
|
-
import
|
|
17164
|
+
import path22 from "path";
|
|
17073
17165
|
import { setTimeout as sleep2 } from "timers/promises";
|
|
17074
17166
|
import Configstore3 from "configstore";
|
|
17075
17167
|
|
|
@@ -17083,6 +17175,10 @@ var KILL_SWITCH_ENV = "MOBB_TRACY_SKILL_QUARANTINE_DISABLE";
|
|
|
17083
17175
|
var MALICIOUS_VERDICT = "MALICIOUS";
|
|
17084
17176
|
var ORPHAN_SWEEP_GRACE_MS = 10 * 60 * 1e3;
|
|
17085
17177
|
|
|
17178
|
+
// src/features/analysis/skill_quarantine/enumerateInstalledSkills.ts
|
|
17179
|
+
import { homedir as homedir2 } from "os";
|
|
17180
|
+
import path15 from "path";
|
|
17181
|
+
|
|
17086
17182
|
// src/features/analysis/context_file_processor.ts
|
|
17087
17183
|
import { createHash } from "crypto";
|
|
17088
17184
|
import path13 from "path";
|
|
@@ -17136,7 +17232,7 @@ async function processContextFiles(regularFiles, skillGroups) {
|
|
|
17136
17232
|
}
|
|
17137
17233
|
|
|
17138
17234
|
// src/features/analysis/context_file_scanner.ts
|
|
17139
|
-
import { lstat, readFile, stat } from "fs/promises";
|
|
17235
|
+
import { lstat, readdir, readFile, realpath, stat } from "fs/promises";
|
|
17140
17236
|
import { homedir } from "os";
|
|
17141
17237
|
import path14 from "path";
|
|
17142
17238
|
import { globby as globby2 } from "globby";
|
|
@@ -17160,15 +17256,15 @@ var SCAN_PATHS = {
|
|
|
17160
17256
|
root: "home"
|
|
17161
17257
|
},
|
|
17162
17258
|
{ kind: "skill-bundle", skillsRoot: ".claude/skills", root: "workspace" },
|
|
17163
|
-
{ glob: ".claude/commands/*.md", category: "
|
|
17259
|
+
{ glob: ".claude/commands/*.md", category: "skill", root: "workspace" },
|
|
17164
17260
|
{
|
|
17165
17261
|
glob: ".claude/agents/*.md",
|
|
17166
|
-
category:
|
|
17262
|
+
category: SKILL_CATEGORY,
|
|
17167
17263
|
root: "workspace"
|
|
17168
17264
|
},
|
|
17169
17265
|
{ kind: "skill-bundle", skillsRoot: ".claude/skills", root: "home" },
|
|
17170
|
-
{ glob: ".claude/commands/*.md", category: "
|
|
17171
|
-
{ glob: ".claude/agents/*.md", category:
|
|
17266
|
+
{ glob: ".claude/commands/*.md", category: "skill", root: "home" },
|
|
17267
|
+
{ glob: ".claude/agents/*.md", category: SKILL_CATEGORY, root: "home" },
|
|
17172
17268
|
{ glob: ".claude/settings.json", category: "config", root: "workspace" },
|
|
17173
17269
|
{
|
|
17174
17270
|
glob: ".claude/settings.local.json",
|
|
@@ -17247,7 +17343,7 @@ var SCAN_PATHS = {
|
|
|
17247
17343
|
},
|
|
17248
17344
|
{
|
|
17249
17345
|
glob: ".claude/agents/*.md",
|
|
17250
|
-
category:
|
|
17346
|
+
category: SKILL_CATEGORY,
|
|
17251
17347
|
root: "workspace"
|
|
17252
17348
|
},
|
|
17253
17349
|
// Agent skills — Copilot discovers skills in all three roots (VS Code docs:
|
|
@@ -17279,7 +17375,7 @@ var SCAN_PATHS = {
|
|
|
17279
17375
|
// Cross-compat home paths (Copilot reads Claude / generic agent dirs too)
|
|
17280
17376
|
{ glob: ".claude/CLAUDE.md", category: "rule", root: "home" },
|
|
17281
17377
|
{ glob: ".claude/rules/**/*.md", category: "rule", root: "home" },
|
|
17282
|
-
{ glob: ".claude/agents/*.md", category:
|
|
17378
|
+
{ glob: ".claude/agents/*.md", category: SKILL_CATEGORY, root: "home" },
|
|
17283
17379
|
{ kind: "skill-bundle", skillsRoot: ".claude/skills", root: "home" },
|
|
17284
17380
|
{ kind: "skill-bundle", skillsRoot: ".agents/skills", root: "home" }
|
|
17285
17381
|
]
|
|
@@ -17450,11 +17546,11 @@ async function readJsoncSettings(settingsPath) {
|
|
|
17450
17546
|
putSettingsCache(settingsPath, { mtimeMs, parsed: payload });
|
|
17451
17547
|
return payload;
|
|
17452
17548
|
}
|
|
17453
|
-
function putSettingsCache(
|
|
17454
|
-
if (!settingsCache.has(
|
|
17549
|
+
function putSettingsCache(path35, entry) {
|
|
17550
|
+
if (!settingsCache.has(path35) && settingsCache.size >= MAX_SETTINGS_CACHE_SIZE) {
|
|
17455
17551
|
settingsCache.delete(settingsCache.keys().next().value);
|
|
17456
17552
|
}
|
|
17457
|
-
settingsCache.set(
|
|
17553
|
+
settingsCache.set(path35, entry);
|
|
17458
17554
|
}
|
|
17459
17555
|
async function readCopilotCustomLocations(workspaceRoot) {
|
|
17460
17556
|
const parsed = await readJsoncSettings(
|
|
@@ -17704,7 +17800,7 @@ async function enumerateGlob(pattern, cwd, category, isDynamic) {
|
|
|
17704
17800
|
} catch {
|
|
17705
17801
|
return [];
|
|
17706
17802
|
}
|
|
17707
|
-
return files.map((
|
|
17803
|
+
return files.map((path35) => ({ path: path35, category }));
|
|
17708
17804
|
}
|
|
17709
17805
|
async function enumerateSkillBundle(baseDir, skillsRoot) {
|
|
17710
17806
|
const skillsDir = path14.resolve(baseDir, skillsRoot);
|
|
@@ -17738,7 +17834,68 @@ async function enumerateSkillBundle(baseDir, skillsRoot) {
|
|
|
17738
17834
|
}
|
|
17739
17835
|
})
|
|
17740
17836
|
);
|
|
17741
|
-
|
|
17837
|
+
const standaloneFiles = await enumerateStandaloneSkills(skillsDir);
|
|
17838
|
+
const symlinkResults = await enumerateSymlinkedSkills(skillsDir);
|
|
17839
|
+
return [
|
|
17840
|
+
...perSkillResults.flat().map((p) => ({ path: p, category: "skill" })),
|
|
17841
|
+
...standaloneFiles.map((p) => ({ path: p, category: "skill" })),
|
|
17842
|
+
...symlinkResults
|
|
17843
|
+
];
|
|
17844
|
+
}
|
|
17845
|
+
async function enumerateStandaloneSkills(skillsDir) {
|
|
17846
|
+
try {
|
|
17847
|
+
return await globby2("*.md", {
|
|
17848
|
+
cwd: skillsDir,
|
|
17849
|
+
absolute: true,
|
|
17850
|
+
onlyFiles: true,
|
|
17851
|
+
dot: false,
|
|
17852
|
+
followSymbolicLinks: false
|
|
17853
|
+
});
|
|
17854
|
+
} catch {
|
|
17855
|
+
return [];
|
|
17856
|
+
}
|
|
17857
|
+
}
|
|
17858
|
+
async function enumerateSymlinkedSkills(skillsDir) {
|
|
17859
|
+
let dirEntries;
|
|
17860
|
+
try {
|
|
17861
|
+
dirEntries = await readdir(skillsDir, {
|
|
17862
|
+
withFileTypes: true,
|
|
17863
|
+
encoding: "utf8"
|
|
17864
|
+
});
|
|
17865
|
+
} catch {
|
|
17866
|
+
return [];
|
|
17867
|
+
}
|
|
17868
|
+
const results = [];
|
|
17869
|
+
for (const entry of dirEntries) {
|
|
17870
|
+
if (!entry.isSymbolicLink()) continue;
|
|
17871
|
+
const entryPath = path14.join(skillsDir, entry.name);
|
|
17872
|
+
try {
|
|
17873
|
+
const st = await stat(entryPath);
|
|
17874
|
+
if (st.isDirectory()) {
|
|
17875
|
+
const hasManifest = await stat(path14.join(entryPath, "SKILL.md")).then(() => true).catch(() => false);
|
|
17876
|
+
if (!hasManifest) continue;
|
|
17877
|
+
const realDir = await realpath(entryPath);
|
|
17878
|
+
const realFiles = await globby2("**/*", {
|
|
17879
|
+
cwd: realDir,
|
|
17880
|
+
absolute: true,
|
|
17881
|
+
onlyFiles: true,
|
|
17882
|
+
dot: true,
|
|
17883
|
+
followSymbolicLinks: false,
|
|
17884
|
+
deep: SKILL_BUNDLE_MAX_DEPTH
|
|
17885
|
+
}).catch(() => []);
|
|
17886
|
+
for (const f of realFiles) {
|
|
17887
|
+
results.push({
|
|
17888
|
+
path: path14.join(entryPath, path14.relative(realDir, f)),
|
|
17889
|
+
category: "skill"
|
|
17890
|
+
});
|
|
17891
|
+
}
|
|
17892
|
+
} else if (st.isFile() && entry.name.endsWith(".md")) {
|
|
17893
|
+
results.push({ path: entryPath, category: "skill" });
|
|
17894
|
+
}
|
|
17895
|
+
} catch {
|
|
17896
|
+
}
|
|
17897
|
+
}
|
|
17898
|
+
return results;
|
|
17742
17899
|
}
|
|
17743
17900
|
var DYNAMIC_SCAN_MAX_DEPTH = 6;
|
|
17744
17901
|
var SKILL_MANIFEST_SCAN_DEPTH = 2;
|
|
@@ -17769,15 +17926,26 @@ function deriveIdentifier(filePath, baseDir) {
|
|
|
17769
17926
|
|
|
17770
17927
|
// src/features/analysis/skill_quarantine/enumerateInstalledSkills.ts
|
|
17771
17928
|
async function enumerateInstalledSkills(workspaceRoot) {
|
|
17772
|
-
const { skillGroups } = await scanContextFiles(
|
|
17929
|
+
const { skillGroups, regularFiles } = await scanContextFiles(
|
|
17773
17930
|
workspaceRoot,
|
|
17774
17931
|
"claude-code",
|
|
17775
17932
|
void 0
|
|
17776
17933
|
);
|
|
17777
|
-
|
|
17934
|
+
const home = homedir2();
|
|
17935
|
+
const agentGroups = regularFiles.filter((f) => f.category === "agent-config").map((f) => ({
|
|
17936
|
+
name: path15.basename(f.path, path15.extname(f.path)),
|
|
17937
|
+
root: f.path.startsWith(home + path15.sep) ? "home" : "workspace",
|
|
17938
|
+
skillPath: f.path,
|
|
17939
|
+
files: [f],
|
|
17940
|
+
isFolder: false,
|
|
17941
|
+
maxMtimeMs: f.mtimeMs,
|
|
17942
|
+
sessionKey: `agent-config:${f.path}`
|
|
17943
|
+
}));
|
|
17944
|
+
const allGroups = [...skillGroups, ...agentGroups];
|
|
17945
|
+
if (allGroups.length === 0) {
|
|
17778
17946
|
return [];
|
|
17779
17947
|
}
|
|
17780
|
-
const { skills } = await processContextFiles([],
|
|
17948
|
+
const { skills } = await processContextFiles([], allGroups);
|
|
17781
17949
|
return skills.map((s) => {
|
|
17782
17950
|
const parts = s.group.skillPath.split(/[\\/]/);
|
|
17783
17951
|
const origName = parts[parts.length - 1] || s.group.name;
|
|
@@ -17818,31 +17986,33 @@ var Metric = {
|
|
|
17818
17986
|
import { randomUUID } from "crypto";
|
|
17819
17987
|
import { existsSync as existsSync2 } from "fs";
|
|
17820
17988
|
import {
|
|
17989
|
+
lstat as lstat2,
|
|
17821
17990
|
mkdir,
|
|
17822
|
-
readdir,
|
|
17991
|
+
readdir as readdir2,
|
|
17823
17992
|
readFile as readFile2,
|
|
17824
17993
|
rename,
|
|
17825
17994
|
rm,
|
|
17826
17995
|
stat as stat2,
|
|
17996
|
+
unlink,
|
|
17827
17997
|
writeFile
|
|
17828
17998
|
} from "fs/promises";
|
|
17829
|
-
import
|
|
17999
|
+
import path17 from "path";
|
|
17830
18000
|
import { move } from "fs-extra";
|
|
17831
18001
|
|
|
17832
18002
|
// src/features/analysis/skill_quarantine/paths.ts
|
|
17833
|
-
import { homedir as
|
|
17834
|
-
import
|
|
18003
|
+
import { homedir as homedir3 } from "os";
|
|
18004
|
+
import path16 from "path";
|
|
17835
18005
|
function getQuarantineRoot() {
|
|
17836
|
-
return
|
|
18006
|
+
return path16.join(homedir3(), ".tracy", "quarantine", "claude", "skills");
|
|
17837
18007
|
}
|
|
17838
18008
|
function getQuarantinedHashDir(md5) {
|
|
17839
|
-
return
|
|
18009
|
+
return path16.join(getQuarantineRoot(), md5);
|
|
17840
18010
|
}
|
|
17841
18011
|
function getQuarantinedTargetPath(md5, origName) {
|
|
17842
|
-
return
|
|
18012
|
+
return path16.join(getQuarantinedHashDir(md5), origName);
|
|
17843
18013
|
}
|
|
17844
18014
|
function getStagingDir(md5, pid, uuid) {
|
|
17845
|
-
return
|
|
18015
|
+
return path16.join(getQuarantineRoot(), `${md5}_tmp_${pid}_${uuid}`);
|
|
17846
18016
|
}
|
|
17847
18017
|
var STAGING_DIR_REGEX = /^([0-9a-f]{32})_tmp_/;
|
|
17848
18018
|
|
|
@@ -17907,8 +18077,61 @@ async function quarantineSkill(params) {
|
|
|
17907
18077
|
);
|
|
17908
18078
|
return { status: "already_quarantined" };
|
|
17909
18079
|
}
|
|
18080
|
+
let isSymlink = false;
|
|
18081
|
+
try {
|
|
18082
|
+
const lst = await lstat2(skillPath);
|
|
18083
|
+
isSymlink = lst.isSymbolicLink();
|
|
18084
|
+
} catch {
|
|
18085
|
+
}
|
|
18086
|
+
if (isSymlink) {
|
|
18087
|
+
const stubContent2 = renderStub({
|
|
18088
|
+
md5,
|
|
18089
|
+
isFolder,
|
|
18090
|
+
// Symlinks have no quarantine archive; note that in the stub.
|
|
18091
|
+
quarantinedPath: `(symlink at ${skillPath} replaced \u2014 original content was not moved)`,
|
|
18092
|
+
origPath: skillPath,
|
|
18093
|
+
summary: verdict.summary,
|
|
18094
|
+
scannerName: verdict.scannerName,
|
|
18095
|
+
scannerVersion: verdict.scannerVersion,
|
|
18096
|
+
scannedAt: verdict.scannedAt
|
|
18097
|
+
});
|
|
18098
|
+
try {
|
|
18099
|
+
await mkdir(hashDir, { recursive: true });
|
|
18100
|
+
if (isFolder) {
|
|
18101
|
+
const tmpDir = `${skillPath}.__tracy_tmp__`;
|
|
18102
|
+
await mkdir(tmpDir, { recursive: true });
|
|
18103
|
+
await writeFile(path17.join(tmpDir, "SKILL.md"), stubContent2, "utf8");
|
|
18104
|
+
await unlink(skillPath);
|
|
18105
|
+
await rename(tmpDir, skillPath);
|
|
18106
|
+
} else {
|
|
18107
|
+
const tmpFile = `${skillPath}.__tracy_tmp__`;
|
|
18108
|
+
await writeFile(tmpFile, stubContent2, "utf8");
|
|
18109
|
+
await unlink(skillPath);
|
|
18110
|
+
await rename(tmpFile, skillPath);
|
|
18111
|
+
}
|
|
18112
|
+
} catch (err) {
|
|
18113
|
+
log2.error(
|
|
18114
|
+
{ err, md5, skillPath, metric: Metric.STUB_ERROR },
|
|
18115
|
+
"skill_quarantine: symlink stub write failed"
|
|
18116
|
+
);
|
|
18117
|
+
return { status: "stub_error", err };
|
|
18118
|
+
}
|
|
18119
|
+
await preRegisterStubMd5(skillPath, isFolder, log2);
|
|
18120
|
+
log2.info(
|
|
18121
|
+
{
|
|
18122
|
+
md5,
|
|
18123
|
+
verdict: verdict.verdict,
|
|
18124
|
+
shape: isFolder ? "folder" : "standalone",
|
|
18125
|
+
scanner: verdict.scannerName,
|
|
18126
|
+
scannerVersion: verdict.scannerVersion,
|
|
18127
|
+
metric: Metric.QUARANTINED
|
|
18128
|
+
},
|
|
18129
|
+
"skill_quarantine: quarantined (symlink)"
|
|
18130
|
+
);
|
|
18131
|
+
return { status: "quarantined" };
|
|
18132
|
+
}
|
|
17910
18133
|
const stagingDir = getStagingDir(md5, process.pid, randomUUID());
|
|
17911
|
-
const stagingTarget =
|
|
18134
|
+
const stagingTarget = path17.join(stagingDir, origName);
|
|
17912
18135
|
const finalTarget = getQuarantinedTargetPath(md5, origName);
|
|
17913
18136
|
try {
|
|
17914
18137
|
await mkdir(stagingDir, { recursive: true });
|
|
@@ -17958,7 +18181,7 @@ async function quarantineSkill(params) {
|
|
|
17958
18181
|
try {
|
|
17959
18182
|
if (isFolder) {
|
|
17960
18183
|
await mkdir(skillPath, { recursive: true });
|
|
17961
|
-
await writeFile(
|
|
18184
|
+
await writeFile(path17.join(skillPath, "SKILL.md"), stubContent, "utf8");
|
|
17962
18185
|
} else {
|
|
17963
18186
|
await writeFile(skillPath, stubContent, "utf8");
|
|
17964
18187
|
}
|
|
@@ -17987,7 +18210,7 @@ async function preRegisterStubMd5(skillPath, isFolder, log2) {
|
|
|
17987
18210
|
try {
|
|
17988
18211
|
const stubEntries = await gatherStubEntries(skillPath, isFolder);
|
|
17989
18212
|
const stubGroup = {
|
|
17990
|
-
name:
|
|
18213
|
+
name: path17.basename(skillPath).replace(/\.md$/i, ""),
|
|
17991
18214
|
root: "workspace",
|
|
17992
18215
|
skillPath,
|
|
17993
18216
|
files: stubEntries,
|
|
@@ -18008,14 +18231,14 @@ async function preRegisterStubMd5(skillPath, isFolder, log2) {
|
|
|
18008
18231
|
}
|
|
18009
18232
|
async function gatherStubEntries(skillPath, isFolder) {
|
|
18010
18233
|
const now = Date.now();
|
|
18011
|
-
const target = isFolder ?
|
|
18234
|
+
const target = isFolder ? path17.join(skillPath, "SKILL.md") : skillPath;
|
|
18012
18235
|
const [st, content] = await Promise.all([
|
|
18013
18236
|
stat2(target),
|
|
18014
18237
|
readFile2(target, "utf8")
|
|
18015
18238
|
]);
|
|
18016
18239
|
return [
|
|
18017
18240
|
{
|
|
18018
|
-
name: isFolder ? "SKILL.md" :
|
|
18241
|
+
name: isFolder ? "SKILL.md" : path17.basename(skillPath),
|
|
18019
18242
|
path: target,
|
|
18020
18243
|
content,
|
|
18021
18244
|
sizeBytes: st.size,
|
|
@@ -18028,7 +18251,7 @@ async function sweepOrphanStagingDirs(log2) {
|
|
|
18028
18251
|
const root = getQuarantineRoot();
|
|
18029
18252
|
let entries;
|
|
18030
18253
|
try {
|
|
18031
|
-
entries = await
|
|
18254
|
+
entries = await readdir2(root);
|
|
18032
18255
|
} catch (err) {
|
|
18033
18256
|
if (err.code === "ENOENT") return 0;
|
|
18034
18257
|
log2.warn({ err, root }, "skill_quarantine: orphan sweep readdir failed");
|
|
@@ -18038,7 +18261,7 @@ async function sweepOrphanStagingDirs(log2) {
|
|
|
18038
18261
|
let swept = 0;
|
|
18039
18262
|
for (const entry of entries) {
|
|
18040
18263
|
if (!STAGING_DIR_REGEX.test(entry)) continue;
|
|
18041
|
-
const full =
|
|
18264
|
+
const full = path17.join(root, entry);
|
|
18042
18265
|
let mtimeMs;
|
|
18043
18266
|
try {
|
|
18044
18267
|
mtimeMs = (await stat2(full)).mtimeMs;
|
|
@@ -18171,7 +18394,7 @@ async function runQuarantineCheckIfNeeded(opts) {
|
|
|
18171
18394
|
// src/features/claude_code/daemon_pid_file.ts
|
|
18172
18395
|
import fs13 from "fs";
|
|
18173
18396
|
import os4 from "os";
|
|
18174
|
-
import
|
|
18397
|
+
import path18 from "path";
|
|
18175
18398
|
|
|
18176
18399
|
// src/features/claude_code/data_collector_constants.ts
|
|
18177
18400
|
var CC_VERSION_CACHE_KEY = "claudeCode.detectedCCVersion";
|
|
@@ -18188,20 +18411,21 @@ var DAEMON_POLL_INTERVAL_MS = (() => {
|
|
|
18188
18411
|
var HEARTBEAT_STALE_MS = 3e4;
|
|
18189
18412
|
var TRANSCRIPT_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
18190
18413
|
var DAEMON_CHUNK_SIZE = 50;
|
|
18414
|
+
var CONTEXT_SCAN_INTERVAL_MS = 5e3;
|
|
18191
18415
|
|
|
18192
18416
|
// src/features/claude_code/daemon_pid_file.ts
|
|
18193
18417
|
function getMobbdevDir() {
|
|
18194
|
-
return
|
|
18418
|
+
return path18.join(os4.homedir(), ".mobbdev");
|
|
18195
18419
|
}
|
|
18196
18420
|
function getDaemonCheckScriptPath() {
|
|
18197
|
-
return
|
|
18421
|
+
return path18.join(getMobbdevDir(), "daemon-check.js");
|
|
18198
18422
|
}
|
|
18199
18423
|
var DaemonPidFile = class {
|
|
18200
18424
|
constructor() {
|
|
18201
18425
|
__publicField(this, "data", null);
|
|
18202
18426
|
}
|
|
18203
18427
|
get filePath() {
|
|
18204
|
-
return
|
|
18428
|
+
return path18.join(getMobbdevDir(), "daemon.pid");
|
|
18205
18429
|
}
|
|
18206
18430
|
/** Ensure ~/.mobbdev/ directory exists. */
|
|
18207
18431
|
ensureDir() {
|
|
@@ -18263,8 +18487,8 @@ var DaemonPidFile = class {
|
|
|
18263
18487
|
// src/features/claude_code/data_collector.ts
|
|
18264
18488
|
import { execFile } from "child_process";
|
|
18265
18489
|
import { createHash as createHash3 } from "crypto";
|
|
18266
|
-
import { access, open as open4, readdir as
|
|
18267
|
-
import
|
|
18490
|
+
import { access, open as open4, readdir as readdir3, readFile as readFile3, unlink as unlink2 } from "fs/promises";
|
|
18491
|
+
import path19 from "path";
|
|
18268
18492
|
import { promisify } from "util";
|
|
18269
18493
|
|
|
18270
18494
|
// src/features/analysis/context_file_uploader.ts
|
|
@@ -18529,8 +18753,8 @@ function createConfigstoreStream(store, opts) {
|
|
|
18529
18753
|
heartbeatBuffer.length = 0;
|
|
18530
18754
|
}
|
|
18531
18755
|
}
|
|
18532
|
-
function setScopePath(
|
|
18533
|
-
scopePath =
|
|
18756
|
+
function setScopePath(path35) {
|
|
18757
|
+
scopePath = path35;
|
|
18534
18758
|
}
|
|
18535
18759
|
return { writable, flush, setScopePath };
|
|
18536
18760
|
}
|
|
@@ -18754,7 +18978,7 @@ function createLogger(config2) {
|
|
|
18754
18978
|
|
|
18755
18979
|
// src/features/claude_code/hook_logger.ts
|
|
18756
18980
|
var DD_RUM_TOKEN = true ? "pubf59c0182545bfb4c299175119f1abf9b" : "";
|
|
18757
|
-
var CLI_VERSION = true ? "1.4.
|
|
18981
|
+
var CLI_VERSION = true ? "1.4.1" : "unknown";
|
|
18758
18982
|
var NAMESPACE = "mobbdev-claude-code-hook-logs";
|
|
18759
18983
|
var claudeCodeVersion;
|
|
18760
18984
|
function buildDdTags() {
|
|
@@ -18845,12 +19069,12 @@ async function resolveTranscriptPath(transcriptPath, sessionId) {
|
|
|
18845
19069
|
return transcriptPath;
|
|
18846
19070
|
} catch {
|
|
18847
19071
|
}
|
|
18848
|
-
const filename =
|
|
18849
|
-
const dirName =
|
|
18850
|
-
const projectsDir =
|
|
19072
|
+
const filename = path19.basename(transcriptPath);
|
|
19073
|
+
const dirName = path19.basename(path19.dirname(transcriptPath));
|
|
19074
|
+
const projectsDir = path19.dirname(path19.dirname(transcriptPath));
|
|
18851
19075
|
const baseDirName = dirName.replace(/[-.]claude-worktrees-.+$/, "");
|
|
18852
19076
|
if (baseDirName !== dirName) {
|
|
18853
|
-
const candidate =
|
|
19077
|
+
const candidate = path19.join(projectsDir, baseDirName, filename);
|
|
18854
19078
|
try {
|
|
18855
19079
|
await access(candidate);
|
|
18856
19080
|
hookLog.info(
|
|
@@ -18869,10 +19093,10 @@ async function resolveTranscriptPath(transcriptPath, sessionId) {
|
|
|
18869
19093
|
}
|
|
18870
19094
|
}
|
|
18871
19095
|
try {
|
|
18872
|
-
const dirs = await
|
|
19096
|
+
const dirs = await readdir3(projectsDir);
|
|
18873
19097
|
for (const dir of dirs) {
|
|
18874
19098
|
if (dir === dirName) continue;
|
|
18875
|
-
const candidate =
|
|
19099
|
+
const candidate = path19.join(projectsDir, dir, filename);
|
|
18876
19100
|
try {
|
|
18877
19101
|
await access(candidate);
|
|
18878
19102
|
hookLog.info(
|
|
@@ -19053,11 +19277,11 @@ async function cleanupStaleSessions(configDir) {
|
|
|
19053
19277
|
const now = Date.now();
|
|
19054
19278
|
const prefix = getSessionFilePrefix();
|
|
19055
19279
|
try {
|
|
19056
|
-
const files = await
|
|
19280
|
+
const files = await readdir3(configDir);
|
|
19057
19281
|
let deletedCount = 0;
|
|
19058
19282
|
for (const file of files) {
|
|
19059
19283
|
if (!file.startsWith(prefix) || !file.endsWith(".json")) continue;
|
|
19060
|
-
const filePath =
|
|
19284
|
+
const filePath = path19.join(configDir, file);
|
|
19061
19285
|
try {
|
|
19062
19286
|
const content = JSON.parse(await readFile3(filePath, "utf-8"));
|
|
19063
19287
|
let newest = 0;
|
|
@@ -19069,7 +19293,7 @@ async function cleanupStaleSessions(configDir) {
|
|
|
19069
19293
|
}
|
|
19070
19294
|
}
|
|
19071
19295
|
if (newest > 0 && now - newest > STALE_KEY_MAX_AGE_MS) {
|
|
19072
|
-
await
|
|
19296
|
+
await unlink2(filePath);
|
|
19073
19297
|
deletedCount++;
|
|
19074
19298
|
}
|
|
19075
19299
|
} catch {
|
|
@@ -19209,16 +19433,6 @@ async function processTranscript(input, sessionStore, log2, maxEntries = DAEMON_
|
|
|
19209
19433
|
entriesSkipped: filteredOut,
|
|
19210
19434
|
claudeCodeVersion: getClaudeCodeVersion()
|
|
19211
19435
|
});
|
|
19212
|
-
if (input.cwd) {
|
|
19213
|
-
uploadContextFilesIfNeeded(
|
|
19214
|
-
input.session_id,
|
|
19215
|
-
input.cwd,
|
|
19216
|
-
gqlClient,
|
|
19217
|
-
log2
|
|
19218
|
-
).catch((err) => {
|
|
19219
|
-
log2.error({ data: { err } }, "uploadContextFilesIfNeeded failed");
|
|
19220
|
-
});
|
|
19221
|
-
}
|
|
19222
19436
|
return {
|
|
19223
19437
|
entriesUploaded: entries.length,
|
|
19224
19438
|
entriesSkipped: filteredOut,
|
|
@@ -19305,14 +19519,14 @@ async function uploadContextFilesIfNeeded(sessionId, cwd, gqlClient, log2) {
|
|
|
19305
19519
|
import fs14 from "fs";
|
|
19306
19520
|
import fsPromises4 from "fs/promises";
|
|
19307
19521
|
import os6 from "os";
|
|
19308
|
-
import
|
|
19522
|
+
import path20 from "path";
|
|
19309
19523
|
import chalk11 from "chalk";
|
|
19310
19524
|
|
|
19311
19525
|
// src/features/claude_code/daemon-check-shim.tmpl.js
|
|
19312
19526
|
var daemon_check_shim_tmpl_default = "// Mobb daemon shim \u2014 checks if daemon is alive, spawns if dead.\n// Auto-generated by mobbdev CLI. Do not edit.\nvar fs = require('fs')\nvar spawn = require('child_process').spawn\nvar path = require('path')\nvar os = require('os')\n\nvar pidFile = path.join(os.homedir(), '.mobbdev', 'daemon.pid')\nvar HEARTBEAT_STALE_MS = __HEARTBEAT_STALE_MS__\n\ntry {\n var data = JSON.parse(fs.readFileSync(pidFile, 'utf8'))\n if (Date.now() - data.heartbeat > HEARTBEAT_STALE_MS) throw new Error('stale')\n process.kill(data.pid, 0) // throws ESRCH if the process is gone\n} catch (e) {\n var localCli = process.env.MOBBDEV_LOCAL_CLI\n var child = localCli\n ? spawn('node', [localCli, 'claude-code-daemon'], { detached: true, stdio: 'ignore', windowsHide: true })\n : spawn('npx', ['--yes', 'mobbdev@latest', 'claude-code-daemon'], { detached: true, stdio: 'ignore', shell: true, windowsHide: true })\n child.unref()\n}\n";
|
|
19313
19527
|
|
|
19314
19528
|
// src/features/claude_code/install_hook.ts
|
|
19315
|
-
var CLAUDE_SETTINGS_PATH =
|
|
19529
|
+
var CLAUDE_SETTINGS_PATH = path20.join(os6.homedir(), ".claude", "settings.json");
|
|
19316
19530
|
var RECOMMENDED_MATCHER = "*";
|
|
19317
19531
|
async function claudeSettingsExists() {
|
|
19318
19532
|
try {
|
|
@@ -19458,18 +19672,18 @@ async function installMobbHooks(options = {}) {
|
|
|
19458
19672
|
}
|
|
19459
19673
|
|
|
19460
19674
|
// src/features/claude_code/transcript_scanner.ts
|
|
19461
|
-
import { open as open5, readdir as
|
|
19675
|
+
import { open as open5, readdir as readdir4, stat as stat3 } from "fs/promises";
|
|
19462
19676
|
import os7 from "os";
|
|
19463
|
-
import
|
|
19677
|
+
import path21 from "path";
|
|
19464
19678
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
19465
19679
|
function getClaudeProjectsDirs() {
|
|
19466
19680
|
const dirs = [];
|
|
19467
19681
|
const configDir = process.env["CLAUDE_CONFIG_DIR"];
|
|
19468
19682
|
if (configDir) {
|
|
19469
|
-
dirs.push(
|
|
19683
|
+
dirs.push(path21.join(configDir, "projects"));
|
|
19470
19684
|
}
|
|
19471
|
-
dirs.push(
|
|
19472
|
-
dirs.push(
|
|
19685
|
+
dirs.push(path21.join(os7.homedir(), ".config", "claude", "projects"));
|
|
19686
|
+
dirs.push(path21.join(os7.homedir(), ".claude", "projects"));
|
|
19473
19687
|
return dirs;
|
|
19474
19688
|
}
|
|
19475
19689
|
async function collectJsonlFiles(files, dir, projectDir, seen, now, results) {
|
|
@@ -19477,7 +19691,7 @@ async function collectJsonlFiles(files, dir, projectDir, seen, now, results) {
|
|
|
19477
19691
|
if (!file.endsWith(".jsonl")) continue;
|
|
19478
19692
|
const sessionId = file.replace(".jsonl", "");
|
|
19479
19693
|
if (!UUID_RE.test(sessionId)) continue;
|
|
19480
|
-
const filePath =
|
|
19694
|
+
const filePath = path21.join(dir, file);
|
|
19481
19695
|
if (seen.has(filePath)) continue;
|
|
19482
19696
|
seen.add(filePath);
|
|
19483
19697
|
let fileStat;
|
|
@@ -19503,12 +19717,12 @@ async function scanForTranscripts(projectsDirs = getClaudeProjectsDirs()) {
|
|
|
19503
19717
|
for (const projectsDir of projectsDirs) {
|
|
19504
19718
|
let projectDirs;
|
|
19505
19719
|
try {
|
|
19506
|
-
projectDirs = await
|
|
19720
|
+
projectDirs = await readdir4(projectsDir);
|
|
19507
19721
|
} catch {
|
|
19508
19722
|
continue;
|
|
19509
19723
|
}
|
|
19510
19724
|
for (const projName of projectDirs) {
|
|
19511
|
-
const projPath =
|
|
19725
|
+
const projPath = path21.join(projectsDir, projName);
|
|
19512
19726
|
let projStat;
|
|
19513
19727
|
try {
|
|
19514
19728
|
projStat = await stat3(projPath);
|
|
@@ -19518,18 +19732,18 @@ async function scanForTranscripts(projectsDirs = getClaudeProjectsDirs()) {
|
|
|
19518
19732
|
if (!projStat.isDirectory()) continue;
|
|
19519
19733
|
let files;
|
|
19520
19734
|
try {
|
|
19521
|
-
files = await
|
|
19735
|
+
files = await readdir4(projPath);
|
|
19522
19736
|
} catch {
|
|
19523
19737
|
continue;
|
|
19524
19738
|
}
|
|
19525
19739
|
await collectJsonlFiles(files, projPath, projPath, seen, now, results);
|
|
19526
19740
|
for (const entry of files) {
|
|
19527
19741
|
if (!UUID_RE.test(entry)) continue;
|
|
19528
|
-
const subagentsDir =
|
|
19742
|
+
const subagentsDir = path21.join(projPath, entry, "subagents");
|
|
19529
19743
|
try {
|
|
19530
19744
|
const s = await stat3(subagentsDir);
|
|
19531
19745
|
if (!s.isDirectory()) continue;
|
|
19532
|
-
const subFiles = await
|
|
19746
|
+
const subFiles = await readdir4(subagentsDir);
|
|
19533
19747
|
await collectJsonlFiles(
|
|
19534
19748
|
subFiles,
|
|
19535
19749
|
subagentsDir,
|
|
@@ -19613,6 +19827,8 @@ async function startDaemon() {
|
|
|
19613
19827
|
const startedAt = Date.now();
|
|
19614
19828
|
const lastSeen = /* @__PURE__ */ new Map();
|
|
19615
19829
|
let cleanupConfigDir;
|
|
19830
|
+
const sessionCwdCache = /* @__PURE__ */ new Map();
|
|
19831
|
+
let lastContextScanMs = 0;
|
|
19616
19832
|
while (true) {
|
|
19617
19833
|
if (shuttingDown) {
|
|
19618
19834
|
await gracefulExit(0, "signal");
|
|
@@ -19626,9 +19842,29 @@ async function startDaemon() {
|
|
|
19626
19842
|
for (const transcript of changed) {
|
|
19627
19843
|
const sessionStore = createSessionConfigStore(transcript.sessionId);
|
|
19628
19844
|
if (!cleanupConfigDir) {
|
|
19629
|
-
cleanupConfigDir =
|
|
19845
|
+
cleanupConfigDir = path22.dirname(sessionStore.path);
|
|
19846
|
+
}
|
|
19847
|
+
await drainTranscript(
|
|
19848
|
+
transcript,
|
|
19849
|
+
sessionStore,
|
|
19850
|
+
gqlClient,
|
|
19851
|
+
sessionCwdCache
|
|
19852
|
+
);
|
|
19853
|
+
}
|
|
19854
|
+
if (lastSeen.size > 0) {
|
|
19855
|
+
for (const filePath of sessionCwdCache.keys()) {
|
|
19856
|
+
if (!lastSeen.has(filePath)) sessionCwdCache.delete(filePath);
|
|
19857
|
+
}
|
|
19858
|
+
}
|
|
19859
|
+
const now = Date.now();
|
|
19860
|
+
if (now - lastContextScanMs >= CONTEXT_SCAN_INTERVAL_MS) {
|
|
19861
|
+
lastContextScanMs = now;
|
|
19862
|
+
for (const { sessionId, cwd } of sessionCwdCache.values()) {
|
|
19863
|
+
const log2 = createScopedHookLog(cwd, { daemonMode: true });
|
|
19864
|
+
uploadContextFilesIfNeeded(sessionId, cwd, gqlClient, log2).catch(
|
|
19865
|
+
(err) => log2.warn({ err }, "Context file scan failed")
|
|
19866
|
+
);
|
|
19630
19867
|
}
|
|
19631
|
-
await drainTranscript(transcript, sessionStore, gqlClient);
|
|
19632
19868
|
}
|
|
19633
19869
|
if (cleanupConfigDir) {
|
|
19634
19870
|
await cleanupStaleSessions(cleanupConfigDir);
|
|
@@ -19669,11 +19905,17 @@ async function authenticateOrExit(exit) {
|
|
|
19669
19905
|
return exit(1, "auth failed");
|
|
19670
19906
|
}
|
|
19671
19907
|
}
|
|
19672
|
-
async function drainTranscript(transcript, sessionStore, gqlClient) {
|
|
19908
|
+
async function drainTranscript(transcript, sessionStore, gqlClient, sessionCwdCache) {
|
|
19673
19909
|
const cwd = await extractCwdFromTranscript(transcript.filePath);
|
|
19674
19910
|
const log2 = createScopedHookLog(cwd ?? transcript.projectDir, {
|
|
19675
19911
|
daemonMode: true
|
|
19676
19912
|
});
|
|
19913
|
+
if (cwd) {
|
|
19914
|
+
sessionCwdCache.set(transcript.filePath, {
|
|
19915
|
+
sessionId: transcript.sessionId,
|
|
19916
|
+
cwd
|
|
19917
|
+
});
|
|
19918
|
+
}
|
|
19677
19919
|
try {
|
|
19678
19920
|
let hasMore = true;
|
|
19679
19921
|
while (hasMore) {
|
|
@@ -19897,8 +20139,8 @@ var WorkspaceService = class {
|
|
|
19897
20139
|
* Sets a known workspace path that was discovered through successful validation
|
|
19898
20140
|
* @param path The validated workspace path to store
|
|
19899
20141
|
*/
|
|
19900
|
-
static setKnownWorkspacePath(
|
|
19901
|
-
this.knownWorkspacePath =
|
|
20142
|
+
static setKnownWorkspacePath(path35) {
|
|
20143
|
+
this.knownWorkspacePath = path35;
|
|
19902
20144
|
}
|
|
19903
20145
|
/**
|
|
19904
20146
|
* Gets the known workspace path that was previously validated
|
|
@@ -20759,7 +21001,7 @@ async function createAuthenticatedMcpGQLClient({
|
|
|
20759
21001
|
import { execSync as execSync2 } from "child_process";
|
|
20760
21002
|
import fs15 from "fs";
|
|
20761
21003
|
import os8 from "os";
|
|
20762
|
-
import
|
|
21004
|
+
import path23 from "path";
|
|
20763
21005
|
var IDEs = ["cursor", "windsurf", "webstorm", "vscode", "claude"];
|
|
20764
21006
|
var runCommand = (cmd) => {
|
|
20765
21007
|
try {
|
|
@@ -20774,7 +21016,7 @@ var gitInfo = {
|
|
|
20774
21016
|
};
|
|
20775
21017
|
var getClaudeWorkspacePaths = () => {
|
|
20776
21018
|
const home = os8.homedir();
|
|
20777
|
-
const claudeIdePath =
|
|
21019
|
+
const claudeIdePath = path23.join(home, ".claude", "ide");
|
|
20778
21020
|
const workspacePaths = [];
|
|
20779
21021
|
if (!fs15.existsSync(claudeIdePath)) {
|
|
20780
21022
|
return workspacePaths;
|
|
@@ -20782,7 +21024,7 @@ var getClaudeWorkspacePaths = () => {
|
|
|
20782
21024
|
try {
|
|
20783
21025
|
const lockFiles = fs15.readdirSync(claudeIdePath).filter((file) => file.endsWith(".lock"));
|
|
20784
21026
|
for (const lockFile of lockFiles) {
|
|
20785
|
-
const lockFilePath =
|
|
21027
|
+
const lockFilePath = path23.join(claudeIdePath, lockFile);
|
|
20786
21028
|
try {
|
|
20787
21029
|
const lockContent = JSON.parse(fs15.readFileSync(lockFilePath, "utf8"));
|
|
20788
21030
|
if (lockContent.workspaceFolders && Array.isArray(lockContent.workspaceFolders)) {
|
|
@@ -20807,24 +21049,24 @@ var getMCPConfigPaths = (hostName) => {
|
|
|
20807
21049
|
switch (hostName.toLowerCase()) {
|
|
20808
21050
|
case "cursor":
|
|
20809
21051
|
return [
|
|
20810
|
-
|
|
21052
|
+
path23.join(currentDir, ".cursor", "mcp.json"),
|
|
20811
21053
|
// local first
|
|
20812
|
-
|
|
21054
|
+
path23.join(home, ".cursor", "mcp.json")
|
|
20813
21055
|
];
|
|
20814
21056
|
case "windsurf":
|
|
20815
21057
|
return [
|
|
20816
|
-
|
|
21058
|
+
path23.join(currentDir, ".codeium", "mcp_config.json"),
|
|
20817
21059
|
// local first
|
|
20818
|
-
|
|
21060
|
+
path23.join(home, ".codeium", "windsurf", "mcp_config.json")
|
|
20819
21061
|
];
|
|
20820
21062
|
case "webstorm":
|
|
20821
21063
|
return [];
|
|
20822
21064
|
case "visualstudiocode":
|
|
20823
21065
|
case "vscode":
|
|
20824
21066
|
return [
|
|
20825
|
-
|
|
21067
|
+
path23.join(currentDir, ".vscode", "mcp.json"),
|
|
20826
21068
|
// local first
|
|
20827
|
-
process.platform === "win32" ?
|
|
21069
|
+
process.platform === "win32" ? path23.join(home, "AppData", "Roaming", "Code", "User", "mcp.json") : path23.join(
|
|
20828
21070
|
home,
|
|
20829
21071
|
"Library",
|
|
20830
21072
|
"Application Support",
|
|
@@ -20835,13 +21077,13 @@ var getMCPConfigPaths = (hostName) => {
|
|
|
20835
21077
|
];
|
|
20836
21078
|
case "claude": {
|
|
20837
21079
|
const claudePaths = [
|
|
20838
|
-
|
|
21080
|
+
path23.join(currentDir, ".claude.json"),
|
|
20839
21081
|
// local first
|
|
20840
|
-
|
|
21082
|
+
path23.join(home, ".claude.json")
|
|
20841
21083
|
];
|
|
20842
21084
|
const workspacePaths = getClaudeWorkspacePaths();
|
|
20843
21085
|
for (const workspacePath of workspacePaths) {
|
|
20844
|
-
claudePaths.push(
|
|
21086
|
+
claudePaths.push(path23.join(workspacePath, ".mcp.json"));
|
|
20845
21087
|
}
|
|
20846
21088
|
return claudePaths;
|
|
20847
21089
|
}
|
|
@@ -21002,10 +21244,10 @@ var getHostInfo = (additionalMcpList) => {
|
|
|
21002
21244
|
const ideConfigPaths = /* @__PURE__ */ new Set();
|
|
21003
21245
|
for (const ide of IDEs) {
|
|
21004
21246
|
const configPaths = getMCPConfigPaths(ide);
|
|
21005
|
-
configPaths.forEach((
|
|
21247
|
+
configPaths.forEach((path35) => ideConfigPaths.add(path35));
|
|
21006
21248
|
}
|
|
21007
21249
|
const uniqueAdditionalPaths = additionalMcpList.filter(
|
|
21008
|
-
(
|
|
21250
|
+
(path35) => !ideConfigPaths.has(path35)
|
|
21009
21251
|
);
|
|
21010
21252
|
for (const ide of IDEs) {
|
|
21011
21253
|
const cfg = readMCPConfig(ide);
|
|
@@ -21127,7 +21369,7 @@ init_configs();
|
|
|
21127
21369
|
init_configs();
|
|
21128
21370
|
import fs16 from "fs";
|
|
21129
21371
|
import os9 from "os";
|
|
21130
|
-
import
|
|
21372
|
+
import path24 from "path";
|
|
21131
21373
|
var MAX_DEPTH = 2;
|
|
21132
21374
|
var patterns = ["mcp", "claude"];
|
|
21133
21375
|
var isFileMatch = (fileName) => {
|
|
@@ -21147,7 +21389,7 @@ var searchDir = async (dir, depth = 0) => {
|
|
|
21147
21389
|
if (depth > MAX_DEPTH) return results;
|
|
21148
21390
|
const entries = await fs16.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
21149
21391
|
for (const entry of entries) {
|
|
21150
|
-
const fullPath =
|
|
21392
|
+
const fullPath = path24.join(dir, entry.name);
|
|
21151
21393
|
if (entry.isFile() && isFileMatch(entry.name)) {
|
|
21152
21394
|
results.push(fullPath);
|
|
21153
21395
|
} else if (entry.isDirectory()) {
|
|
@@ -21164,14 +21406,14 @@ var findSystemMCPConfigs = async () => {
|
|
|
21164
21406
|
const home = os9.homedir();
|
|
21165
21407
|
const platform2 = os9.platform();
|
|
21166
21408
|
const knownDirs = platform2 === "win32" ? [
|
|
21167
|
-
|
|
21168
|
-
|
|
21169
|
-
|
|
21409
|
+
path24.join(home, ".cursor"),
|
|
21410
|
+
path24.join(home, "Documents"),
|
|
21411
|
+
path24.join(home, "Downloads")
|
|
21170
21412
|
] : [
|
|
21171
|
-
|
|
21172
|
-
process.env["XDG_CONFIG_HOME"] ||
|
|
21173
|
-
|
|
21174
|
-
|
|
21413
|
+
path24.join(home, ".cursor"),
|
|
21414
|
+
process.env["XDG_CONFIG_HOME"] || path24.join(home, ".config"),
|
|
21415
|
+
path24.join(home, "Documents"),
|
|
21416
|
+
path24.join(home, "Downloads")
|
|
21175
21417
|
];
|
|
21176
21418
|
const timeoutPromise = new Promise(
|
|
21177
21419
|
(resolve) => setTimeout(() => {
|
|
@@ -23587,13 +23829,13 @@ For a complete security audit workflow, use the \`full-security-audit\` prompt.
|
|
|
23587
23829
|
// src/mcp/services/McpDetectionService/CursorMcpDetectionService.ts
|
|
23588
23830
|
import * as fs19 from "fs";
|
|
23589
23831
|
import * as os12 from "os";
|
|
23590
|
-
import * as
|
|
23832
|
+
import * as path26 from "path";
|
|
23591
23833
|
|
|
23592
23834
|
// src/mcp/services/McpDetectionService/BaseMcpDetectionService.ts
|
|
23593
23835
|
init_configs();
|
|
23594
23836
|
import * as fs18 from "fs";
|
|
23595
23837
|
import fetch7 from "node-fetch";
|
|
23596
|
-
import * as
|
|
23838
|
+
import * as path25 from "path";
|
|
23597
23839
|
|
|
23598
23840
|
// src/mcp/services/McpDetectionService/McpDetectionServiceUtils.ts
|
|
23599
23841
|
import * as fs17 from "fs";
|
|
@@ -23602,14 +23844,14 @@ import * as os11 from "os";
|
|
|
23602
23844
|
// src/mcp/services/McpDetectionService/VscodeMcpDetectionService.ts
|
|
23603
23845
|
import * as fs20 from "fs";
|
|
23604
23846
|
import * as os13 from "os";
|
|
23605
|
-
import * as
|
|
23847
|
+
import * as path27 from "path";
|
|
23606
23848
|
|
|
23607
23849
|
// src/mcp/tools/checkForNewAvailableFixes/CheckForNewAvailableFixesTool.ts
|
|
23608
23850
|
import { z as z42 } from "zod";
|
|
23609
23851
|
|
|
23610
23852
|
// src/mcp/services/PathValidation.ts
|
|
23611
23853
|
import fs21 from "fs";
|
|
23612
|
-
import
|
|
23854
|
+
import path28 from "path";
|
|
23613
23855
|
async function validatePath(inputPath) {
|
|
23614
23856
|
logDebug("Validating MCP path", { inputPath });
|
|
23615
23857
|
if (/^\/[a-zA-Z]:\//.test(inputPath)) {
|
|
@@ -23641,7 +23883,7 @@ async function validatePath(inputPath) {
|
|
|
23641
23883
|
logError(error);
|
|
23642
23884
|
return { isValid: false, error, path: inputPath };
|
|
23643
23885
|
}
|
|
23644
|
-
const normalizedPath =
|
|
23886
|
+
const normalizedPath = path28.normalize(inputPath);
|
|
23645
23887
|
if (normalizedPath.includes("..")) {
|
|
23646
23888
|
const error = `Normalized path contains path traversal patterns: ${inputPath}`;
|
|
23647
23889
|
logError(error);
|
|
@@ -24293,7 +24535,7 @@ init_configs();
|
|
|
24293
24535
|
import fs22 from "fs/promises";
|
|
24294
24536
|
import nodePath from "path";
|
|
24295
24537
|
var getLocalFiles = async ({
|
|
24296
|
-
path:
|
|
24538
|
+
path: path35,
|
|
24297
24539
|
maxFileSize = MCP_MAX_FILE_SIZE,
|
|
24298
24540
|
maxFiles,
|
|
24299
24541
|
isAllFilesScan,
|
|
@@ -24301,17 +24543,17 @@ var getLocalFiles = async ({
|
|
|
24301
24543
|
scanRecentlyChangedFiles
|
|
24302
24544
|
}) => {
|
|
24303
24545
|
logDebug(`[${scanContext}] Starting getLocalFiles`, {
|
|
24304
|
-
path:
|
|
24546
|
+
path: path35,
|
|
24305
24547
|
maxFileSize,
|
|
24306
24548
|
maxFiles,
|
|
24307
24549
|
isAllFilesScan,
|
|
24308
24550
|
scanRecentlyChangedFiles
|
|
24309
24551
|
});
|
|
24310
24552
|
try {
|
|
24311
|
-
const resolvedRepoPath = await fs22.realpath(
|
|
24553
|
+
const resolvedRepoPath = await fs22.realpath(path35);
|
|
24312
24554
|
logDebug(`[${scanContext}] Resolved repository path`, {
|
|
24313
24555
|
resolvedRepoPath,
|
|
24314
|
-
originalPath:
|
|
24556
|
+
originalPath: path35
|
|
24315
24557
|
});
|
|
24316
24558
|
const gitService = new GitService(resolvedRepoPath, log);
|
|
24317
24559
|
const gitValidation = await gitService.validateRepository();
|
|
@@ -24324,7 +24566,7 @@ var getLocalFiles = async ({
|
|
|
24324
24566
|
if (!gitValidation.isValid || isAllFilesScan) {
|
|
24325
24567
|
try {
|
|
24326
24568
|
files = await FileUtils.getLastChangedFiles({
|
|
24327
|
-
dir:
|
|
24569
|
+
dir: path35,
|
|
24328
24570
|
maxFileSize,
|
|
24329
24571
|
maxFiles,
|
|
24330
24572
|
isAllFilesScan
|
|
@@ -24416,7 +24658,7 @@ var getLocalFiles = async ({
|
|
|
24416
24658
|
logError(`${scanContext}Unexpected error in getLocalFiles`, {
|
|
24417
24659
|
error: error instanceof Error ? error.message : String(error),
|
|
24418
24660
|
stack: error instanceof Error ? error.stack : void 0,
|
|
24419
|
-
path:
|
|
24661
|
+
path: path35
|
|
24420
24662
|
});
|
|
24421
24663
|
throw error;
|
|
24422
24664
|
}
|
|
@@ -24426,7 +24668,7 @@ var getLocalFiles = async ({
|
|
|
24426
24668
|
init_client_generates();
|
|
24427
24669
|
init_GitService();
|
|
24428
24670
|
import fs23 from "fs";
|
|
24429
|
-
import
|
|
24671
|
+
import path29 from "path";
|
|
24430
24672
|
import { z as z41 } from "zod";
|
|
24431
24673
|
function extractPathFromPatch(patch) {
|
|
24432
24674
|
const match = patch?.match(/diff --git a\/([^\s]+) b\//);
|
|
@@ -24512,7 +24754,7 @@ var LocalMobbFolderService = class {
|
|
|
24512
24754
|
"[LocalMobbFolderService] Non-git repository detected, skipping .gitignore operations"
|
|
24513
24755
|
);
|
|
24514
24756
|
}
|
|
24515
|
-
const mobbFolderPath =
|
|
24757
|
+
const mobbFolderPath = path29.join(
|
|
24516
24758
|
this.repoPath,
|
|
24517
24759
|
this.defaultMobbFolderName
|
|
24518
24760
|
);
|
|
@@ -24684,7 +24926,7 @@ var LocalMobbFolderService = class {
|
|
|
24684
24926
|
mobbFolderPath,
|
|
24685
24927
|
baseFileName
|
|
24686
24928
|
);
|
|
24687
|
-
const filePath =
|
|
24929
|
+
const filePath = path29.join(mobbFolderPath, uniqueFileName);
|
|
24688
24930
|
await fs23.promises.writeFile(filePath, patch, "utf8");
|
|
24689
24931
|
logInfo("[LocalMobbFolderService] Patch saved successfully", {
|
|
24690
24932
|
filePath,
|
|
@@ -24742,11 +24984,11 @@ var LocalMobbFolderService = class {
|
|
|
24742
24984
|
* @returns Unique filename that doesn't conflict with existing files
|
|
24743
24985
|
*/
|
|
24744
24986
|
getUniqueFileName(folderPath, baseFileName) {
|
|
24745
|
-
const baseName =
|
|
24746
|
-
const extension =
|
|
24987
|
+
const baseName = path29.parse(baseFileName).name;
|
|
24988
|
+
const extension = path29.parse(baseFileName).ext;
|
|
24747
24989
|
let uniqueFileName = baseFileName;
|
|
24748
24990
|
let index = 1;
|
|
24749
|
-
while (fs23.existsSync(
|
|
24991
|
+
while (fs23.existsSync(path29.join(folderPath, uniqueFileName))) {
|
|
24750
24992
|
uniqueFileName = `${baseName}-${index}${extension}`;
|
|
24751
24993
|
index++;
|
|
24752
24994
|
if (index > 1e3) {
|
|
@@ -24777,7 +25019,7 @@ var LocalMobbFolderService = class {
|
|
|
24777
25019
|
logDebug("[LocalMobbFolderService] Logging patch info", { fixId: fix.id });
|
|
24778
25020
|
try {
|
|
24779
25021
|
const mobbFolderPath = await this.getFolder();
|
|
24780
|
-
const patchInfoPath =
|
|
25022
|
+
const patchInfoPath = path29.join(mobbFolderPath, "patchInfo.md");
|
|
24781
25023
|
const markdownContent = this.generateFixMarkdown(fix, savedPatchFileName);
|
|
24782
25024
|
let existingContent = "";
|
|
24783
25025
|
if (fs23.existsSync(patchInfoPath)) {
|
|
@@ -24819,7 +25061,7 @@ var LocalMobbFolderService = class {
|
|
|
24819
25061
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
24820
25062
|
const patch = this.extractPatchFromFix(fix);
|
|
24821
25063
|
const relativePatchedFilePath = patch ? extractPathFromPatch(patch) : null;
|
|
24822
|
-
const patchedFilePath = relativePatchedFilePath ?
|
|
25064
|
+
const patchedFilePath = relativePatchedFilePath ? path29.resolve(this.repoPath, relativePatchedFilePath) : null;
|
|
24823
25065
|
const fixIdentifier = savedPatchFileName ? savedPatchFileName.replace(".patch", "") : fix.id;
|
|
24824
25066
|
let markdown = `# Fix ${fixIdentifier}
|
|
24825
25067
|
|
|
@@ -25163,14 +25405,14 @@ import {
|
|
|
25163
25405
|
} from "fs";
|
|
25164
25406
|
import fs24 from "fs/promises";
|
|
25165
25407
|
import parseDiff2 from "parse-diff";
|
|
25166
|
-
import
|
|
25408
|
+
import path30 from "path";
|
|
25167
25409
|
var PatchApplicationService = class {
|
|
25168
25410
|
/**
|
|
25169
25411
|
* Gets the appropriate comment syntax for a file based on its extension
|
|
25170
25412
|
*/
|
|
25171
25413
|
static getCommentSyntax(filePath) {
|
|
25172
|
-
const ext =
|
|
25173
|
-
const basename2 =
|
|
25414
|
+
const ext = path30.extname(filePath).toLowerCase();
|
|
25415
|
+
const basename2 = path30.basename(filePath);
|
|
25174
25416
|
const commentMap = {
|
|
25175
25417
|
// C-style languages (single line comments)
|
|
25176
25418
|
".js": "//",
|
|
@@ -25378,7 +25620,7 @@ var PatchApplicationService = class {
|
|
|
25378
25620
|
}
|
|
25379
25621
|
);
|
|
25380
25622
|
}
|
|
25381
|
-
const dirPath =
|
|
25623
|
+
const dirPath = path30.dirname(normalizedFilePath);
|
|
25382
25624
|
mkdirSync(dirPath, { recursive: true });
|
|
25383
25625
|
writeFileSync3(normalizedFilePath, finalContent, "utf8");
|
|
25384
25626
|
return normalizedFilePath;
|
|
@@ -25387,9 +25629,9 @@ var PatchApplicationService = class {
|
|
|
25387
25629
|
repositoryPath,
|
|
25388
25630
|
targetPath
|
|
25389
25631
|
}) {
|
|
25390
|
-
const repoRoot =
|
|
25391
|
-
const normalizedPath =
|
|
25392
|
-
const repoRootWithSep = repoRoot.endsWith(
|
|
25632
|
+
const repoRoot = path30.resolve(repositoryPath);
|
|
25633
|
+
const normalizedPath = path30.resolve(repoRoot, targetPath);
|
|
25634
|
+
const repoRootWithSep = repoRoot.endsWith(path30.sep) ? repoRoot : `${repoRoot}${path30.sep}`;
|
|
25393
25635
|
if (normalizedPath !== repoRoot && !normalizedPath.startsWith(repoRootWithSep)) {
|
|
25394
25636
|
throw new Error(
|
|
25395
25637
|
`Security violation: target path ${targetPath} resolves outside repository`
|
|
@@ -25398,7 +25640,7 @@ var PatchApplicationService = class {
|
|
|
25398
25640
|
return {
|
|
25399
25641
|
repoRoot,
|
|
25400
25642
|
normalizedPath,
|
|
25401
|
-
relativePath:
|
|
25643
|
+
relativePath: path30.relative(repoRoot, normalizedPath)
|
|
25402
25644
|
};
|
|
25403
25645
|
}
|
|
25404
25646
|
/**
|
|
@@ -25680,7 +25922,7 @@ var PatchApplicationService = class {
|
|
|
25680
25922
|
continue;
|
|
25681
25923
|
}
|
|
25682
25924
|
try {
|
|
25683
|
-
const absolutePath =
|
|
25925
|
+
const absolutePath = path30.resolve(repositoryPath, targetFile);
|
|
25684
25926
|
if (existsSync7(absolutePath)) {
|
|
25685
25927
|
const stats = await fs24.stat(absolutePath);
|
|
25686
25928
|
const fileModTime = stats.mtime.getTime();
|
|
@@ -25906,7 +26148,7 @@ var PatchApplicationService = class {
|
|
|
25906
26148
|
fix,
|
|
25907
26149
|
scanContext
|
|
25908
26150
|
});
|
|
25909
|
-
appliedFiles.push(
|
|
26151
|
+
appliedFiles.push(path30.relative(repositoryPath, actualPath));
|
|
25910
26152
|
logDebug(`[${scanContext}] Created new file: ${relativePath}`);
|
|
25911
26153
|
}
|
|
25912
26154
|
/**
|
|
@@ -25955,7 +26197,7 @@ var PatchApplicationService = class {
|
|
|
25955
26197
|
fix,
|
|
25956
26198
|
scanContext
|
|
25957
26199
|
});
|
|
25958
|
-
appliedFiles.push(
|
|
26200
|
+
appliedFiles.push(path30.relative(repositoryPath, actualPath));
|
|
25959
26201
|
logDebug(`[${scanContext}] Modified file: ${relativePath}`);
|
|
25960
26202
|
}
|
|
25961
26203
|
}
|
|
@@ -26152,7 +26394,7 @@ init_configs();
|
|
|
26152
26394
|
// src/mcp/services/FileOperations.ts
|
|
26153
26395
|
init_FileUtils();
|
|
26154
26396
|
import fs25 from "fs";
|
|
26155
|
-
import
|
|
26397
|
+
import path31 from "path";
|
|
26156
26398
|
import AdmZip4 from "adm-zip";
|
|
26157
26399
|
var FileOperations = class {
|
|
26158
26400
|
/**
|
|
@@ -26172,10 +26414,10 @@ var FileOperations = class {
|
|
|
26172
26414
|
let packedFilesCount = 0;
|
|
26173
26415
|
const packedFiles = [];
|
|
26174
26416
|
const excludedFiles = [];
|
|
26175
|
-
const resolvedRepoPath =
|
|
26417
|
+
const resolvedRepoPath = path31.resolve(repositoryPath);
|
|
26176
26418
|
for (const filepath of fileList) {
|
|
26177
|
-
const absoluteFilepath =
|
|
26178
|
-
const resolvedFilePath =
|
|
26419
|
+
const absoluteFilepath = path31.join(repositoryPath, filepath);
|
|
26420
|
+
const resolvedFilePath = path31.resolve(absoluteFilepath);
|
|
26179
26421
|
if (!resolvedFilePath.startsWith(resolvedRepoPath)) {
|
|
26180
26422
|
const reason = "potential path traversal security risk";
|
|
26181
26423
|
logDebug(`[FileOperations] Skipping ${filepath} due to ${reason}`);
|
|
@@ -26222,11 +26464,11 @@ var FileOperations = class {
|
|
|
26222
26464
|
fileList,
|
|
26223
26465
|
repositoryPath
|
|
26224
26466
|
}) {
|
|
26225
|
-
const resolvedRepoPath =
|
|
26467
|
+
const resolvedRepoPath = path31.resolve(repositoryPath);
|
|
26226
26468
|
const validatedPaths = [];
|
|
26227
26469
|
for (const filepath of fileList) {
|
|
26228
|
-
const absoluteFilepath =
|
|
26229
|
-
const resolvedFilePath =
|
|
26470
|
+
const absoluteFilepath = path31.join(repositoryPath, filepath);
|
|
26471
|
+
const resolvedFilePath = path31.resolve(absoluteFilepath);
|
|
26230
26472
|
if (!resolvedFilePath.startsWith(resolvedRepoPath)) {
|
|
26231
26473
|
logDebug(
|
|
26232
26474
|
`[FileOperations] Rejecting ${filepath} - path traversal attempt detected`
|
|
@@ -26254,7 +26496,7 @@ var FileOperations = class {
|
|
|
26254
26496
|
for (const absolutePath of filePaths) {
|
|
26255
26497
|
try {
|
|
26256
26498
|
const content = await fs25.promises.readFile(absolutePath);
|
|
26257
|
-
const relativePath =
|
|
26499
|
+
const relativePath = path31.basename(absolutePath);
|
|
26258
26500
|
fileDataArray.push({
|
|
26259
26501
|
relativePath,
|
|
26260
26502
|
absolutePath,
|
|
@@ -26566,14 +26808,14 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
26566
26808
|
* since the last scan.
|
|
26567
26809
|
*/
|
|
26568
26810
|
async scanForSecurityVulnerabilities({
|
|
26569
|
-
path:
|
|
26811
|
+
path: path35,
|
|
26570
26812
|
isAllDetectionRulesScan,
|
|
26571
26813
|
isAllFilesScan,
|
|
26572
26814
|
scanContext
|
|
26573
26815
|
}) {
|
|
26574
26816
|
this.hasAuthenticationFailed = false;
|
|
26575
26817
|
logDebug(`[${scanContext}] Scanning for new security vulnerabilities`, {
|
|
26576
|
-
path:
|
|
26818
|
+
path: path35
|
|
26577
26819
|
});
|
|
26578
26820
|
if (!this.gqlClient) {
|
|
26579
26821
|
logInfo(`[${scanContext}] No GQL client found, skipping scan`);
|
|
@@ -26589,11 +26831,11 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
26589
26831
|
}
|
|
26590
26832
|
logDebug(
|
|
26591
26833
|
`[${scanContext}] Connected to the API, assembling list of files to scan`,
|
|
26592
|
-
{ path:
|
|
26834
|
+
{ path: path35 }
|
|
26593
26835
|
);
|
|
26594
26836
|
const isBackgroundScan = scanContext === ScanContext.BACKGROUND_INITIAL || scanContext === ScanContext.BACKGROUND_PERIODIC;
|
|
26595
26837
|
const files = await getLocalFiles({
|
|
26596
|
-
path:
|
|
26838
|
+
path: path35,
|
|
26597
26839
|
isAllFilesScan,
|
|
26598
26840
|
scanContext,
|
|
26599
26841
|
scanRecentlyChangedFiles: !isBackgroundScan
|
|
@@ -26619,13 +26861,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
26619
26861
|
});
|
|
26620
26862
|
const { fixReportId, projectId } = await scanFiles({
|
|
26621
26863
|
fileList: filesToScan.map((file) => file.relativePath),
|
|
26622
|
-
repositoryPath:
|
|
26864
|
+
repositoryPath: path35,
|
|
26623
26865
|
gqlClient: this.gqlClient,
|
|
26624
26866
|
isAllDetectionRulesScan,
|
|
26625
26867
|
scanContext
|
|
26626
26868
|
});
|
|
26627
26869
|
logInfo(
|
|
26628
|
-
`[${scanContext}] Security scan completed for ${
|
|
26870
|
+
`[${scanContext}] Security scan completed for ${path35} reportId: ${fixReportId} projectId: ${projectId}`
|
|
26629
26871
|
);
|
|
26630
26872
|
if (isAllFilesScan) {
|
|
26631
26873
|
return;
|
|
@@ -26919,13 +27161,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
26919
27161
|
});
|
|
26920
27162
|
return scannedFiles.some((file) => file.relativePath === fixFile);
|
|
26921
27163
|
}
|
|
26922
|
-
async getFreshFixes({ path:
|
|
27164
|
+
async getFreshFixes({ path: path35 }) {
|
|
26923
27165
|
const scanContext = ScanContext.USER_REQUEST;
|
|
26924
|
-
logDebug(`[${scanContext}] Getting fresh fixes`, { path:
|
|
26925
|
-
if (this.path !==
|
|
26926
|
-
this.path =
|
|
27166
|
+
logDebug(`[${scanContext}] Getting fresh fixes`, { path: path35 });
|
|
27167
|
+
if (this.path !== path35) {
|
|
27168
|
+
this.path = path35;
|
|
26927
27169
|
this.reset();
|
|
26928
|
-
logInfo(`[${scanContext}] Reset service state for new path`, { path:
|
|
27170
|
+
logInfo(`[${scanContext}] Reset service state for new path`, { path: path35 });
|
|
26929
27171
|
}
|
|
26930
27172
|
try {
|
|
26931
27173
|
const loginContext = createMcpLoginContext("check_new_fixes");
|
|
@@ -26944,7 +27186,7 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
26944
27186
|
}
|
|
26945
27187
|
throw error;
|
|
26946
27188
|
}
|
|
26947
|
-
this.triggerScan({ path:
|
|
27189
|
+
this.triggerScan({ path: path35, gqlClient: this.gqlClient });
|
|
26948
27190
|
let isMvsAutoFixEnabled = null;
|
|
26949
27191
|
try {
|
|
26950
27192
|
isMvsAutoFixEnabled = await this.gqlClient.getMvsAutoFixSettings();
|
|
@@ -26978,33 +27220,33 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
26978
27220
|
return noFreshFixesPrompt;
|
|
26979
27221
|
}
|
|
26980
27222
|
triggerScan({
|
|
26981
|
-
path:
|
|
27223
|
+
path: path35,
|
|
26982
27224
|
gqlClient
|
|
26983
27225
|
}) {
|
|
26984
|
-
if (this.path !==
|
|
26985
|
-
this.path =
|
|
27226
|
+
if (this.path !== path35) {
|
|
27227
|
+
this.path = path35;
|
|
26986
27228
|
this.reset();
|
|
26987
|
-
logInfo(`Reset service state for new path in triggerScan`, { path:
|
|
27229
|
+
logInfo(`Reset service state for new path in triggerScan`, { path: path35 });
|
|
26988
27230
|
}
|
|
26989
27231
|
this.gqlClient = gqlClient;
|
|
26990
27232
|
if (!this.intervalId) {
|
|
26991
|
-
this.startPeriodicScanning(
|
|
26992
|
-
this.executeInitialScan(
|
|
26993
|
-
void this.executeInitialFullScan(
|
|
27233
|
+
this.startPeriodicScanning(path35);
|
|
27234
|
+
this.executeInitialScan(path35);
|
|
27235
|
+
void this.executeInitialFullScan(path35);
|
|
26994
27236
|
}
|
|
26995
27237
|
}
|
|
26996
|
-
startPeriodicScanning(
|
|
27238
|
+
startPeriodicScanning(path35) {
|
|
26997
27239
|
const scanContext = ScanContext.BACKGROUND_PERIODIC;
|
|
26998
27240
|
logDebug(
|
|
26999
27241
|
`[${scanContext}] Starting periodic scan for new security vulnerabilities`,
|
|
27000
27242
|
{
|
|
27001
|
-
path:
|
|
27243
|
+
path: path35
|
|
27002
27244
|
}
|
|
27003
27245
|
);
|
|
27004
27246
|
this.intervalId = setInterval(() => {
|
|
27005
|
-
logDebug(`[${scanContext}] Triggering periodic security scan`, { path:
|
|
27247
|
+
logDebug(`[${scanContext}] Triggering periodic security scan`, { path: path35 });
|
|
27006
27248
|
this.scanForSecurityVulnerabilities({
|
|
27007
|
-
path:
|
|
27249
|
+
path: path35,
|
|
27008
27250
|
scanContext
|
|
27009
27251
|
}).catch((error) => {
|
|
27010
27252
|
logError(`[${scanContext}] Error during periodic security scan`, {
|
|
@@ -27013,45 +27255,45 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
27013
27255
|
});
|
|
27014
27256
|
}, MCP_PERIODIC_CHECK_INTERVAL);
|
|
27015
27257
|
}
|
|
27016
|
-
async executeInitialFullScan(
|
|
27258
|
+
async executeInitialFullScan(path35) {
|
|
27017
27259
|
const scanContext = ScanContext.FULL_SCAN;
|
|
27018
|
-
logDebug(`[${scanContext}] Triggering initial full security scan`, { path:
|
|
27260
|
+
logDebug(`[${scanContext}] Triggering initial full security scan`, { path: path35 });
|
|
27019
27261
|
logDebug(`[${scanContext}] Full scan paths scanned`, {
|
|
27020
27262
|
fullScanPathsScanned: this.fullScanPathsScanned
|
|
27021
27263
|
});
|
|
27022
|
-
if (this.fullScanPathsScanned.includes(
|
|
27264
|
+
if (this.fullScanPathsScanned.includes(path35)) {
|
|
27023
27265
|
logDebug(`[${scanContext}] Full scan already executed for this path`, {
|
|
27024
|
-
path:
|
|
27266
|
+
path: path35
|
|
27025
27267
|
});
|
|
27026
27268
|
return;
|
|
27027
27269
|
}
|
|
27028
27270
|
configStore.set("fullScanPathsScanned", [
|
|
27029
27271
|
...this.fullScanPathsScanned,
|
|
27030
|
-
|
|
27272
|
+
path35
|
|
27031
27273
|
]);
|
|
27032
27274
|
try {
|
|
27033
27275
|
await this.scanForSecurityVulnerabilities({
|
|
27034
|
-
path:
|
|
27276
|
+
path: path35,
|
|
27035
27277
|
isAllFilesScan: true,
|
|
27036
27278
|
isAllDetectionRulesScan: true,
|
|
27037
27279
|
scanContext: ScanContext.FULL_SCAN
|
|
27038
27280
|
});
|
|
27039
|
-
if (!this.fullScanPathsScanned.includes(
|
|
27040
|
-
this.fullScanPathsScanned.push(
|
|
27281
|
+
if (!this.fullScanPathsScanned.includes(path35)) {
|
|
27282
|
+
this.fullScanPathsScanned.push(path35);
|
|
27041
27283
|
configStore.set("fullScanPathsScanned", this.fullScanPathsScanned);
|
|
27042
27284
|
}
|
|
27043
|
-
logInfo(`[${scanContext}] Full scan completed`, { path:
|
|
27285
|
+
logInfo(`[${scanContext}] Full scan completed`, { path: path35 });
|
|
27044
27286
|
} catch (error) {
|
|
27045
27287
|
logError(`[${scanContext}] Error during initial full security scan`, {
|
|
27046
27288
|
error
|
|
27047
27289
|
});
|
|
27048
27290
|
}
|
|
27049
27291
|
}
|
|
27050
|
-
executeInitialScan(
|
|
27292
|
+
executeInitialScan(path35) {
|
|
27051
27293
|
const scanContext = ScanContext.BACKGROUND_INITIAL;
|
|
27052
|
-
logDebug(`[${scanContext}] Triggering initial security scan`, { path:
|
|
27294
|
+
logDebug(`[${scanContext}] Triggering initial security scan`, { path: path35 });
|
|
27053
27295
|
this.scanForSecurityVulnerabilities({
|
|
27054
|
-
path:
|
|
27296
|
+
path: path35,
|
|
27055
27297
|
scanContext: ScanContext.BACKGROUND_INITIAL
|
|
27056
27298
|
}).catch((error) => {
|
|
27057
27299
|
logError(`[${scanContext}] Error during initial security scan`, { error });
|
|
@@ -27148,9 +27390,9 @@ Example payload:
|
|
|
27148
27390
|
`Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
|
|
27149
27391
|
);
|
|
27150
27392
|
}
|
|
27151
|
-
const
|
|
27393
|
+
const path35 = pathValidationResult.path;
|
|
27152
27394
|
const resultText = await this.newFixesService.getFreshFixes({
|
|
27153
|
-
path:
|
|
27395
|
+
path: path35
|
|
27154
27396
|
});
|
|
27155
27397
|
logInfo("CheckForNewAvailableFixesTool execution completed", {
|
|
27156
27398
|
resultText
|
|
@@ -27328,8 +27570,8 @@ Call this tool instead of ${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES} when you only
|
|
|
27328
27570
|
`Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
|
|
27329
27571
|
);
|
|
27330
27572
|
}
|
|
27331
|
-
const
|
|
27332
|
-
const gitService = new GitService(
|
|
27573
|
+
const path35 = pathValidationResult.path;
|
|
27574
|
+
const gitService = new GitService(path35, log);
|
|
27333
27575
|
const gitValidation = await gitService.validateRepository();
|
|
27334
27576
|
if (!gitValidation.isValid) {
|
|
27335
27577
|
throw new Error(`Invalid git repository: ${gitValidation.error}`);
|
|
@@ -27714,9 +27956,9 @@ Example payload:
|
|
|
27714
27956
|
`Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
|
|
27715
27957
|
);
|
|
27716
27958
|
}
|
|
27717
|
-
const
|
|
27959
|
+
const path35 = pathValidationResult.path;
|
|
27718
27960
|
const files = await getLocalFiles({
|
|
27719
|
-
path:
|
|
27961
|
+
path: path35,
|
|
27720
27962
|
maxFileSize: MCP_MAX_FILE_SIZE,
|
|
27721
27963
|
maxFiles: args.maxFiles,
|
|
27722
27964
|
scanContext: ScanContext.USER_REQUEST,
|
|
@@ -27736,7 +27978,7 @@ Example payload:
|
|
|
27736
27978
|
try {
|
|
27737
27979
|
const fixResult = await this.vulnerabilityFixService.processVulnerabilities({
|
|
27738
27980
|
fileList: files.map((file) => file.relativePath),
|
|
27739
|
-
repositoryPath:
|
|
27981
|
+
repositoryPath: path35,
|
|
27740
27982
|
offset: args.offset,
|
|
27741
27983
|
limit: args.limit,
|
|
27742
27984
|
isRescan: args.rescan || !!args.maxFiles
|
|
@@ -28037,10 +28279,10 @@ init_client_generates();
|
|
|
28037
28279
|
init_urlParser2();
|
|
28038
28280
|
|
|
28039
28281
|
// src/features/codeium_intellij/codeium_language_server_grpc_client.ts
|
|
28040
|
-
import
|
|
28282
|
+
import path32 from "path";
|
|
28041
28283
|
import * as grpc from "@grpc/grpc-js";
|
|
28042
28284
|
import * as protoLoader from "@grpc/proto-loader";
|
|
28043
|
-
var PROTO_PATH =
|
|
28285
|
+
var PROTO_PATH = path32.join(
|
|
28044
28286
|
getModuleRootDir(),
|
|
28045
28287
|
"src/features/codeium_intellij/proto/exa/language_server_pb/language_server.proto"
|
|
28046
28288
|
);
|
|
@@ -28052,7 +28294,7 @@ function loadProto() {
|
|
|
28052
28294
|
defaults: true,
|
|
28053
28295
|
oneofs: true,
|
|
28054
28296
|
includeDirs: [
|
|
28055
|
-
|
|
28297
|
+
path32.join(getModuleRootDir(), "src/features/codeium_intellij/proto")
|
|
28056
28298
|
]
|
|
28057
28299
|
});
|
|
28058
28300
|
return grpc.loadPackageDefinition(
|
|
@@ -28108,28 +28350,28 @@ async function getGrpcClient(port, csrf3) {
|
|
|
28108
28350
|
// src/features/codeium_intellij/parse_intellij_logs.ts
|
|
28109
28351
|
import fs27 from "fs";
|
|
28110
28352
|
import os14 from "os";
|
|
28111
|
-
import
|
|
28353
|
+
import path33 from "path";
|
|
28112
28354
|
function getLogsDir() {
|
|
28113
28355
|
if (process.platform === "darwin") {
|
|
28114
|
-
return
|
|
28356
|
+
return path33.join(os14.homedir(), "Library/Logs/JetBrains");
|
|
28115
28357
|
} else if (process.platform === "win32") {
|
|
28116
|
-
return
|
|
28117
|
-
process.env["LOCALAPPDATA"] ||
|
|
28358
|
+
return path33.join(
|
|
28359
|
+
process.env["LOCALAPPDATA"] || path33.join(os14.homedir(), "AppData/Local"),
|
|
28118
28360
|
"JetBrains"
|
|
28119
28361
|
);
|
|
28120
28362
|
} else {
|
|
28121
|
-
return
|
|
28363
|
+
return path33.join(os14.homedir(), ".cache/JetBrains");
|
|
28122
28364
|
}
|
|
28123
28365
|
}
|
|
28124
28366
|
function parseIdeLogDir(ideLogDir) {
|
|
28125
28367
|
const logFiles = fs27.readdirSync(ideLogDir).filter((f) => /^idea(\.\d+)?\.log$/.test(f)).map((f) => ({
|
|
28126
28368
|
name: f,
|
|
28127
|
-
mtime: fs27.statSync(
|
|
28369
|
+
mtime: fs27.statSync(path33.join(ideLogDir, f)).mtimeMs
|
|
28128
28370
|
})).sort((a, b) => a.mtime - b.mtime).map((f) => f.name);
|
|
28129
28371
|
let latestCsrf = null;
|
|
28130
28372
|
let latestPort = null;
|
|
28131
28373
|
for (const logFile of logFiles) {
|
|
28132
|
-
const lines = fs27.readFileSync(
|
|
28374
|
+
const lines = fs27.readFileSync(path33.join(ideLogDir, logFile), "utf-8").split("\n");
|
|
28133
28375
|
for (const line of lines) {
|
|
28134
28376
|
if (!line.includes(
|
|
28135
28377
|
"com.codeium.intellij.language_server.LanguageServerProcessHandler"
|
|
@@ -28157,9 +28399,9 @@ function findRunningCodeiumLanguageServers() {
|
|
|
28157
28399
|
const logsDir = getLogsDir();
|
|
28158
28400
|
if (!fs27.existsSync(logsDir)) return results;
|
|
28159
28401
|
for (const ide of fs27.readdirSync(logsDir)) {
|
|
28160
|
-
let ideLogDir =
|
|
28402
|
+
let ideLogDir = path33.join(logsDir, ide);
|
|
28161
28403
|
if (process.platform !== "darwin") {
|
|
28162
|
-
ideLogDir =
|
|
28404
|
+
ideLogDir = path33.join(ideLogDir, "log");
|
|
28163
28405
|
}
|
|
28164
28406
|
if (!fs27.existsSync(ideLogDir) || !fs27.statSync(ideLogDir).isDirectory()) {
|
|
28165
28407
|
continue;
|
|
@@ -28342,10 +28584,10 @@ function processChatStepCodeAction(step) {
|
|
|
28342
28584
|
// src/features/codeium_intellij/install_hook.ts
|
|
28343
28585
|
import fsPromises5 from "fs/promises";
|
|
28344
28586
|
import os15 from "os";
|
|
28345
|
-
import
|
|
28587
|
+
import path34 from "path";
|
|
28346
28588
|
import chalk14 from "chalk";
|
|
28347
28589
|
function getCodeiumHooksPath() {
|
|
28348
|
-
return
|
|
28590
|
+
return path34.join(os15.homedir(), ".codeium", "hooks.json");
|
|
28349
28591
|
}
|
|
28350
28592
|
async function readCodeiumHooks() {
|
|
28351
28593
|
const hooksPath = getCodeiumHooksPath();
|
|
@@ -28358,7 +28600,7 @@ async function readCodeiumHooks() {
|
|
|
28358
28600
|
}
|
|
28359
28601
|
async function writeCodeiumHooks(config2) {
|
|
28360
28602
|
const hooksPath = getCodeiumHooksPath();
|
|
28361
|
-
const dir =
|
|
28603
|
+
const dir = path34.dirname(hooksPath);
|
|
28362
28604
|
await fsPromises5.mkdir(dir, { recursive: true });
|
|
28363
28605
|
await fsPromises5.writeFile(
|
|
28364
28606
|
hooksPath,
|