mobbdev 1.4.21 → 1.4.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/args/commands/upload_ai_blame.mjs +72 -20
- package/dist/index.mjs +481 -302
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -417,6 +417,7 @@ var init_client_generates = __esm({
|
|
|
417
417
|
return Vulnerability_Report_Issue_State_Enum2;
|
|
418
418
|
})(Vulnerability_Report_Issue_State_Enum || {});
|
|
419
419
|
Vulnerability_Report_Issue_Tag_Enum = /* @__PURE__ */ ((Vulnerability_Report_Issue_Tag_Enum3) => {
|
|
420
|
+
Vulnerability_Report_Issue_Tag_Enum3["AgenticRemediationInProgress"] = "AGENTIC_REMEDIATION_IN_PROGRESS";
|
|
420
421
|
Vulnerability_Report_Issue_Tag_Enum3["AutogeneratedCode"] = "AUTOGENERATED_CODE";
|
|
421
422
|
Vulnerability_Report_Issue_Tag_Enum3["AuxiliaryCode"] = "AUXILIARY_CODE";
|
|
422
423
|
Vulnerability_Report_Issue_Tag_Enum3["FalsePositive"] = "FALSE_POSITIVE";
|
|
@@ -1592,7 +1593,8 @@ var init_getIssueType = __esm({
|
|
|
1592
1593
|
["TEST_CODE" /* TestCode */]: "The flagged code resides in a test-specific path or context. This categorization indicates that **it supports testing scenarios and is isolated from production use**.",
|
|
1593
1594
|
["UNFIXABLE" /* Unfixable */]: "The flagged code cannot be fixed",
|
|
1594
1595
|
["VENDOR_CODE" /* VendorCode */]: "The flagged code originates from a third-party library or dependency maintained externally. This categorization suggests that **the issue lies outside the application's direct control** and should be addressed by the vendor if necessary.",
|
|
1595
|
-
["SUPPRESSED" /* Suppressed */]: "Suppressed in the scan report."
|
|
1596
|
+
["SUPPRESSED" /* Suppressed */]: "Suppressed in the scan report.",
|
|
1597
|
+
["AGENTIC_REMEDIATION_IN_PROGRESS" /* AgenticRemediationInProgress */]: "Mobb is currently retrying remediation on this issue. The state will refresh automatically once the run finishes."
|
|
1596
1598
|
};
|
|
1597
1599
|
}
|
|
1598
1600
|
});
|
|
@@ -3872,9 +3874,9 @@ var init_GitService = __esm({
|
|
|
3872
3874
|
this.log("[GitService] Git repository validation successful", "debug");
|
|
3873
3875
|
return { isValid: true };
|
|
3874
3876
|
} catch (error) {
|
|
3875
|
-
const
|
|
3876
|
-
this.log(`[GitService] ${
|
|
3877
|
-
return { isValid: false, error:
|
|
3877
|
+
const errorMessage3 = `Failed to verify git repository: ${error.message}`;
|
|
3878
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
3879
|
+
return { isValid: false, error: errorMessage3 };
|
|
3878
3880
|
}
|
|
3879
3881
|
}
|
|
3880
3882
|
/**
|
|
@@ -3920,9 +3922,9 @@ var init_GitService = __esm({
|
|
|
3920
3922
|
});
|
|
3921
3923
|
return { files, deletedFiles, status };
|
|
3922
3924
|
} catch (error) {
|
|
3923
|
-
const
|
|
3924
|
-
this.log(`[GitService] ${
|
|
3925
|
-
throw new Error(
|
|
3925
|
+
const errorMessage3 = `Failed to get git status: ${error.message}`;
|
|
3926
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
3927
|
+
throw new Error(errorMessage3);
|
|
3926
3928
|
}
|
|
3927
3929
|
}
|
|
3928
3930
|
/**
|
|
@@ -3948,9 +3950,9 @@ var init_GitService = __esm({
|
|
|
3948
3950
|
reference
|
|
3949
3951
|
};
|
|
3950
3952
|
} catch (error) {
|
|
3951
|
-
const
|
|
3952
|
-
this.log(`[GitService] ${
|
|
3953
|
-
throw new Error(
|
|
3953
|
+
const errorMessage3 = `Failed to get git repository information: ${error.message}`;
|
|
3954
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
3955
|
+
throw new Error(errorMessage3);
|
|
3954
3956
|
}
|
|
3955
3957
|
}
|
|
3956
3958
|
/**
|
|
@@ -3988,9 +3990,9 @@ var init_GitService = __esm({
|
|
|
3988
3990
|
this.log("[GitService] Current branch retrieved", "debug", { branch });
|
|
3989
3991
|
return branch;
|
|
3990
3992
|
} catch (error) {
|
|
3991
|
-
const
|
|
3992
|
-
this.log(`[GitService] ${
|
|
3993
|
-
throw new Error(
|
|
3993
|
+
const errorMessage3 = `Failed to get current branch: ${error.message}`;
|
|
3994
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
3995
|
+
throw new Error(errorMessage3);
|
|
3994
3996
|
}
|
|
3995
3997
|
}
|
|
3996
3998
|
/**
|
|
@@ -4003,9 +4005,9 @@ var init_GitService = __esm({
|
|
|
4003
4005
|
this.log("[GitService] Current commit hash retrieved", "debug", { hash });
|
|
4004
4006
|
return hash;
|
|
4005
4007
|
} catch (error) {
|
|
4006
|
-
const
|
|
4007
|
-
this.log(`[GitService] ${
|
|
4008
|
-
throw new Error(
|
|
4008
|
+
const errorMessage3 = `Failed to get current commit hash: ${error.message}`;
|
|
4009
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
4010
|
+
throw new Error(errorMessage3);
|
|
4009
4011
|
}
|
|
4010
4012
|
}
|
|
4011
4013
|
/**
|
|
@@ -4053,8 +4055,8 @@ var init_GitService = __esm({
|
|
|
4053
4055
|
);
|
|
4054
4056
|
return { hash, branch };
|
|
4055
4057
|
} catch (error) {
|
|
4056
|
-
const
|
|
4057
|
-
this.log(`[GitService] ${
|
|
4058
|
+
const errorMessage3 = `Failed to get current commit hash and branch: ${error.message}`;
|
|
4059
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
4058
4060
|
return { hash: "", branch: "" };
|
|
4059
4061
|
}
|
|
4060
4062
|
}
|
|
@@ -4072,9 +4074,9 @@ var init_GitService = __esm({
|
|
|
4072
4074
|
});
|
|
4073
4075
|
return normalizedUrl;
|
|
4074
4076
|
} catch (error) {
|
|
4075
|
-
const
|
|
4076
|
-
this.log(`[GitService] ${
|
|
4077
|
-
throw new Error(
|
|
4077
|
+
const errorMessage3 = `Failed to get remote repository URL: ${error.message}`;
|
|
4078
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
4079
|
+
throw new Error(errorMessage3);
|
|
4078
4080
|
}
|
|
4079
4081
|
}
|
|
4080
4082
|
/**
|
|
@@ -4195,9 +4197,9 @@ var init_GitService = __esm({
|
|
|
4195
4197
|
commitCount: commitsProcessed
|
|
4196
4198
|
};
|
|
4197
4199
|
} catch (error) {
|
|
4198
|
-
const
|
|
4199
|
-
this.log(`[GitService] ${
|
|
4200
|
-
throw new Error(
|
|
4200
|
+
const errorMessage3 = `Failed to get recently changed files: ${error.message}`;
|
|
4201
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
4202
|
+
throw new Error(errorMessage3);
|
|
4201
4203
|
}
|
|
4202
4204
|
}
|
|
4203
4205
|
/**
|
|
@@ -4241,8 +4243,8 @@ ${rootContent}`;
|
|
|
4241
4243
|
);
|
|
4242
4244
|
return combinedContent.trimEnd();
|
|
4243
4245
|
} catch (error) {
|
|
4244
|
-
const
|
|
4245
|
-
this.log(`[GitService] ${
|
|
4246
|
+
const errorMessage3 = `Failed to get .gitignore contents: ${error.message}`;
|
|
4247
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
4246
4248
|
return null;
|
|
4247
4249
|
}
|
|
4248
4250
|
}
|
|
@@ -4262,9 +4264,9 @@ ${rootContent}`;
|
|
|
4262
4264
|
this.log("[GitService] Git root retrieved", "debug", { gitRoot });
|
|
4263
4265
|
return gitRoot;
|
|
4264
4266
|
} catch (error) {
|
|
4265
|
-
const
|
|
4266
|
-
this.log(`[GitService] ${
|
|
4267
|
-
throw new Error(
|
|
4267
|
+
const errorMessage3 = `Failed to get git repository root: ${error.message}`;
|
|
4268
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
4269
|
+
throw new Error(errorMessage3);
|
|
4268
4270
|
}
|
|
4269
4271
|
}
|
|
4270
4272
|
/**
|
|
@@ -4303,9 +4305,9 @@ ${rootContent}`;
|
|
|
4303
4305
|
});
|
|
4304
4306
|
return true;
|
|
4305
4307
|
} catch (error) {
|
|
4306
|
-
const
|
|
4307
|
-
this.log(`[GitService] ${
|
|
4308
|
-
throw new Error(
|
|
4308
|
+
const errorMessage3 = `Failed to ensure .gitignore entry: ${error.message}`;
|
|
4309
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error, entry });
|
|
4310
|
+
throw new Error(errorMessage3);
|
|
4309
4311
|
}
|
|
4310
4312
|
}
|
|
4311
4313
|
/**
|
|
@@ -4323,9 +4325,9 @@ ${rootContent}`;
|
|
|
4323
4325
|
});
|
|
4324
4326
|
return exists2;
|
|
4325
4327
|
} catch (error) {
|
|
4326
|
-
const
|
|
4327
|
-
this.log(`[GitService] ${
|
|
4328
|
-
throw new Error(
|
|
4328
|
+
const errorMessage3 = `Failed to check .gitignore existence: ${error.message}`;
|
|
4329
|
+
this.log(`[GitService] ${errorMessage3}`, "error", { error });
|
|
4330
|
+
throw new Error(errorMessage3);
|
|
4329
4331
|
}
|
|
4330
4332
|
}
|
|
4331
4333
|
/**
|
|
@@ -4385,8 +4387,8 @@ ${rootContent}`;
|
|
|
4385
4387
|
coAuthors: parsed.coAuthors
|
|
4386
4388
|
};
|
|
4387
4389
|
} catch (error) {
|
|
4388
|
-
const
|
|
4389
|
-
this.log(`[GitService] ${
|
|
4390
|
+
const errorMessage3 = `Failed to get local commit data: ${error.message}`;
|
|
4391
|
+
this.log(`[GitService] ${errorMessage3}`, "debug", { error, commitSha });
|
|
4390
4392
|
return null;
|
|
4391
4393
|
}
|
|
4392
4394
|
}
|
|
@@ -4395,7 +4397,7 @@ ${rootContent}`;
|
|
|
4395
4397
|
});
|
|
4396
4398
|
|
|
4397
4399
|
// src/index.ts
|
|
4398
|
-
import
|
|
4400
|
+
import Debug23 from "debug";
|
|
4399
4401
|
import { hideBin } from "yargs/helpers";
|
|
4400
4402
|
|
|
4401
4403
|
// src/args/yargs.ts
|
|
@@ -9325,8 +9327,8 @@ function handleGitHubError(error, scmType = "GitHub" /* GitHub */) {
|
|
|
9325
9327
|
(Number.parseInt(headers["x-ratelimit-reset"], 10) * 1e3 - Date.now()) / 1e3
|
|
9326
9328
|
)
|
|
9327
9329
|
) : void 0;
|
|
9328
|
-
const
|
|
9329
|
-
if (status === 403 && retryAfter !== void 0 ||
|
|
9330
|
+
const errorMessage3 = errorObj.message || (error instanceof Error ? error.message : String(error));
|
|
9331
|
+
if (status === 403 && retryAfter !== void 0 || errorMessage3.toLowerCase().includes("rate limit") || errorMessage3.toLowerCase().includes("api rate limit exceeded")) {
|
|
9330
9332
|
throw new RateLimitError(
|
|
9331
9333
|
"GitHub API rate limit exceeded",
|
|
9332
9334
|
scmType,
|
|
@@ -9354,7 +9356,7 @@ function handleGitHubError(error, scmType = "GitHub" /* GitHub */) {
|
|
|
9354
9356
|
const errorCode = errorObj.code || errorObj.response?.code;
|
|
9355
9357
|
if (errorCode === "ECONNREFUSED" || errorCode === "ETIMEDOUT" || errorCode === "ENOTFOUND" || errorCode === "EAI_AGAIN") {
|
|
9356
9358
|
throw new NetworkError(
|
|
9357
|
-
`GitHub network error: ${
|
|
9359
|
+
`GitHub network error: ${errorMessage3}`,
|
|
9358
9360
|
scmType,
|
|
9359
9361
|
errorCode
|
|
9360
9362
|
);
|
|
@@ -9362,7 +9364,7 @@ function handleGitHubError(error, scmType = "GitHub" /* GitHub */) {
|
|
|
9362
9364
|
if (error instanceof RateLimitError || error instanceof InvalidAccessTokenError || error instanceof ScmBadCredentialsError || error instanceof InvalidRepoUrlError || error instanceof NetworkError || error instanceof InvalidUrlPatternError) {
|
|
9363
9365
|
throw error;
|
|
9364
9366
|
}
|
|
9365
|
-
throw new Error(`GitHub API error: ${
|
|
9367
|
+
throw new Error(`GitHub API error: ${errorMessage3}`);
|
|
9366
9368
|
}
|
|
9367
9369
|
async function githubValidateParams(url, accessToken) {
|
|
9368
9370
|
try {
|
|
@@ -13112,7 +13114,7 @@ import path10 from "path";
|
|
|
13112
13114
|
import { env as env2 } from "process";
|
|
13113
13115
|
import { pipeline } from "stream/promises";
|
|
13114
13116
|
import chalk7 from "chalk";
|
|
13115
|
-
import
|
|
13117
|
+
import Debug22 from "debug";
|
|
13116
13118
|
import extract from "extract-zip";
|
|
13117
13119
|
import { createSpinner as createSpinner4 } from "nanospinner";
|
|
13118
13120
|
import fetch4 from "node-fetch";
|
|
@@ -13123,7 +13125,7 @@ import { z as z31 } from "zod";
|
|
|
13123
13125
|
// src/commands/AuthManager.ts
|
|
13124
13126
|
import crypto from "crypto";
|
|
13125
13127
|
import os3 from "os";
|
|
13126
|
-
import
|
|
13128
|
+
import Debug11 from "debug";
|
|
13127
13129
|
import open from "open";
|
|
13128
13130
|
|
|
13129
13131
|
// src/features/analysis/graphql/gql.ts
|
|
@@ -13778,11 +13780,11 @@ var GQLClient = class {
|
|
|
13778
13780
|
{
|
|
13779
13781
|
next: async (data) => {
|
|
13780
13782
|
if (!data.analysis?.state || data.analysis?.state === "Failed" /* Failed */) {
|
|
13781
|
-
const
|
|
13783
|
+
const errorMessage3 = data.analysis?.failReason || `Analysis failed with id: ${data.analysis?.id}`;
|
|
13782
13784
|
subscription.unsubscribe();
|
|
13783
13785
|
reject(
|
|
13784
13786
|
new ReportDigestError(
|
|
13785
|
-
|
|
13787
|
+
errorMessage3,
|
|
13786
13788
|
data.analysis?.failReason ?? ""
|
|
13787
13789
|
)
|
|
13788
13790
|
);
|
|
@@ -13846,9 +13848,9 @@ var GQLClient = class {
|
|
|
13846
13848
|
`[pollForAnalysisState] Poll #${pollCount} - current state: ${analysis.state}`
|
|
13847
13849
|
);
|
|
13848
13850
|
if (!analysis.state || analysis.state === "Failed" /* Failed */) {
|
|
13849
|
-
const
|
|
13850
|
-
debug7(`[pollForAnalysisState] Analysis failed: ${
|
|
13851
|
-
throw new ReportDigestError(
|
|
13851
|
+
const errorMessage3 = analysis.failReason || `Analysis failed with id: ${analysis.id}`;
|
|
13852
|
+
debug7(`[pollForAnalysisState] Analysis failed: ${errorMessage3}`);
|
|
13853
|
+
throw new ReportDigestError(errorMessage3, analysis.failReason ?? "");
|
|
13852
13854
|
}
|
|
13853
13855
|
if (callbackStates.includes(analysis.state)) {
|
|
13854
13856
|
debug7(
|
|
@@ -13949,7 +13951,7 @@ var GQLClient = class {
|
|
|
13949
13951
|
};
|
|
13950
13952
|
|
|
13951
13953
|
// src/features/analysis/graphql/tracy-batch-upload.ts
|
|
13952
|
-
import
|
|
13954
|
+
import Debug10 from "debug";
|
|
13953
13955
|
|
|
13954
13956
|
// src/args/commands/upload_ai_blame.ts
|
|
13955
13957
|
import fsPromises2 from "fs/promises";
|
|
@@ -14068,12 +14070,28 @@ init_urlParser2();
|
|
|
14068
14070
|
import Debug8 from "debug";
|
|
14069
14071
|
import fetch3, { File, fileFrom, FormData } from "node-fetch";
|
|
14070
14072
|
var debug9 = Debug8("mobbdev:upload-file");
|
|
14073
|
+
var S3UploadError = class extends Error {
|
|
14074
|
+
constructor(status, s3Code, s3Message) {
|
|
14075
|
+
super(`Failed to upload the file: ${status}`);
|
|
14076
|
+
this.status = status;
|
|
14077
|
+
this.s3Code = s3Code;
|
|
14078
|
+
this.s3Message = s3Message;
|
|
14079
|
+
this.name = "S3UploadError";
|
|
14080
|
+
}
|
|
14081
|
+
};
|
|
14082
|
+
function parseS3ErrorBody(body) {
|
|
14083
|
+
return {
|
|
14084
|
+
code: body.match(/<Code>([^<]+)<\/Code>/)?.[1],
|
|
14085
|
+
message: body.match(/<Message>([^<]+)<\/Message>/)?.[1]
|
|
14086
|
+
};
|
|
14087
|
+
}
|
|
14071
14088
|
async function uploadFile({
|
|
14072
14089
|
file,
|
|
14073
14090
|
url,
|
|
14074
14091
|
uploadKey,
|
|
14075
14092
|
uploadFields,
|
|
14076
|
-
logger: logger3
|
|
14093
|
+
logger: logger3,
|
|
14094
|
+
signal
|
|
14077
14095
|
}) {
|
|
14078
14096
|
const logInfo2 = logger3 || ((_message, _data) => {
|
|
14079
14097
|
});
|
|
@@ -14095,18 +14113,44 @@ async function uploadFile({
|
|
|
14095
14113
|
} else {
|
|
14096
14114
|
debug9("upload file from buffer");
|
|
14097
14115
|
logInfo2(`FileUpload: upload file from buffer`);
|
|
14098
|
-
form.append(
|
|
14116
|
+
form.append(
|
|
14117
|
+
"file",
|
|
14118
|
+
new File(
|
|
14119
|
+
[
|
|
14120
|
+
new Uint8Array(
|
|
14121
|
+
file.buffer,
|
|
14122
|
+
file.byteOffset,
|
|
14123
|
+
file.byteLength
|
|
14124
|
+
)
|
|
14125
|
+
],
|
|
14126
|
+
"file"
|
|
14127
|
+
)
|
|
14128
|
+
);
|
|
14099
14129
|
}
|
|
14100
14130
|
const agent = getProxyAgent(url);
|
|
14101
14131
|
const response = await fetch3(url, {
|
|
14102
14132
|
method: "POST",
|
|
14103
14133
|
body: form,
|
|
14104
|
-
agent
|
|
14134
|
+
agent,
|
|
14135
|
+
signal
|
|
14105
14136
|
});
|
|
14106
14137
|
if (!response.ok) {
|
|
14107
|
-
|
|
14108
|
-
|
|
14109
|
-
|
|
14138
|
+
let bodyText = "";
|
|
14139
|
+
try {
|
|
14140
|
+
bodyText = await response.text();
|
|
14141
|
+
} catch {
|
|
14142
|
+
}
|
|
14143
|
+
const { code, message } = parseS3ErrorBody(bodyText);
|
|
14144
|
+
debug9(
|
|
14145
|
+
"error from S3 status=%d code=%s message=%s",
|
|
14146
|
+
response.status,
|
|
14147
|
+
code,
|
|
14148
|
+
message
|
|
14149
|
+
);
|
|
14150
|
+
logInfo2(
|
|
14151
|
+
`FileUpload: error from S3 status=${response.status} code=${code ?? "unknown"}`
|
|
14152
|
+
);
|
|
14153
|
+
throw new S3UploadError(response.status, code, message);
|
|
14110
14154
|
}
|
|
14111
14155
|
debug9("upload file done");
|
|
14112
14156
|
logInfo2(`FileUpload: upload file done`);
|
|
@@ -14772,39 +14816,240 @@ function withTimeout(promise, ms, label) {
|
|
|
14772
14816
|
]);
|
|
14773
14817
|
}
|
|
14774
14818
|
|
|
14819
|
+
// src/features/analysis/graphql/s3-raw-data-upload.ts
|
|
14820
|
+
import { setTimeout as sleep2 } from "timers/promises";
|
|
14821
|
+
import Debug9 from "debug";
|
|
14822
|
+
var debug10 = Debug9("mobbdev:tracy-s3-upload");
|
|
14823
|
+
var S3_OP_TIMEOUT_MS = 3e4;
|
|
14824
|
+
var MAX_TOTAL_S3_UPLOAD_MS = 12e4;
|
|
14825
|
+
var MAX_CONCURRENT_S3_UPLOADS = 5;
|
|
14826
|
+
var URL_REFRESH_MS = 20 * 60 * 1e3;
|
|
14827
|
+
var MAX_UPLOAD_ATTEMPTS = 3;
|
|
14828
|
+
var RETRY_BACKOFF_MS = 500;
|
|
14829
|
+
var MAX_S3_MESSAGE_CHARS = 120;
|
|
14830
|
+
var errorMessage = (e) => e instanceof Error ? e.message : String(e);
|
|
14831
|
+
function classifyUploadError(reason) {
|
|
14832
|
+
if (reason instanceof S3UploadError) {
|
|
14833
|
+
return {
|
|
14834
|
+
status: reason.status,
|
|
14835
|
+
s3Code: reason.s3Code,
|
|
14836
|
+
s3Message: reason.s3Message,
|
|
14837
|
+
retryable: reason.status !== 400 && reason.status !== 401
|
|
14838
|
+
};
|
|
14839
|
+
}
|
|
14840
|
+
return { retryable: true };
|
|
14841
|
+
}
|
|
14842
|
+
function createPresignedUrlProvider(client) {
|
|
14843
|
+
let creds = null;
|
|
14844
|
+
let fetchedAt = 0;
|
|
14845
|
+
const fetchFresh = async () => {
|
|
14846
|
+
let res;
|
|
14847
|
+
try {
|
|
14848
|
+
res = await withTimeout(
|
|
14849
|
+
client.getTracyRawDataUploadUrl(),
|
|
14850
|
+
S3_OP_TIMEOUT_MS,
|
|
14851
|
+
"[step:s3-url] getTracyRawDataUploadUrl"
|
|
14852
|
+
);
|
|
14853
|
+
} catch (err) {
|
|
14854
|
+
throw new Error(
|
|
14855
|
+
`[step:s3-url] Failed to fetch S3 upload URL: ${errorMessage(err)}`
|
|
14856
|
+
);
|
|
14857
|
+
}
|
|
14858
|
+
const { url, uploadFieldsJSON, keyPrefix } = res.getTracyRawDataUploadUrl;
|
|
14859
|
+
if (!url || !uploadFieldsJSON || !keyPrefix) {
|
|
14860
|
+
throw new Error(
|
|
14861
|
+
`[step:s3-url] Missing S3 upload fields (url=${!!url}, fields=${!!uploadFieldsJSON}, prefix=${!!keyPrefix})`
|
|
14862
|
+
);
|
|
14863
|
+
}
|
|
14864
|
+
try {
|
|
14865
|
+
return { url, uploadFields: JSON.parse(uploadFieldsJSON), keyPrefix };
|
|
14866
|
+
} catch {
|
|
14867
|
+
throw new Error("[step:s3-url] Malformed uploadFieldsJSON from server");
|
|
14868
|
+
}
|
|
14869
|
+
};
|
|
14870
|
+
const refresh = async () => {
|
|
14871
|
+
creds = await fetchFresh();
|
|
14872
|
+
fetchedAt = Date.now();
|
|
14873
|
+
return creds;
|
|
14874
|
+
};
|
|
14875
|
+
return {
|
|
14876
|
+
refresh,
|
|
14877
|
+
/** Cached creds, refreshed if missing or near expiry. */
|
|
14878
|
+
async current() {
|
|
14879
|
+
if (!creds || Date.now() - fetchedAt > URL_REFRESH_MS) return refresh();
|
|
14880
|
+
return creds;
|
|
14881
|
+
}
|
|
14882
|
+
};
|
|
14883
|
+
}
|
|
14884
|
+
async function uploadRawDataToS3(client, entries, serializedByIndex) {
|
|
14885
|
+
const uploaded = /* @__PURE__ */ new Map();
|
|
14886
|
+
const urls = createPresignedUrlProvider(client);
|
|
14887
|
+
debug10(
|
|
14888
|
+
"[step:s3-upload] Uploading %d files to S3 (concurrency=%d)",
|
|
14889
|
+
entries.length,
|
|
14890
|
+
MAX_CONCURRENT_S3_UPLOADS
|
|
14891
|
+
);
|
|
14892
|
+
const start = Date.now();
|
|
14893
|
+
const deadline = start + MAX_TOTAL_S3_UPLOAD_MS;
|
|
14894
|
+
const uploadPass = async (pass) => {
|
|
14895
|
+
const failures = [];
|
|
14896
|
+
for (let i = 0; i < pass.length; i += MAX_CONCURRENT_S3_UPLOADS) {
|
|
14897
|
+
if (Date.now() > deadline) {
|
|
14898
|
+
for (const entry of pass.slice(i)) {
|
|
14899
|
+
failures.push({
|
|
14900
|
+
entry,
|
|
14901
|
+
kind: { retryable: false },
|
|
14902
|
+
message: `[step:s3-upload] aborted: exceeded ${MAX_TOTAL_S3_UPLOAD_MS}ms total upload budget`
|
|
14903
|
+
});
|
|
14904
|
+
}
|
|
14905
|
+
break;
|
|
14906
|
+
}
|
|
14907
|
+
const { url, uploadFields, keyPrefix } = await urls.current();
|
|
14908
|
+
const chunk = pass.slice(i, i + MAX_CONCURRENT_S3_UPLOADS);
|
|
14909
|
+
const settled = await Promise.allSettled(
|
|
14910
|
+
chunk.map(async (entry) => {
|
|
14911
|
+
const rawDataJson = serializedByIndex.get(entry.index);
|
|
14912
|
+
if (!rawDataJson) {
|
|
14913
|
+
debug10("No serialized rawData for recordId=%s", entry.recordId);
|
|
14914
|
+
return;
|
|
14915
|
+
}
|
|
14916
|
+
const uploadKey = `${keyPrefix}${entry.recordId}.json`;
|
|
14917
|
+
const signal = AbortSignal.timeout(S3_OP_TIMEOUT_MS);
|
|
14918
|
+
try {
|
|
14919
|
+
await uploadFile({
|
|
14920
|
+
file: Buffer.from(rawDataJson, "utf-8"),
|
|
14921
|
+
url,
|
|
14922
|
+
uploadKey,
|
|
14923
|
+
uploadFields,
|
|
14924
|
+
signal
|
|
14925
|
+
});
|
|
14926
|
+
} catch (err) {
|
|
14927
|
+
if (signal.aborted) {
|
|
14928
|
+
throw new Error(
|
|
14929
|
+
`[step:s3-upload] uploadFile ${entry.recordId} timed out after ${S3_OP_TIMEOUT_MS}ms`
|
|
14930
|
+
);
|
|
14931
|
+
}
|
|
14932
|
+
throw err;
|
|
14933
|
+
}
|
|
14934
|
+
uploaded.set(entry.index, uploadKey);
|
|
14935
|
+
serializedByIndex.delete(entry.index);
|
|
14936
|
+
})
|
|
14937
|
+
);
|
|
14938
|
+
settled.forEach((outcome, idx) => {
|
|
14939
|
+
if (outcome.status === "rejected") {
|
|
14940
|
+
failures.push({
|
|
14941
|
+
entry: chunk[idx],
|
|
14942
|
+
kind: classifyUploadError(outcome.reason),
|
|
14943
|
+
message: errorMessage(outcome.reason)
|
|
14944
|
+
});
|
|
14945
|
+
}
|
|
14946
|
+
});
|
|
14947
|
+
}
|
|
14948
|
+
return failures;
|
|
14949
|
+
};
|
|
14950
|
+
const failuresByRecord = /* @__PURE__ */ new Map();
|
|
14951
|
+
try {
|
|
14952
|
+
await urls.refresh();
|
|
14953
|
+
let pending = entries;
|
|
14954
|
+
for (let attempt = 1; attempt <= MAX_UPLOAD_ATTEMPTS; attempt++) {
|
|
14955
|
+
const failures = await uploadPass(pending);
|
|
14956
|
+
for (const entry of pending) failuresByRecord.delete(entry.recordId);
|
|
14957
|
+
for (const failure of failures)
|
|
14958
|
+
failuresByRecord.set(failure.entry.recordId, failure);
|
|
14959
|
+
const retryable = failures.filter((failure) => failure.kind.retryable);
|
|
14960
|
+
if (retryable.length === 0 || attempt === MAX_UPLOAD_ATTEMPTS || Date.now() > deadline) {
|
|
14961
|
+
break;
|
|
14962
|
+
}
|
|
14963
|
+
debug10(
|
|
14964
|
+
"[step:s3-upload] attempt %d failed for %d record(s); refreshing URL and retrying",
|
|
14965
|
+
attempt,
|
|
14966
|
+
retryable.length
|
|
14967
|
+
);
|
|
14968
|
+
await sleep2(RETRY_BACKOFF_MS * attempt);
|
|
14969
|
+
await urls.refresh();
|
|
14970
|
+
pending = retryable.map((failure) => failure.entry);
|
|
14971
|
+
}
|
|
14972
|
+
} catch (err) {
|
|
14973
|
+
return { uploaded, errors: [errorMessage(err)] };
|
|
14974
|
+
}
|
|
14975
|
+
debug10("[perf] s3-upload %d files: %dms", entries.length, Date.now() - start);
|
|
14976
|
+
const missing = entries.filter((entry) => !uploaded.has(entry.index));
|
|
14977
|
+
if (missing.length === 0) {
|
|
14978
|
+
debug10("[step:s3-upload] S3 uploads complete");
|
|
14979
|
+
return { uploaded, errors: null };
|
|
14980
|
+
}
|
|
14981
|
+
const detail = missing.map((entry) => {
|
|
14982
|
+
const failure = failuresByRecord.get(entry.recordId);
|
|
14983
|
+
const code = failure?.kind.s3Code ? ` ${failure.kind.s3Code}` : "";
|
|
14984
|
+
const message = failure?.kind.s3Message ? ` "${failure.kind.s3Message.slice(0, MAX_S3_MESSAGE_CHARS)}"` : "";
|
|
14985
|
+
return `[step:s3-upload] ${entry.recordId}: HTTP ${failure?.kind.status ?? "n/a"}${code}${message} (${failure?.message ?? "unknown"})`;
|
|
14986
|
+
});
|
|
14987
|
+
debug10(
|
|
14988
|
+
"[step:s3-upload] Records missing S3 keys: %O",
|
|
14989
|
+
missing.map((entry) => entry.recordId)
|
|
14990
|
+
);
|
|
14991
|
+
return {
|
|
14992
|
+
uploaded,
|
|
14993
|
+
errors: [
|
|
14994
|
+
`[step:s3-upload] Failed to upload rawData for ${missing.length} record(s): ${missing.map((entry) => entry.recordId).join(", ")}`,
|
|
14995
|
+
...detail
|
|
14996
|
+
]
|
|
14997
|
+
};
|
|
14998
|
+
}
|
|
14999
|
+
|
|
14775
15000
|
// src/features/analysis/graphql/tracy-batch-upload.ts
|
|
14776
|
-
var
|
|
15001
|
+
var debug11 = Debug10("mobbdev:tracy-batch-upload");
|
|
15002
|
+
var errorMessage2 = (e) => e instanceof Error ? e.message : String(e);
|
|
14777
15003
|
function timedStep(label, fn) {
|
|
14778
15004
|
const start = Date.now();
|
|
14779
15005
|
const result = fn();
|
|
14780
15006
|
const maybePromise = result instanceof Promise ? result : Promise.resolve(result);
|
|
14781
15007
|
return maybePromise.then(
|
|
14782
15008
|
(val) => {
|
|
14783
|
-
|
|
15009
|
+
debug11("[perf] %s: %dms", label, Date.now() - start);
|
|
14784
15010
|
return val;
|
|
14785
15011
|
},
|
|
14786
15012
|
(err) => {
|
|
14787
|
-
|
|
15013
|
+
debug11("[perf] %s FAILED: %dms", label, Date.now() - start);
|
|
14788
15014
|
throw err;
|
|
14789
15015
|
}
|
|
14790
15016
|
);
|
|
14791
15017
|
}
|
|
14792
15018
|
var BATCH_TIMEOUT_MS = 3e4;
|
|
15019
|
+
var MIN_RAWDATA_BYTES = 5;
|
|
15020
|
+
var MAX_DEGENERATE_SAMPLE_CHARS = 500;
|
|
15021
|
+
var REDACTED_SAMPLE = "<redacted: sanitization disabled>";
|
|
15022
|
+
var MAX_DEGENERATE_LOG_RECORDS = 20;
|
|
15023
|
+
var DEGENERATE_RECORDS_LOG_MESSAGE = "Skipped empty/degenerate rawData records before S3 upload";
|
|
15024
|
+
function degenerateRecordsLogFields(degenerate) {
|
|
15025
|
+
return {
|
|
15026
|
+
count: degenerate.length,
|
|
15027
|
+
records: degenerate.slice(0, MAX_DEGENERATE_LOG_RECORDS)
|
|
15028
|
+
};
|
|
15029
|
+
}
|
|
15030
|
+
function isStructurallyEmptyPayload(serialized) {
|
|
15031
|
+
const trimmed = serialized.trim();
|
|
15032
|
+
if (trimmed === "" || trimmed === "null" || trimmed === '""') return true;
|
|
15033
|
+
const isObject = trimmed.startsWith("{") && trimmed.endsWith("}");
|
|
15034
|
+
const isArray = trimmed.startsWith("[") && trimmed.endsWith("]");
|
|
15035
|
+
if (isObject || isArray) return trimmed.slice(1, -1).trim() === "";
|
|
15036
|
+
return false;
|
|
15037
|
+
}
|
|
14793
15038
|
async function sanitizeRawData(rawData) {
|
|
14794
15039
|
const start = Date.now();
|
|
14795
15040
|
try {
|
|
14796
15041
|
const sanitized = await sanitizeData(rawData);
|
|
14797
15042
|
const serialized = JSON.stringify(sanitized);
|
|
14798
|
-
|
|
15043
|
+
debug11(
|
|
14799
15044
|
"[perf] sanitizeRawData: %dms (%d bytes)",
|
|
14800
15045
|
Date.now() - start,
|
|
14801
15046
|
serialized.length
|
|
14802
15047
|
);
|
|
14803
15048
|
return serialized;
|
|
14804
15049
|
} catch (err) {
|
|
14805
|
-
|
|
14806
|
-
"[tracy] sanitizeRawData failed, falling back to unsanitized:",
|
|
14807
|
-
err
|
|
15050
|
+
debug11(
|
|
15051
|
+
"[tracy] sanitizeRawData failed, falling back to unsanitized: %s",
|
|
15052
|
+
errorMessage2(err)
|
|
14808
15053
|
);
|
|
14809
15054
|
return JSON.stringify(rawData);
|
|
14810
15055
|
}
|
|
@@ -14814,12 +15059,13 @@ async function prepareAndSendTracyRecords(client, rawRecords, workingDir, option
|
|
|
14814
15059
|
const defaultClientVersion = packageJson.version;
|
|
14815
15060
|
const shouldSanitize = options?.sanitize ?? true;
|
|
14816
15061
|
const defaults = workingDir != null ? await readRepoState(workingDir) : { repositoryUrl: null, branch: null, commitSha: null };
|
|
14817
|
-
|
|
15062
|
+
debug11(
|
|
14818
15063
|
"[step:sanitize] %s %d records",
|
|
14819
15064
|
shouldSanitize ? "Sanitizing" : "Serializing",
|
|
14820
15065
|
rawRecords.length
|
|
14821
15066
|
);
|
|
14822
15067
|
const serializedRawDataByIndex = /* @__PURE__ */ new Map();
|
|
15068
|
+
const degenerate = [];
|
|
14823
15069
|
const records = await timedStep(
|
|
14824
15070
|
`${shouldSanitize ? "sanitize" : "serialize"} ${rawRecords.length} records`,
|
|
14825
15071
|
async () => {
|
|
@@ -14828,7 +15074,19 @@ async function prepareAndSendTracyRecords(client, rawRecords, workingDir, option
|
|
|
14828
15074
|
const record = rawRecords[index];
|
|
14829
15075
|
if (record.rawData != null && record.rawDataS3Key == null) {
|
|
14830
15076
|
const serialized = shouldSanitize ? await sanitizeRawData(record.rawData) : JSON.stringify(record.rawData);
|
|
14831
|
-
|
|
15077
|
+
const bytes = Buffer.byteLength(serialized, "utf-8");
|
|
15078
|
+
if (bytes < MIN_RAWDATA_BYTES || isStructurallyEmptyPayload(serialized)) {
|
|
15079
|
+
degenerate.push({
|
|
15080
|
+
recordId: record.recordId,
|
|
15081
|
+
platform: record.platform,
|
|
15082
|
+
filePath: record.filePath,
|
|
15083
|
+
editType: record.editType,
|
|
15084
|
+
bytes,
|
|
15085
|
+
sample: shouldSanitize ? serialized.slice(0, MAX_DEGENERATE_SAMPLE_CHARS) : REDACTED_SAMPLE
|
|
15086
|
+
});
|
|
15087
|
+
} else {
|
|
15088
|
+
serializedRawDataByIndex.set(index, serialized);
|
|
15089
|
+
}
|
|
14832
15090
|
}
|
|
14833
15091
|
const { rawData: _rawData, ...rest } = record;
|
|
14834
15092
|
results.push({
|
|
@@ -14844,104 +15102,19 @@ async function prepareAndSendTracyRecords(client, rawRecords, workingDir, option
|
|
|
14844
15102
|
return results;
|
|
14845
15103
|
}
|
|
14846
15104
|
);
|
|
14847
|
-
const
|
|
15105
|
+
const degenerateOut = degenerate.length > 0 ? degenerate : void 0;
|
|
15106
|
+
const finish = (result) => ({ ...result, degenerate: degenerateOut });
|
|
15107
|
+
const recordsWithRawData = rawRecords.map((record, index) => ({ recordId: record.recordId, index })).filter((entry) => serializedRawDataByIndex.has(entry.index));
|
|
14848
15108
|
if (recordsWithRawData.length > 0) {
|
|
14849
|
-
|
|
14850
|
-
|
|
14851
|
-
recordsWithRawData
|
|
14852
|
-
|
|
14853
|
-
let uploadUrlResult;
|
|
14854
|
-
try {
|
|
14855
|
-
uploadUrlResult = await withTimeout(
|
|
14856
|
-
client.getTracyRawDataUploadUrl(),
|
|
14857
|
-
BATCH_TIMEOUT_MS,
|
|
14858
|
-
"[step:s3-url] getTracyRawDataUploadUrl"
|
|
14859
|
-
);
|
|
14860
|
-
} catch (err) {
|
|
14861
|
-
return {
|
|
14862
|
-
ok: false,
|
|
14863
|
-
errors: [
|
|
14864
|
-
`[step:s3-url] Failed to fetch S3 upload URL: ${err.message}`
|
|
14865
|
-
]
|
|
14866
|
-
};
|
|
14867
|
-
}
|
|
14868
|
-
const { url, uploadFieldsJSON, keyPrefix } = uploadUrlResult.getTracyRawDataUploadUrl;
|
|
14869
|
-
if (!url || !uploadFieldsJSON || !keyPrefix) {
|
|
14870
|
-
return {
|
|
14871
|
-
ok: false,
|
|
14872
|
-
errors: [
|
|
14873
|
-
`[step:s3-url] Missing S3 upload fields (url=${!!url}, fields=${!!uploadFieldsJSON}, prefix=${!!keyPrefix})`
|
|
14874
|
-
]
|
|
14875
|
-
};
|
|
14876
|
-
}
|
|
14877
|
-
let uploadFields;
|
|
14878
|
-
try {
|
|
14879
|
-
uploadFields = JSON.parse(uploadFieldsJSON);
|
|
14880
|
-
} catch {
|
|
14881
|
-
return {
|
|
14882
|
-
ok: false,
|
|
14883
|
-
errors: ["[step:s3-url] Malformed uploadFieldsJSON from server"]
|
|
14884
|
-
};
|
|
14885
|
-
}
|
|
14886
|
-
const MAX_CONCURRENT_S3_UPLOADS = 5;
|
|
14887
|
-
debug10(
|
|
14888
|
-
"[step:s3-upload] Uploading %d files to S3 (concurrency=%d)",
|
|
14889
|
-
recordsWithRawData.length,
|
|
14890
|
-
MAX_CONCURRENT_S3_UPLOADS
|
|
14891
|
-
);
|
|
14892
|
-
const s3Start = Date.now();
|
|
14893
|
-
const uploadResults = [];
|
|
14894
|
-
for (let i = 0; i < recordsWithRawData.length; i += MAX_CONCURRENT_S3_UPLOADS) {
|
|
14895
|
-
const chunk = recordsWithRawData.slice(i, i + MAX_CONCURRENT_S3_UPLOADS);
|
|
14896
|
-
const chunkResults = await Promise.allSettled(
|
|
14897
|
-
chunk.map(async (entry) => {
|
|
14898
|
-
const rawDataJson = serializedRawDataByIndex.get(entry.index);
|
|
14899
|
-
if (!rawDataJson) {
|
|
14900
|
-
debug10("No serialized rawData for recordId=%s", entry.recordId);
|
|
14901
|
-
return;
|
|
14902
|
-
}
|
|
14903
|
-
const uploadKey = `${keyPrefix}${entry.recordId}.json`;
|
|
14904
|
-
await withTimeout(
|
|
14905
|
-
uploadFile({
|
|
14906
|
-
file: Buffer.from(rawDataJson, "utf-8"),
|
|
14907
|
-
url,
|
|
14908
|
-
uploadKey,
|
|
14909
|
-
uploadFields
|
|
14910
|
-
}),
|
|
14911
|
-
BATCH_TIMEOUT_MS,
|
|
14912
|
-
`[step:s3-upload] uploadFile ${entry.recordId}`
|
|
14913
|
-
);
|
|
14914
|
-
records[entry.index].rawDataS3Key = uploadKey;
|
|
14915
|
-
})
|
|
14916
|
-
);
|
|
14917
|
-
uploadResults.push(...chunkResults);
|
|
14918
|
-
}
|
|
14919
|
-
debug10(
|
|
14920
|
-
"[perf] s3-upload %d files: %dms",
|
|
14921
|
-
recordsWithRawData.length,
|
|
14922
|
-
Date.now() - s3Start
|
|
15109
|
+
const { uploaded, errors } = await uploadRawDataToS3(
|
|
15110
|
+
client,
|
|
15111
|
+
recordsWithRawData,
|
|
15112
|
+
serializedRawDataByIndex
|
|
14923
15113
|
);
|
|
14924
|
-
|
|
14925
|
-
if (
|
|
14926
|
-
debug10("[step:s3-upload] S3 upload errors: %O", uploadErrors);
|
|
14927
|
-
}
|
|
14928
|
-
const missingS3Keys = recordsWithRawData.filter(
|
|
14929
|
-
(entry) => !records[entry.index].rawDataS3Key
|
|
14930
|
-
);
|
|
14931
|
-
if (missingS3Keys.length > 0) {
|
|
14932
|
-
const missingIds = missingS3Keys.map((e) => e.recordId);
|
|
14933
|
-
debug10("[step:s3-upload] Records missing S3 keys: %O", missingIds);
|
|
14934
|
-
return {
|
|
14935
|
-
ok: false,
|
|
14936
|
-
errors: [
|
|
14937
|
-
`[step:s3-upload] Failed to upload rawData for ${missingS3Keys.length} record(s): ${missingIds.join(", ")}`,
|
|
14938
|
-
...uploadErrors
|
|
14939
|
-
]
|
|
14940
|
-
};
|
|
14941
|
-
}
|
|
14942
|
-
debug10("[step:s3-upload] S3 uploads complete");
|
|
15114
|
+
for (const [index, key] of uploaded) records[index].rawDataS3Key = key;
|
|
15115
|
+
if (errors) return finish({ ok: false, errors });
|
|
14943
15116
|
}
|
|
14944
|
-
|
|
15117
|
+
debug11("[step:gql-submit] Submitting %d records via GraphQL", records.length);
|
|
14945
15118
|
try {
|
|
14946
15119
|
const result = await timedStep(
|
|
14947
15120
|
`gql-submit ${records.length} records`,
|
|
@@ -14952,21 +15125,21 @@ async function prepareAndSendTracyRecords(client, rawRecords, workingDir, option
|
|
|
14952
15125
|
)
|
|
14953
15126
|
);
|
|
14954
15127
|
if (result.uploadTracyRecords.status !== "OK") {
|
|
14955
|
-
return {
|
|
15128
|
+
return finish({
|
|
14956
15129
|
ok: false,
|
|
14957
15130
|
errors: [
|
|
14958
15131
|
`[step:gql-submit] Server rejected: ${result.uploadTracyRecords.error ?? "Unknown server error"}`
|
|
14959
15132
|
]
|
|
14960
|
-
};
|
|
15133
|
+
});
|
|
14961
15134
|
}
|
|
14962
15135
|
} catch (err) {
|
|
14963
|
-
|
|
14964
|
-
return {
|
|
15136
|
+
debug11("[step:gql-submit] Upload failed: %s", errorMessage2(err));
|
|
15137
|
+
return finish({
|
|
14965
15138
|
ok: false,
|
|
14966
|
-
errors: [`[step:gql-submit] ${err
|
|
14967
|
-
};
|
|
15139
|
+
errors: [`[step:gql-submit] ${errorMessage2(err)}`]
|
|
15140
|
+
});
|
|
14968
15141
|
}
|
|
14969
|
-
return { ok: true, errors: null };
|
|
15142
|
+
return finish({ ok: true, errors: null });
|
|
14970
15143
|
}
|
|
14971
15144
|
|
|
14972
15145
|
// src/mcp/services/types.ts
|
|
@@ -15002,7 +15175,7 @@ function buildLoginUrl(baseUrl, loginId, hostname, context) {
|
|
|
15002
15175
|
}
|
|
15003
15176
|
|
|
15004
15177
|
// src/commands/AuthManager.ts
|
|
15005
|
-
var
|
|
15178
|
+
var debug12 = Debug11("mobbdev:auth");
|
|
15006
15179
|
var LOGIN_MAX_WAIT = 2 * 60 * 1e3;
|
|
15007
15180
|
var LOGIN_CHECK_DELAY = 2 * 1e3;
|
|
15008
15181
|
var _AuthManager = class _AuthManager {
|
|
@@ -15032,7 +15205,7 @@ var _AuthManager = class _AuthManager {
|
|
|
15032
15205
|
return false;
|
|
15033
15206
|
}
|
|
15034
15207
|
if (_AuthManager.browserCooldownMs > 0 && Date.now() - _AuthManager.lastBrowserOpenTime < _AuthManager.browserCooldownMs) {
|
|
15035
|
-
|
|
15208
|
+
debug12("browser cooldown active, skipping open");
|
|
15036
15209
|
return false;
|
|
15037
15210
|
}
|
|
15038
15211
|
open(this.currentBrowserUrl);
|
|
@@ -15085,7 +15258,7 @@ var _AuthManager = class _AuthManager {
|
|
|
15085
15258
|
const result = await this.checkAuthentication();
|
|
15086
15259
|
this.authenticated = result.isAuthenticated;
|
|
15087
15260
|
if (!result.isAuthenticated) {
|
|
15088
|
-
|
|
15261
|
+
debug12("isAuthenticated: false \u2014 %s (%s)", result.message, result.reason);
|
|
15089
15262
|
}
|
|
15090
15263
|
}
|
|
15091
15264
|
return this.authenticated;
|
|
@@ -15173,9 +15346,9 @@ var _AuthManager = class _AuthManager {
|
|
|
15173
15346
|
return null;
|
|
15174
15347
|
} catch (error) {
|
|
15175
15348
|
if (isTransientError(error)) {
|
|
15176
|
-
|
|
15349
|
+
debug12("getApiToken: transient error, will retry");
|
|
15177
15350
|
} else {
|
|
15178
|
-
|
|
15351
|
+
debug12("getApiToken: unexpected error: %O", error);
|
|
15179
15352
|
}
|
|
15180
15353
|
return null;
|
|
15181
15354
|
}
|
|
@@ -15228,10 +15401,10 @@ __publicField(_AuthManager, "lastBrowserOpenTime", 0);
|
|
|
15228
15401
|
var AuthManager = _AuthManager;
|
|
15229
15402
|
|
|
15230
15403
|
// src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
|
|
15231
|
-
import
|
|
15404
|
+
import Debug15 from "debug";
|
|
15232
15405
|
|
|
15233
15406
|
// src/features/analysis/add_fix_comments_for_pr/utils/utils.ts
|
|
15234
|
-
import
|
|
15407
|
+
import Debug14 from "debug";
|
|
15235
15408
|
import parseDiff from "parse-diff";
|
|
15236
15409
|
import { z as z29 } from "zod";
|
|
15237
15410
|
|
|
@@ -15243,9 +15416,9 @@ function keyBy(array, keyBy2) {
|
|
|
15243
15416
|
}
|
|
15244
15417
|
|
|
15245
15418
|
// src/features/analysis/utils/send_report.ts
|
|
15246
|
-
import
|
|
15419
|
+
import Debug12 from "debug";
|
|
15247
15420
|
init_client_generates();
|
|
15248
|
-
var
|
|
15421
|
+
var debug13 = Debug12("mobbdev:index");
|
|
15249
15422
|
async function sendReport({
|
|
15250
15423
|
spinner,
|
|
15251
15424
|
submitVulnerabilityReportVariables,
|
|
@@ -15257,7 +15430,7 @@ async function sendReport({
|
|
|
15257
15430
|
submitVulnerabilityReportVariables
|
|
15258
15431
|
);
|
|
15259
15432
|
if (submitRes.submitVulnerabilityReport.__typename !== "VulnerabilityReport") {
|
|
15260
|
-
|
|
15433
|
+
debug13("error submit vul report %s", submitRes);
|
|
15261
15434
|
throw new Error("\u{1F575}\uFE0F\u200D\u2642\uFE0F Mobb analysis failed");
|
|
15262
15435
|
}
|
|
15263
15436
|
spinner.update({ text: progressMassages.processingVulnerabilityReport });
|
|
@@ -15269,7 +15442,7 @@ async function sendReport({
|
|
|
15269
15442
|
"Finished" /* Finished */
|
|
15270
15443
|
];
|
|
15271
15444
|
if (polling) {
|
|
15272
|
-
|
|
15445
|
+
debug13("[sendReport] Using POLLING mode for analysis state updates");
|
|
15273
15446
|
await gqlClient.pollForAnalysisState({
|
|
15274
15447
|
analysisId: submitRes.submitVulnerabilityReport.fixReportId,
|
|
15275
15448
|
callback,
|
|
@@ -15277,7 +15450,7 @@ async function sendReport({
|
|
|
15277
15450
|
timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
|
|
15278
15451
|
});
|
|
15279
15452
|
} else {
|
|
15280
|
-
|
|
15453
|
+
debug13("[sendReport] Using WEBSOCKET mode for analysis state updates");
|
|
15281
15454
|
await gqlClient.subscribeToAnalysis({
|
|
15282
15455
|
subscribeToAnalysisParams: {
|
|
15283
15456
|
analysisId: submitRes.submitVulnerabilityReport.fixReportId
|
|
@@ -15321,10 +15494,10 @@ var scannerToFriendlyString = {
|
|
|
15321
15494
|
};
|
|
15322
15495
|
|
|
15323
15496
|
// src/features/analysis/add_fix_comments_for_pr/utils/buildCommentBody.ts
|
|
15324
|
-
import
|
|
15497
|
+
import Debug13 from "debug";
|
|
15325
15498
|
import { z as z28 } from "zod";
|
|
15326
15499
|
init_client_generates();
|
|
15327
|
-
var
|
|
15500
|
+
var debug14 = Debug13("mobbdev:handle-finished-analysis");
|
|
15328
15501
|
var getCommitFixButton = (commitUrl) => `<a href="${commitUrl}"><img src=${COMMIT_FIX_SVG}></a>`;
|
|
15329
15502
|
function buildFixCommentBody({
|
|
15330
15503
|
fix,
|
|
@@ -15375,7 +15548,7 @@ function buildFixCommentBody({
|
|
|
15375
15548
|
safeIssueType: z28.nativeEnum(IssueType_Enum)
|
|
15376
15549
|
}).safeParse(fix);
|
|
15377
15550
|
if (!validFixParseRes.success) {
|
|
15378
|
-
|
|
15551
|
+
debug14(
|
|
15379
15552
|
`fix ${fixId} has custom issue type or language, therefore the commit description will not be added`,
|
|
15380
15553
|
validFixParseRes.error
|
|
15381
15554
|
);
|
|
@@ -15439,7 +15612,7 @@ ${issuePageLink}`;
|
|
|
15439
15612
|
}
|
|
15440
15613
|
|
|
15441
15614
|
// src/features/analysis/add_fix_comments_for_pr/utils/utils.ts
|
|
15442
|
-
var
|
|
15615
|
+
var debug15 = Debug14("mobbdev:handle-finished-analysis");
|
|
15443
15616
|
function calculateRanges(integers) {
|
|
15444
15617
|
if (integers.length === 0) {
|
|
15445
15618
|
return [];
|
|
@@ -15473,7 +15646,7 @@ function deleteAllPreviousComments({
|
|
|
15473
15646
|
try {
|
|
15474
15647
|
return scm.deleteComment({ comment_id: comment.id });
|
|
15475
15648
|
} catch (e) {
|
|
15476
|
-
|
|
15649
|
+
debug15("delete comment failed %s", e);
|
|
15477
15650
|
return Promise.resolve();
|
|
15478
15651
|
}
|
|
15479
15652
|
});
|
|
@@ -15489,7 +15662,7 @@ function deleteAllPreviousGeneralPrComments(params) {
|
|
|
15489
15662
|
try {
|
|
15490
15663
|
return scm.deleteGeneralPrComment({ commentId: comment.id });
|
|
15491
15664
|
} catch (e) {
|
|
15492
|
-
|
|
15665
|
+
debug15("delete comment failed %s", e);
|
|
15493
15666
|
return Promise.resolve();
|
|
15494
15667
|
}
|
|
15495
15668
|
});
|
|
@@ -15633,7 +15806,7 @@ async function postAnalysisInsightComment(params) {
|
|
|
15633
15806
|
fixablePrVuls,
|
|
15634
15807
|
nonFixablePrVuls
|
|
15635
15808
|
} = prVulenrabilities;
|
|
15636
|
-
|
|
15809
|
+
debug15({
|
|
15637
15810
|
fixablePrVuls,
|
|
15638
15811
|
nonFixablePrVuls,
|
|
15639
15812
|
vulnerabilitiesOutsidePr,
|
|
@@ -15688,7 +15861,7 @@ ${contactUsMarkdown}`;
|
|
|
15688
15861
|
}
|
|
15689
15862
|
|
|
15690
15863
|
// src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
|
|
15691
|
-
var
|
|
15864
|
+
var debug16 = Debug15("mobbdev:handle-finished-analysis");
|
|
15692
15865
|
async function addFixCommentsForPr({
|
|
15693
15866
|
analysisId,
|
|
15694
15867
|
scm: _scm,
|
|
@@ -15700,7 +15873,7 @@ async function addFixCommentsForPr({
|
|
|
15700
15873
|
}
|
|
15701
15874
|
const scm = _scm;
|
|
15702
15875
|
const getAnalysisRes = await gqlClient.getAnalysis(analysisId);
|
|
15703
|
-
|
|
15876
|
+
debug16("getAnalysis %o", getAnalysisRes);
|
|
15704
15877
|
const {
|
|
15705
15878
|
vulnerabilityReport: {
|
|
15706
15879
|
projectId,
|
|
@@ -15810,8 +15983,8 @@ ${contextString}` : description;
|
|
|
15810
15983
|
|
|
15811
15984
|
// src/features/analysis/auto_pr_handler.ts
|
|
15812
15985
|
init_client_generates();
|
|
15813
|
-
import
|
|
15814
|
-
var
|
|
15986
|
+
import Debug16 from "debug";
|
|
15987
|
+
var debug17 = Debug16("mobbdev:handleAutoPr");
|
|
15815
15988
|
async function handleAutoPr(params) {
|
|
15816
15989
|
const {
|
|
15817
15990
|
gqlClient,
|
|
@@ -15832,7 +16005,7 @@ async function handleAutoPr(params) {
|
|
|
15832
16005
|
prId,
|
|
15833
16006
|
prStrategy: createOnePr ? "CONDENSE" /* Condense */ : "SPREAD" /* Spread */
|
|
15834
16007
|
});
|
|
15835
|
-
|
|
16008
|
+
debug17("auto pr analysis res %o", autoPrAnalysisRes);
|
|
15836
16009
|
if (autoPrAnalysisRes.autoPrAnalysis?.__typename === "AutoPrError") {
|
|
15837
16010
|
createAutoPrSpinner.error({
|
|
15838
16011
|
text: `\u{1F504} Automatic pull request failed - ${autoPrAnalysisRes.autoPrAnalysis.error}`
|
|
@@ -15854,14 +16027,14 @@ async function handleAutoPr(params) {
|
|
|
15854
16027
|
};
|
|
15855
16028
|
const callbackStates = ["Finished" /* Finished */];
|
|
15856
16029
|
if (polling) {
|
|
15857
|
-
|
|
16030
|
+
debug17("[handleAutoPr] Using POLLING mode for analysis state updates");
|
|
15858
16031
|
return await gqlClient.pollForAnalysisState({
|
|
15859
16032
|
analysisId,
|
|
15860
16033
|
callback,
|
|
15861
16034
|
callbackStates
|
|
15862
16035
|
});
|
|
15863
16036
|
} else {
|
|
15864
|
-
|
|
16037
|
+
debug17("[handleAutoPr] Using WEBSOCKET mode for analysis state updates");
|
|
15865
16038
|
return await gqlClient.subscribeToAnalysis({
|
|
15866
16039
|
subscribeToAnalysisParams: {
|
|
15867
16040
|
analysisId
|
|
@@ -15874,15 +16047,15 @@ async function handleAutoPr(params) {
|
|
|
15874
16047
|
|
|
15875
16048
|
// src/features/analysis/git.ts
|
|
15876
16049
|
init_GitService();
|
|
15877
|
-
import
|
|
15878
|
-
var
|
|
16050
|
+
import Debug17 from "debug";
|
|
16051
|
+
var debug18 = Debug17("mobbdev:git");
|
|
15879
16052
|
async function getGitInfo(srcDirPath) {
|
|
15880
|
-
|
|
16053
|
+
debug18("getting git info for %s", srcDirPath);
|
|
15881
16054
|
const gitService = new GitService(srcDirPath);
|
|
15882
16055
|
try {
|
|
15883
16056
|
const validationResult = await gitService.validateRepository();
|
|
15884
16057
|
if (!validationResult.isValid) {
|
|
15885
|
-
|
|
16058
|
+
debug18("folder is not a git repo");
|
|
15886
16059
|
return {
|
|
15887
16060
|
success: false,
|
|
15888
16061
|
hash: void 0,
|
|
@@ -15897,9 +16070,9 @@ async function getGitInfo(srcDirPath) {
|
|
|
15897
16070
|
};
|
|
15898
16071
|
} catch (e) {
|
|
15899
16072
|
if (e instanceof Error) {
|
|
15900
|
-
|
|
16073
|
+
debug18("failed to run git %o", e);
|
|
15901
16074
|
if (e.message.includes(" spawn ")) {
|
|
15902
|
-
|
|
16075
|
+
debug18("git cli not installed");
|
|
15903
16076
|
} else {
|
|
15904
16077
|
throw e;
|
|
15905
16078
|
}
|
|
@@ -15913,13 +16086,13 @@ init_configs();
|
|
|
15913
16086
|
import fs9 from "fs";
|
|
15914
16087
|
import path8 from "path";
|
|
15915
16088
|
import AdmZip from "adm-zip";
|
|
15916
|
-
import
|
|
16089
|
+
import Debug18 from "debug";
|
|
15917
16090
|
import { globby } from "globby";
|
|
15918
16091
|
import { isBinary as isBinary2 } from "istextorbinary";
|
|
15919
16092
|
import { simpleGit as simpleGit3 } from "simple-git";
|
|
15920
16093
|
import { parseStringPromise } from "xml2js";
|
|
15921
16094
|
import { z as z30 } from "zod";
|
|
15922
|
-
var
|
|
16095
|
+
var debug19 = Debug18("mobbdev:pack");
|
|
15923
16096
|
var FPR_SOURCE_CODE_FILE_MAPPING_SCHEMA = z30.object({
|
|
15924
16097
|
properties: z30.object({
|
|
15925
16098
|
entry: z30.array(
|
|
@@ -15941,7 +16114,7 @@ function getManifestFilesSuffixes() {
|
|
|
15941
16114
|
return ["package.json", "pom.xml"];
|
|
15942
16115
|
}
|
|
15943
16116
|
async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
|
|
15944
|
-
|
|
16117
|
+
debug19("pack folder %s", srcDirPath);
|
|
15945
16118
|
let git;
|
|
15946
16119
|
try {
|
|
15947
16120
|
git = simpleGit3({
|
|
@@ -15951,13 +16124,13 @@ async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
|
|
|
15951
16124
|
});
|
|
15952
16125
|
await git.status();
|
|
15953
16126
|
} catch (e) {
|
|
15954
|
-
|
|
16127
|
+
debug19("failed to run git %o", e);
|
|
15955
16128
|
git = void 0;
|
|
15956
16129
|
if (e instanceof Error) {
|
|
15957
16130
|
if (e.message.includes(" spawn ")) {
|
|
15958
|
-
|
|
16131
|
+
debug19("git cli not installed");
|
|
15959
16132
|
} else if (e.message.includes("not a git repository")) {
|
|
15960
|
-
|
|
16133
|
+
debug19("folder is not a git repo");
|
|
15961
16134
|
} else {
|
|
15962
16135
|
throw e;
|
|
15963
16136
|
}
|
|
@@ -15972,9 +16145,9 @@ async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
|
|
|
15972
16145
|
followSymbolicLinks: false,
|
|
15973
16146
|
dot: true
|
|
15974
16147
|
});
|
|
15975
|
-
|
|
16148
|
+
debug19("files found %d", filepaths.length);
|
|
15976
16149
|
const zip = new AdmZip();
|
|
15977
|
-
|
|
16150
|
+
debug19("compressing files");
|
|
15978
16151
|
for (const filepath of filepaths) {
|
|
15979
16152
|
const absFilepath = path8.join(srcDirPath, filepath.toString());
|
|
15980
16153
|
if (!isIncludeAllFiles) {
|
|
@@ -15983,12 +16156,12 @@ async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
|
|
|
15983
16156
|
absFilepath.toString().replaceAll(path8.win32.sep, path8.posix.sep),
|
|
15984
16157
|
vulnFiles
|
|
15985
16158
|
)) {
|
|
15986
|
-
|
|
16159
|
+
debug19("ignoring %s because it is not a vulnerability file", filepath);
|
|
15987
16160
|
continue;
|
|
15988
16161
|
}
|
|
15989
16162
|
}
|
|
15990
16163
|
if (fs9.lstatSync(absFilepath).size > MCP_MAX_FILE_SIZE) {
|
|
15991
|
-
|
|
16164
|
+
debug19(
|
|
15992
16165
|
"ignoring %s \u2014 file size exceeds MCP_MAX_FILE_SIZE (%d bytes)",
|
|
15993
16166
|
filepath,
|
|
15994
16167
|
MCP_MAX_FILE_SIZE
|
|
@@ -16006,16 +16179,16 @@ async function pack(srcDirPath, vulnFiles, isIncludeAllFiles = false) {
|
|
|
16006
16179
|
data = fs9.readFileSync(absFilepath);
|
|
16007
16180
|
}
|
|
16008
16181
|
if (isBinary2(null, data)) {
|
|
16009
|
-
|
|
16182
|
+
debug19("ignoring %s because is seems to be a binary file", filepath);
|
|
16010
16183
|
continue;
|
|
16011
16184
|
}
|
|
16012
16185
|
zip.addFile(filepath.toString(), data);
|
|
16013
16186
|
}
|
|
16014
|
-
|
|
16187
|
+
debug19("get zip file buffer");
|
|
16015
16188
|
return zip.toBuffer();
|
|
16016
16189
|
}
|
|
16017
16190
|
async function repackFpr(fprPath) {
|
|
16018
|
-
|
|
16191
|
+
debug19("repack fpr file %s", fprPath);
|
|
16019
16192
|
const zipIn = new AdmZip(fprPath);
|
|
16020
16193
|
const zipOut = new AdmZip();
|
|
16021
16194
|
const mappingXML = zipIn.readAsText("src-archive/index.xml", "utf-8");
|
|
@@ -16030,7 +16203,7 @@ async function repackFpr(fprPath) {
|
|
|
16030
16203
|
zipOut.addFile(realPath, buf);
|
|
16031
16204
|
}
|
|
16032
16205
|
}
|
|
16033
|
-
|
|
16206
|
+
debug19("get repacked zip file buffer");
|
|
16034
16207
|
return zipOut.toBuffer();
|
|
16035
16208
|
}
|
|
16036
16209
|
|
|
@@ -16101,7 +16274,7 @@ async function snykArticlePrompt() {
|
|
|
16101
16274
|
// src/features/analysis/scanners/checkmarx.ts
|
|
16102
16275
|
import { createRequire } from "module";
|
|
16103
16276
|
import chalk5 from "chalk";
|
|
16104
|
-
import
|
|
16277
|
+
import Debug20 from "debug";
|
|
16105
16278
|
import { existsSync } from "fs";
|
|
16106
16279
|
import { createSpinner as createSpinner2 } from "nanospinner";
|
|
16107
16280
|
import { type } from "os";
|
|
@@ -16113,7 +16286,7 @@ var cxOperatingSystemSupportMessage = `Your operating system does not support ch
|
|
|
16113
16286
|
|
|
16114
16287
|
// src/utils/child_process.ts
|
|
16115
16288
|
import cp from "child_process";
|
|
16116
|
-
import
|
|
16289
|
+
import Debug19 from "debug";
|
|
16117
16290
|
import * as process2 from "process";
|
|
16118
16291
|
function createFork({ args, processPath, name }, options) {
|
|
16119
16292
|
const child = cp.fork(processPath, args, {
|
|
@@ -16131,16 +16304,16 @@ function createSpawn({ args, processPath, name, cwd, env: env3 }, options) {
|
|
|
16131
16304
|
return createChildProcess({ childProcess: child, name }, options);
|
|
16132
16305
|
}
|
|
16133
16306
|
function createChildProcess({ childProcess, name }, options) {
|
|
16134
|
-
const
|
|
16307
|
+
const debug24 = Debug19(`mobbdev:${name}`);
|
|
16135
16308
|
const { display } = options;
|
|
16136
16309
|
return new Promise((resolve, reject) => {
|
|
16137
16310
|
let out = "";
|
|
16138
16311
|
const onData = (chunk) => {
|
|
16139
|
-
|
|
16312
|
+
debug24(`chunk received from ${name} std ${chunk}`);
|
|
16140
16313
|
out += chunk;
|
|
16141
16314
|
};
|
|
16142
16315
|
if (!childProcess?.stdout || !childProcess?.stderr) {
|
|
16143
|
-
|
|
16316
|
+
debug24(`unable to fork ${name}`);
|
|
16144
16317
|
reject(new Error(`unable to fork ${name}`));
|
|
16145
16318
|
}
|
|
16146
16319
|
childProcess.stdout?.on("data", onData);
|
|
@@ -16150,18 +16323,18 @@ function createChildProcess({ childProcess, name }, options) {
|
|
|
16150
16323
|
childProcess.stderr?.pipe(process2.stderr);
|
|
16151
16324
|
}
|
|
16152
16325
|
childProcess.on("exit", (code) => {
|
|
16153
|
-
|
|
16326
|
+
debug24(`${name} exit code ${code}`);
|
|
16154
16327
|
resolve({ message: out, code });
|
|
16155
16328
|
});
|
|
16156
16329
|
childProcess.on("error", (err) => {
|
|
16157
|
-
|
|
16330
|
+
debug24(`${name} error %o`, err);
|
|
16158
16331
|
reject(err);
|
|
16159
16332
|
});
|
|
16160
16333
|
});
|
|
16161
16334
|
}
|
|
16162
16335
|
|
|
16163
16336
|
// src/features/analysis/scanners/checkmarx.ts
|
|
16164
|
-
var
|
|
16337
|
+
var debug20 = Debug20("mobbdev:checkmarx");
|
|
16165
16338
|
var moduleUrl;
|
|
16166
16339
|
if (typeof __filename !== "undefined") {
|
|
16167
16340
|
moduleUrl = __filename;
|
|
@@ -16220,14 +16393,14 @@ function validateCheckmarxInstallation() {
|
|
|
16220
16393
|
existsSync(getCheckmarxPath());
|
|
16221
16394
|
}
|
|
16222
16395
|
async function forkCheckmarx(args, { display }) {
|
|
16223
|
-
|
|
16396
|
+
debug20("fork checkmarx with args %o %s", args.join(" "), display);
|
|
16224
16397
|
return createSpawn(
|
|
16225
16398
|
{ args, processPath: getCheckmarxPath(), name: "checkmarx" },
|
|
16226
16399
|
{ display }
|
|
16227
16400
|
);
|
|
16228
16401
|
}
|
|
16229
16402
|
async function getCheckmarxReport({ reportPath, repositoryRoot, branch, projectName }, { skipPrompts = false }) {
|
|
16230
|
-
|
|
16403
|
+
debug20("get checkmarx report start %s %s", reportPath, repositoryRoot);
|
|
16231
16404
|
const { code: loginCode } = await forkCheckmarx(VALIDATE_COMMAND, {
|
|
16232
16405
|
display: false
|
|
16233
16406
|
});
|
|
@@ -16295,10 +16468,10 @@ async function validateCheckamxCredentials() {
|
|
|
16295
16468
|
// src/features/analysis/scanners/snyk.ts
|
|
16296
16469
|
import { createRequire as createRequire2 } from "module";
|
|
16297
16470
|
import chalk6 from "chalk";
|
|
16298
|
-
import
|
|
16471
|
+
import Debug21 from "debug";
|
|
16299
16472
|
import { createSpinner as createSpinner3 } from "nanospinner";
|
|
16300
16473
|
import open2 from "open";
|
|
16301
|
-
var
|
|
16474
|
+
var debug21 = Debug21("mobbdev:snyk");
|
|
16302
16475
|
var moduleUrl2;
|
|
16303
16476
|
if (typeof __filename !== "undefined") {
|
|
16304
16477
|
moduleUrl2 = __filename;
|
|
@@ -16320,13 +16493,13 @@ if (typeof __filename !== "undefined") {
|
|
|
16320
16493
|
var costumeRequire2 = createRequire2(moduleUrl2);
|
|
16321
16494
|
var SNYK_PATH = costumeRequire2.resolve("snyk/bin/snyk");
|
|
16322
16495
|
var SNYK_ARTICLE_URL = "https://docs.snyk.io/scan-using-snyk/snyk-code/configure-snyk-code#enable-snyk-code";
|
|
16323
|
-
|
|
16496
|
+
debug21("snyk executable path %s", SNYK_PATH);
|
|
16324
16497
|
async function forkSnyk(args, { display }) {
|
|
16325
|
-
|
|
16498
|
+
debug21("fork snyk with args %o %s", args, display);
|
|
16326
16499
|
return createFork({ args, processPath: SNYK_PATH, name: "snyk" }, { display });
|
|
16327
16500
|
}
|
|
16328
16501
|
async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
|
|
16329
|
-
|
|
16502
|
+
debug21("get snyk report start %s %s", reportPath, repoRoot);
|
|
16330
16503
|
const config2 = await forkSnyk(["config"], { display: false });
|
|
16331
16504
|
const { message: configMessage } = config2;
|
|
16332
16505
|
if (!configMessage.includes("api: ")) {
|
|
@@ -16340,7 +16513,7 @@ async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
|
|
|
16340
16513
|
snykLoginSpinner.update({
|
|
16341
16514
|
text: "\u{1F513} Waiting for Snyk login to complete"
|
|
16342
16515
|
});
|
|
16343
|
-
|
|
16516
|
+
debug21("no token in the config %s", config2);
|
|
16344
16517
|
await forkSnyk(["auth"], { display: true });
|
|
16345
16518
|
snykLoginSpinner.success({ text: "\u{1F513} Login to Snyk Successful" });
|
|
16346
16519
|
}
|
|
@@ -16350,12 +16523,12 @@ async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
|
|
|
16350
16523
|
{ display: true }
|
|
16351
16524
|
);
|
|
16352
16525
|
if (scanOutput.includes("Snyk Code is not supported for org")) {
|
|
16353
|
-
|
|
16526
|
+
debug21("snyk code is not enabled %s", scanOutput);
|
|
16354
16527
|
snykSpinner.error({ text: "\u{1F50D} Snyk configuration needed" });
|
|
16355
16528
|
const answer = await snykArticlePrompt();
|
|
16356
|
-
|
|
16529
|
+
debug21("answer %s", answer);
|
|
16357
16530
|
if (answer) {
|
|
16358
|
-
|
|
16531
|
+
debug21("opening the browser");
|
|
16359
16532
|
await open2(SNYK_ARTICLE_URL);
|
|
16360
16533
|
}
|
|
16361
16534
|
console.log(
|
|
@@ -16403,9 +16576,9 @@ async function downloadRepo({
|
|
|
16403
16576
|
}) {
|
|
16404
16577
|
const { createSpinner: createSpinner5 } = Spinner2({ ci });
|
|
16405
16578
|
const repoSpinner = createSpinner5("\u{1F4BE} Downloading Repo").start();
|
|
16406
|
-
|
|
16579
|
+
debug22("download repo %s %s %s", repoUrl, dirname);
|
|
16407
16580
|
const zipFilePath = path10.join(dirname, "repo.zip");
|
|
16408
|
-
|
|
16581
|
+
debug22("download URL: %s auth headers: %o", downloadUrl, authHeaders);
|
|
16409
16582
|
const response = await fetch4(downloadUrl, {
|
|
16410
16583
|
method: "GET",
|
|
16411
16584
|
headers: {
|
|
@@ -16413,7 +16586,7 @@ async function downloadRepo({
|
|
|
16413
16586
|
}
|
|
16414
16587
|
});
|
|
16415
16588
|
if (!response.ok) {
|
|
16416
|
-
|
|
16589
|
+
debug22("SCM zipball request failed %s %s", response.body, response.status);
|
|
16417
16590
|
repoSpinner.error({ text: "\u{1F4BE} Repo download failed" });
|
|
16418
16591
|
throw new Error(`Can't access ${chalk7.bold(repoUrl)}`);
|
|
16419
16592
|
}
|
|
@@ -16427,7 +16600,7 @@ async function downloadRepo({
|
|
|
16427
16600
|
if (!repoRoot) {
|
|
16428
16601
|
throw new Error("Repo root not found");
|
|
16429
16602
|
}
|
|
16430
|
-
|
|
16603
|
+
debug22("repo root %s", repoRoot);
|
|
16431
16604
|
repoSpinner.success({ text: "\u{1F4BE} Repo downloaded successfully" });
|
|
16432
16605
|
return path10.join(dirname, repoRoot);
|
|
16433
16606
|
}
|
|
@@ -16436,7 +16609,7 @@ var getReportUrl = ({
|
|
|
16436
16609
|
projectId,
|
|
16437
16610
|
fixReportId
|
|
16438
16611
|
}) => `${WEB_APP_URL}/organization/${organizationId}/project/${projectId}/report/${fixReportId}`;
|
|
16439
|
-
var
|
|
16612
|
+
var debug22 = Debug22("mobbdev:index");
|
|
16440
16613
|
async function runAnalysis(params, options) {
|
|
16441
16614
|
const tmpObj = tmp2.dirSync({
|
|
16442
16615
|
unsafeCleanup: true
|
|
@@ -16583,7 +16756,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
16583
16756
|
polling,
|
|
16584
16757
|
baselineCommit
|
|
16585
16758
|
} = params;
|
|
16586
|
-
|
|
16759
|
+
debug22("start %s %s", dirname, repo);
|
|
16587
16760
|
const { createSpinner: createSpinner5 } = Spinner2({ ci });
|
|
16588
16761
|
skipPrompts = skipPrompts || ci;
|
|
16589
16762
|
const gqlClient = await getAuthenticatedGQLClient({
|
|
@@ -16623,8 +16796,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
16623
16796
|
});
|
|
16624
16797
|
if (!isRepoAvailable) {
|
|
16625
16798
|
if (ci || !cloudScmLibType || !scmAuthUrl) {
|
|
16626
|
-
const
|
|
16627
|
-
throw new Error(
|
|
16799
|
+
const errorMessage3 = scmAuthUrl ? `Cannot access repo ${repo}. Make sure that the repo is accessible and the SCM token configured on Mobb is correct.` : `Cannot access repo ${repo} with the provided token, please visit ${scmAuthUrl} to refresh your source control management system token`;
|
|
16800
|
+
throw new Error(errorMessage3);
|
|
16628
16801
|
}
|
|
16629
16802
|
if (cloudScmLibType && scmAuthUrl) {
|
|
16630
16803
|
await handleScmIntegration(tokenInfo.accessToken, scmAuthUrl, repo);
|
|
@@ -16656,8 +16829,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
16656
16829
|
);
|
|
16657
16830
|
}
|
|
16658
16831
|
const { sha } = getReferenceDataRes.gitReference;
|
|
16659
|
-
|
|
16660
|
-
|
|
16832
|
+
debug22("project id %s", projectId);
|
|
16833
|
+
debug22("default branch %s", reference);
|
|
16661
16834
|
if (command === "scan") {
|
|
16662
16835
|
reportPath = await getReport(
|
|
16663
16836
|
{
|
|
@@ -16994,7 +17167,7 @@ async function _digestReport({
|
|
|
16994
17167
|
text: progressMassages.processingVulnerabilityReportSuccess
|
|
16995
17168
|
});
|
|
16996
17169
|
if (polling) {
|
|
16997
|
-
|
|
17170
|
+
debug22(
|
|
16998
17171
|
"[_digestReport] Using POLLING mode for analysis state updates (--polling flag enabled)"
|
|
16999
17172
|
);
|
|
17000
17173
|
console.log(
|
|
@@ -17009,7 +17182,7 @@ async function _digestReport({
|
|
|
17009
17182
|
timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
|
|
17010
17183
|
});
|
|
17011
17184
|
} else {
|
|
17012
|
-
|
|
17185
|
+
debug22(
|
|
17013
17186
|
"[_digestReport] Using WEBSOCKET mode for analysis state updates (default)"
|
|
17014
17187
|
);
|
|
17015
17188
|
console.log(
|
|
@@ -17034,9 +17207,9 @@ async function _digestReport({
|
|
|
17034
17207
|
});
|
|
17035
17208
|
return vulnFiles;
|
|
17036
17209
|
} catch (e) {
|
|
17037
|
-
const
|
|
17210
|
+
const errorMessage3 = e instanceof ReportDigestError ? e.getDisplayMessage() : ReportDigestError.defaultMessage;
|
|
17038
17211
|
digestSpinner.error({
|
|
17039
|
-
text:
|
|
17212
|
+
text: errorMessage3
|
|
17040
17213
|
});
|
|
17041
17214
|
throw e;
|
|
17042
17215
|
}
|
|
@@ -17073,7 +17246,7 @@ async function waitForAnaysisAndReviewPr({
|
|
|
17073
17246
|
});
|
|
17074
17247
|
};
|
|
17075
17248
|
if (polling) {
|
|
17076
|
-
|
|
17249
|
+
debug22(
|
|
17077
17250
|
"[waitForAnaysisAndReviewPr] Using POLLING mode for analysis state updates"
|
|
17078
17251
|
);
|
|
17079
17252
|
console.log(
|
|
@@ -17087,7 +17260,7 @@ async function waitForAnaysisAndReviewPr({
|
|
|
17087
17260
|
callbackStates: ["Finished" /* Finished */]
|
|
17088
17261
|
});
|
|
17089
17262
|
} else {
|
|
17090
|
-
|
|
17263
|
+
debug22(
|
|
17091
17264
|
"[waitForAnaysisAndReviewPr] Using WEBSOCKET mode for analysis state updates"
|
|
17092
17265
|
);
|
|
17093
17266
|
console.log(
|
|
@@ -17391,11 +17564,11 @@ function throwRepoUrlErrorMessage({
|
|
|
17391
17564
|
repoUrl,
|
|
17392
17565
|
command
|
|
17393
17566
|
}) {
|
|
17394
|
-
const
|
|
17567
|
+
const errorMessage3 = error.issues[error.issues.length - 1]?.message;
|
|
17395
17568
|
const formattedErrorMessage = `
|
|
17396
17569
|
Error: ${chalk9.bold(
|
|
17397
17570
|
repoUrl
|
|
17398
|
-
)} is ${
|
|
17571
|
+
)} is ${errorMessage3}
|
|
17399
17572
|
Example:
|
|
17400
17573
|
mobbdev ${command} -r ${chalk9.bold(
|
|
17401
17574
|
"https://github.com/WebGoat/WebGoat"
|
|
@@ -17523,7 +17696,7 @@ import { spawn } from "child_process";
|
|
|
17523
17696
|
import { readFileSync, writeFileSync as writeFileSync2 } from "fs";
|
|
17524
17697
|
import * as os8 from "os";
|
|
17525
17698
|
import path24 from "path";
|
|
17526
|
-
import { setTimeout as
|
|
17699
|
+
import { setTimeout as sleep3 } from "timers/promises";
|
|
17527
17700
|
import Configstore3 from "configstore";
|
|
17528
17701
|
|
|
17529
17702
|
// src/features/analysis/skill_quarantine/runQuarantineCheck.ts
|
|
@@ -19410,7 +19583,7 @@ function createLogger(config2) {
|
|
|
19410
19583
|
const info = pinoLogger.info.bind(pinoLogger);
|
|
19411
19584
|
const warn = pinoLogger.warn.bind(pinoLogger);
|
|
19412
19585
|
const error = pinoLogger.error.bind(pinoLogger);
|
|
19413
|
-
const
|
|
19586
|
+
const debug24 = pinoLogger.debug.bind(pinoLogger);
|
|
19414
19587
|
function heartbeat(message, data) {
|
|
19415
19588
|
pinoLogger.info({ data, heartbeat: true }, message);
|
|
19416
19589
|
}
|
|
@@ -19453,7 +19626,7 @@ function createLogger(config2) {
|
|
|
19453
19626
|
info,
|
|
19454
19627
|
warn,
|
|
19455
19628
|
error,
|
|
19456
|
-
debug:
|
|
19629
|
+
debug: debug24,
|
|
19457
19630
|
heartbeat,
|
|
19458
19631
|
timed,
|
|
19459
19632
|
flushLogs,
|
|
@@ -19468,7 +19641,7 @@ function createLogger(config2) {
|
|
|
19468
19641
|
|
|
19469
19642
|
// src/features/claude_code/hook_logger.ts
|
|
19470
19643
|
var DD_RUM_TOKEN = true ? "pubf59c0182545bfb4c299175119f1abf9b" : "";
|
|
19471
|
-
var CLI_VERSION = true ? "1.4.
|
|
19644
|
+
var CLI_VERSION = true ? "1.4.22" : "unknown";
|
|
19472
19645
|
var NAMESPACE = "mobbdev-claude-code-hook-logs";
|
|
19473
19646
|
var claudeCodeVersion;
|
|
19474
19647
|
function buildDdTags() {
|
|
@@ -19996,6 +20169,12 @@ async function processTranscript(input, sessionStore, log2, maxEntries = DAEMON_
|
|
|
19996
20169
|
sanitize
|
|
19997
20170
|
})
|
|
19998
20171
|
);
|
|
20172
|
+
if (result.degenerate?.length) {
|
|
20173
|
+
log2.warn(
|
|
20174
|
+
{ data: degenerateRecordsLogFields(result.degenerate) },
|
|
20175
|
+
DEGENERATE_RECORDS_LOG_MESSAGE
|
|
20176
|
+
);
|
|
20177
|
+
}
|
|
19999
20178
|
if (result.ok) {
|
|
20000
20179
|
const lastRawEntry = rawEntries[rawEntries.length - 1];
|
|
20001
20180
|
const cursor = {
|
|
@@ -20566,7 +20745,7 @@ async function startDaemon() {
|
|
|
20566
20745
|
},
|
|
20567
20746
|
"daemon poll cycle"
|
|
20568
20747
|
);
|
|
20569
|
-
await
|
|
20748
|
+
await sleep3(DAEMON_POLL_INTERVAL_MS);
|
|
20570
20749
|
}
|
|
20571
20750
|
}
|
|
20572
20751
|
async function acquirePidFile() {
|
|
@@ -21289,7 +21468,7 @@ var McpGQLClient = class extends GQLClient {
|
|
|
21289
21468
|
{ data }
|
|
21290
21469
|
);
|
|
21291
21470
|
if (!data.analysis?.state || data.analysis?.state === "Failed" /* Failed */) {
|
|
21292
|
-
const
|
|
21471
|
+
const errorMessage3 = data.analysis?.failReason || `Analysis failed with id: ${data.analysis?.id}`;
|
|
21293
21472
|
logError(`[${scanContext}] GraphQL: Analysis failed`, {
|
|
21294
21473
|
analysisId: data.analysis?.id,
|
|
21295
21474
|
state: data.analysis?.state,
|
|
@@ -21297,7 +21476,7 @@ var McpGQLClient = class extends GQLClient {
|
|
|
21297
21476
|
...this.getErrorContext()
|
|
21298
21477
|
});
|
|
21299
21478
|
subscription.unsubscribe();
|
|
21300
|
-
reject(new Error(
|
|
21479
|
+
reject(new Error(errorMessage3));
|
|
21301
21480
|
return;
|
|
21302
21481
|
}
|
|
21303
21482
|
if (callbackStates.includes(data.analysis?.state)) {
|
|
@@ -21409,17 +21588,17 @@ var McpGQLClient = class extends GQLClient {
|
|
|
21409
21588
|
});
|
|
21410
21589
|
return createdProject.createProject.projectId;
|
|
21411
21590
|
} catch (createError) {
|
|
21412
|
-
const
|
|
21413
|
-
const isConstraintViolation =
|
|
21591
|
+
const errorMessage3 = createError instanceof Error ? createError.message : String(createError);
|
|
21592
|
+
const isConstraintViolation = errorMessage3.includes(
|
|
21414
21593
|
"duplicate key value violates unique constraint"
|
|
21415
|
-
) &&
|
|
21594
|
+
) && errorMessage3.includes("project_name_organization_id_key");
|
|
21416
21595
|
if (isConstraintViolation) {
|
|
21417
21596
|
logDebug(
|
|
21418
21597
|
"[GraphQL] Project creation failed due to constraint violation, retrying fetch",
|
|
21419
21598
|
{
|
|
21420
21599
|
organizationId: organization.id,
|
|
21421
21600
|
projectName,
|
|
21422
|
-
error:
|
|
21601
|
+
error: errorMessage3
|
|
21423
21602
|
}
|
|
21424
21603
|
);
|
|
21425
21604
|
const retryOrgAndProjectRes = await this._clientSdk.getLastOrgAndNamedProject({
|
|
@@ -22829,8 +23008,8 @@ var McpServer = class {
|
|
|
22829
23008
|
});
|
|
22830
23009
|
return serializedResponse;
|
|
22831
23010
|
} catch (error) {
|
|
22832
|
-
const
|
|
22833
|
-
logError(`Error executing tool ${name}: ${
|
|
23011
|
+
const errorMessage3 = error instanceof Error ? error.message : String(error);
|
|
23012
|
+
logError(`Error executing tool ${name}: ${errorMessage3}`, {
|
|
22834
23013
|
error,
|
|
22835
23014
|
toolName: name,
|
|
22836
23015
|
args
|
|
@@ -22885,8 +23064,8 @@ var McpServer = class {
|
|
|
22885
23064
|
});
|
|
22886
23065
|
return response;
|
|
22887
23066
|
} catch (error) {
|
|
22888
|
-
const
|
|
22889
|
-
logError(`Error generating prompt ${name}: ${
|
|
23067
|
+
const errorMessage3 = error instanceof Error ? error.message : String(error);
|
|
23068
|
+
logError(`Error generating prompt ${name}: ${errorMessage3}`, {
|
|
22890
23069
|
error,
|
|
22891
23070
|
promptName: name,
|
|
22892
23071
|
args
|
|
@@ -23023,8 +23202,8 @@ var BasePrompt = class {
|
|
|
23023
23202
|
const message = e.message === "Required" ? `Missing required argument '${fieldPath}'` : `Invalid value for '${fieldPath}': ${e.message}`;
|
|
23024
23203
|
return message;
|
|
23025
23204
|
});
|
|
23026
|
-
const
|
|
23027
|
-
throw new Error(
|
|
23205
|
+
const errorMessage3 = `Invalid arguments: ${errorDetails.join(", ")}`;
|
|
23206
|
+
throw new Error(errorMessage3);
|
|
23028
23207
|
}
|
|
23029
23208
|
throw error;
|
|
23030
23209
|
}
|
|
@@ -24733,9 +24912,9 @@ async function validatePath(inputPath) {
|
|
|
24733
24912
|
logDebug("Stored validated path in WorkspaceService", { inputPath });
|
|
24734
24913
|
return { isValid: true, path: inputPath };
|
|
24735
24914
|
} catch (error) {
|
|
24736
|
-
const
|
|
24737
|
-
logError(
|
|
24738
|
-
return { isValid: false, error:
|
|
24915
|
+
const errorMessage3 = `Path does not exist or is not accessible: ${inputPath}`;
|
|
24916
|
+
logError(errorMessage3, { error });
|
|
24917
|
+
return { isValid: false, error: errorMessage3, path: inputPath };
|
|
24739
24918
|
}
|
|
24740
24919
|
}
|
|
24741
24920
|
|
|
@@ -24773,8 +24952,8 @@ var BaseTool = class {
|
|
|
24773
24952
|
const message = e.message === "Required" ? `Missing required parameter '${fieldPath}'` : `Invalid value for '${fieldPath}': ${e.message}`;
|
|
24774
24953
|
return message;
|
|
24775
24954
|
});
|
|
24776
|
-
const
|
|
24777
|
-
throw new Error(
|
|
24955
|
+
const errorMessage3 = `Invalid arguments: ${errorDetails.join(", ")}`;
|
|
24956
|
+
throw new Error(errorMessage3);
|
|
24778
24957
|
}
|
|
24779
24958
|
throw error;
|
|
24780
24959
|
}
|
|
@@ -25746,9 +25925,9 @@ var LocalMobbFolderService = class {
|
|
|
25746
25925
|
});
|
|
25747
25926
|
return mobbFolderPath;
|
|
25748
25927
|
} catch (error) {
|
|
25749
|
-
const
|
|
25750
|
-
logError(
|
|
25751
|
-
throw new Error(
|
|
25928
|
+
const errorMessage3 = `Failed to get/create .mobb folder: ${error}`;
|
|
25929
|
+
logError(errorMessage3, { repoPath: this.repoPath, error });
|
|
25930
|
+
throw new Error(errorMessage3);
|
|
25752
25931
|
}
|
|
25753
25932
|
}
|
|
25754
25933
|
/**
|
|
@@ -25909,8 +26088,8 @@ var LocalMobbFolderService = class {
|
|
|
25909
26088
|
message: `Patch saved successfully as ${uniqueFileName}`
|
|
25910
26089
|
};
|
|
25911
26090
|
} catch (error) {
|
|
25912
|
-
const
|
|
25913
|
-
logError(
|
|
26091
|
+
const errorMessage3 = `Failed to save patch for fix ${fix.id}: ${error}`;
|
|
26092
|
+
logError(errorMessage3, {
|
|
25914
26093
|
fixId: fix.id,
|
|
25915
26094
|
fileName,
|
|
25916
26095
|
severity,
|
|
@@ -25920,8 +26099,8 @@ var LocalMobbFolderService = class {
|
|
|
25920
26099
|
});
|
|
25921
26100
|
return {
|
|
25922
26101
|
success: false,
|
|
25923
|
-
error:
|
|
25924
|
-
message:
|
|
26102
|
+
error: errorMessage3,
|
|
26103
|
+
message: errorMessage3
|
|
25925
26104
|
};
|
|
25926
26105
|
}
|
|
25927
26106
|
}
|
|
@@ -26011,12 +26190,12 @@ var LocalMobbFolderService = class {
|
|
|
26011
26190
|
message: `Fix details logged to patchInfo.md`
|
|
26012
26191
|
};
|
|
26013
26192
|
} catch (error) {
|
|
26014
|
-
const
|
|
26015
|
-
logError(
|
|
26193
|
+
const errorMessage3 = `Failed to log patch info: ${error}`;
|
|
26194
|
+
logError(errorMessage3, { fixId: fix.id, error });
|
|
26016
26195
|
return {
|
|
26017
26196
|
success: false,
|
|
26018
|
-
error:
|
|
26019
|
-
message:
|
|
26197
|
+
error: errorMessage3,
|
|
26198
|
+
message: errorMessage3
|
|
26020
26199
|
};
|
|
26021
26200
|
}
|
|
26022
26201
|
}
|
|
@@ -26711,12 +26890,12 @@ var PatchApplicationService = class {
|
|
|
26711
26890
|
failedFixes.push({ fix, error: result.error || "Unknown error" });
|
|
26712
26891
|
}
|
|
26713
26892
|
} catch (error) {
|
|
26714
|
-
const
|
|
26893
|
+
const errorMessage3 = error instanceof Error ? error.message : String(error);
|
|
26715
26894
|
logError(`[${scanContext}] Failed to apply standalone fix ${fix.id}`, {
|
|
26716
|
-
error:
|
|
26895
|
+
error: errorMessage3,
|
|
26717
26896
|
issueType: fix.safeIssueType
|
|
26718
26897
|
});
|
|
26719
|
-
failedFixes.push({ fix, error:
|
|
26898
|
+
failedFixes.push({ fix, error: errorMessage3 });
|
|
26720
26899
|
}
|
|
26721
26900
|
}
|
|
26722
26901
|
}
|
|
@@ -26767,17 +26946,17 @@ var PatchApplicationService = class {
|
|
|
26767
26946
|
return { success: false, error: result.error };
|
|
26768
26947
|
}
|
|
26769
26948
|
} catch (error) {
|
|
26770
|
-
const
|
|
26949
|
+
const errorMessage3 = error instanceof Error ? error.message : String(error);
|
|
26771
26950
|
logInfo(
|
|
26772
26951
|
`[${scanContext}] Fix ${fix.id} threw exception for ${targetFile}, trying next option if available`,
|
|
26773
26952
|
{
|
|
26774
|
-
error:
|
|
26953
|
+
error: errorMessage3,
|
|
26775
26954
|
issueType: fix.safeIssueType,
|
|
26776
26955
|
attemptNumber,
|
|
26777
26956
|
remainingOptions: totalAttempts - attemptNumber
|
|
26778
26957
|
}
|
|
26779
26958
|
);
|
|
26780
|
-
return { success: false, error:
|
|
26959
|
+
return { success: false, error: errorMessage3 };
|
|
26781
26960
|
}
|
|
26782
26961
|
}
|
|
26783
26962
|
/**
|
|
@@ -27281,18 +27460,18 @@ var PatchApplicationService = class {
|
|
|
27281
27460
|
);
|
|
27282
27461
|
return { success: true };
|
|
27283
27462
|
} catch (patchError) {
|
|
27284
|
-
const
|
|
27463
|
+
const errorMessage3 = patchError instanceof Error ? patchError.message : String(patchError);
|
|
27285
27464
|
logError(
|
|
27286
27465
|
`[${scanContext}] In-memory patch application failed for fix ${fix.id}`,
|
|
27287
27466
|
{
|
|
27288
|
-
errorMessage,
|
|
27467
|
+
errorMessage: errorMessage3,
|
|
27289
27468
|
patchErrorType: patchError instanceof Error ? patchError.name : typeof patchError,
|
|
27290
27469
|
targetFiles
|
|
27291
27470
|
}
|
|
27292
27471
|
);
|
|
27293
27472
|
return {
|
|
27294
27473
|
success: false,
|
|
27295
|
-
error: `Patch application failed: ${
|
|
27474
|
+
error: `Patch application failed: ${errorMessage3}`
|
|
27296
27475
|
};
|
|
27297
27476
|
}
|
|
27298
27477
|
}
|
|
@@ -27912,22 +28091,22 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
27912
28091
|
this.updateFilesScanTimestamps(filesToScan);
|
|
27913
28092
|
this.isInitialScanComplete = true;
|
|
27914
28093
|
} catch (error) {
|
|
27915
|
-
const
|
|
27916
|
-
if (
|
|
28094
|
+
const errorMessage3 = error.message;
|
|
28095
|
+
if (errorMessage3.includes("Authentication failed") || errorMessage3.includes("access-denied") || errorMessage3.includes("Authentication hook unauthorized")) {
|
|
27917
28096
|
logError(
|
|
27918
28097
|
`[${scanContext}] Periodic scan skipped due to authentication failure. Please re-authenticate by running a manual scan.`,
|
|
27919
28098
|
{
|
|
27920
|
-
error:
|
|
28099
|
+
error: errorMessage3
|
|
27921
28100
|
}
|
|
27922
28101
|
);
|
|
27923
28102
|
this.hasAuthenticationFailed = true;
|
|
27924
28103
|
return;
|
|
27925
28104
|
}
|
|
27926
|
-
if (
|
|
28105
|
+
if (errorMessage3.includes("ReportInitializationError")) {
|
|
27927
28106
|
logError(
|
|
27928
28107
|
`[${scanContext}] Periodic scan failed during report initialization`,
|
|
27929
28108
|
{
|
|
27930
|
-
error:
|
|
28109
|
+
error: errorMessage3
|
|
27931
28110
|
}
|
|
27932
28111
|
);
|
|
27933
28112
|
return;
|
|
@@ -28162,12 +28341,12 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
28162
28341
|
const loginContext = createMcpLoginContext("check_new_fixes");
|
|
28163
28342
|
this.gqlClient = await createAuthenticatedMcpGQLClient({ loginContext });
|
|
28164
28343
|
} catch (error) {
|
|
28165
|
-
const
|
|
28166
|
-
if (
|
|
28344
|
+
const errorMessage3 = error.message;
|
|
28345
|
+
if (errorMessage3.includes("Authentication failed") || errorMessage3.includes("access-denied") || errorMessage3.includes("Authentication hook unauthorized")) {
|
|
28167
28346
|
logError(
|
|
28168
28347
|
`[${scanContext}] Failed to create authenticated client due to authentication failure`,
|
|
28169
28348
|
{
|
|
28170
|
-
error:
|
|
28349
|
+
error: errorMessage3
|
|
28171
28350
|
}
|
|
28172
28351
|
);
|
|
28173
28352
|
this.hasAuthenticationFailed = true;
|
|
@@ -30037,13 +30216,13 @@ var parseArgs = async (args) => {
|
|
|
30037
30216
|
};
|
|
30038
30217
|
|
|
30039
30218
|
// src/index.ts
|
|
30040
|
-
var
|
|
30219
|
+
var debug23 = Debug23("mobbdev:index");
|
|
30041
30220
|
async function run() {
|
|
30042
30221
|
return parseArgs(hideBin(process.argv));
|
|
30043
30222
|
}
|
|
30044
30223
|
(async () => {
|
|
30045
30224
|
try {
|
|
30046
|
-
|
|
30225
|
+
debug23("Bugsy CLI v%s running...", packageJson.version);
|
|
30047
30226
|
await run();
|
|
30048
30227
|
process.exit(0);
|
|
30049
30228
|
} catch (err) {
|