mobbdev 1.2.36 → 1.2.45
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 +116 -68
- package/dist/index.mjs +365 -516
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -2696,12 +2696,11 @@ var init_env = __esm({
|
|
|
2696
2696
|
});
|
|
2697
2697
|
|
|
2698
2698
|
// src/mcp/core/configs.ts
|
|
2699
|
-
var
|
|
2699
|
+
var MCP_LOGIN_MAX_WAIT, MCP_LOGIN_CHECK_DELAY, MCP_VUL_REPORT_DIGEST_TIMEOUT_MS, MCP_MAX_FILE_SIZE, MCP_PERIODIC_CHECK_INTERVAL, MCP_DEFAULT_MAX_FILES_TO_SCAN, MCP_REPORT_ID_EXPIRATION_MS, MCP_TOOLS_BROWSER_COOLDOWN_MS, MCP_DEFAULT_LIMIT, isAutoScan, MVS_AUTO_FIX_OVERRIDE, MCP_AUTO_FIX_DEBUG_MODE, MCP_PERIODIC_TRACK_INTERVAL, MCP_DEFAULT_REST_API_URL, MCP_SYSTEM_FIND_TIMEOUT_MS;
|
|
2700
2700
|
var init_configs = __esm({
|
|
2701
2701
|
"src/mcp/core/configs.ts"() {
|
|
2702
2702
|
"use strict";
|
|
2703
2703
|
init_env();
|
|
2704
|
-
MCP_API_KEY_HEADER_NAME = "x-mobb-key";
|
|
2705
2704
|
MCP_LOGIN_MAX_WAIT = 2 * 60 * 1e3;
|
|
2706
2705
|
MCP_LOGIN_CHECK_DELAY = 2 * 1e3;
|
|
2707
2706
|
MCP_VUL_REPORT_DIGEST_TIMEOUT_MS = 30 * 60 * 1e3;
|
|
@@ -11013,16 +11012,20 @@ function createGitWithLogging(dirName, logger2 = defaultLogger) {
|
|
|
11013
11012
|
}).outputHandler((bin, stdout2, stderr2) => {
|
|
11014
11013
|
const callID = Math.random();
|
|
11015
11014
|
logger2.info({ callID, bin }, "Start git CLI call");
|
|
11016
|
-
|
|
11017
|
-
|
|
11018
|
-
let
|
|
11019
|
-
let
|
|
11020
|
-
|
|
11021
|
-
|
|
11022
|
-
|
|
11023
|
-
|
|
11015
|
+
let errChunks = [];
|
|
11016
|
+
let outChunks = [];
|
|
11017
|
+
let isStdoutDone = false;
|
|
11018
|
+
let isStderrDone = false;
|
|
11019
|
+
const onStderrData = (data) => errChunks.push(data.toString("utf8"));
|
|
11020
|
+
const onStdoutData = (data) => outChunks.push(data.toString("utf8"));
|
|
11021
|
+
stderr2.on("data", onStderrData);
|
|
11022
|
+
stdout2.on("data", onStdoutData);
|
|
11023
|
+
let finalized = false;
|
|
11024
|
+
function finalizeAndCleanup() {
|
|
11025
|
+
if (finalized || !isStderrDone || !isStdoutDone) {
|
|
11024
11026
|
return;
|
|
11025
11027
|
}
|
|
11028
|
+
finalized = true;
|
|
11026
11029
|
const logObj = {
|
|
11027
11030
|
callID,
|
|
11028
11031
|
bin,
|
|
@@ -11030,14 +11033,25 @@ function createGitWithLogging(dirName, logger2 = defaultLogger) {
|
|
|
11030
11033
|
out: `${outChunks.join("").slice(0, 200)}...`
|
|
11031
11034
|
};
|
|
11032
11035
|
logger2.info(logObj, "git log output");
|
|
11033
|
-
|
|
11034
|
-
|
|
11035
|
-
|
|
11036
|
-
|
|
11036
|
+
stderr2.removeListener("data", onStderrData);
|
|
11037
|
+
stdout2.removeListener("data", onStdoutData);
|
|
11038
|
+
errChunks = [];
|
|
11039
|
+
outChunks = [];
|
|
11040
|
+
}
|
|
11041
|
+
function markDone(stream) {
|
|
11042
|
+
if (stream === "stderr") isStderrDone = true;
|
|
11043
|
+
else isStdoutDone = true;
|
|
11044
|
+
finalizeAndCleanup();
|
|
11045
|
+
}
|
|
11046
|
+
stderr2.on("close", () => markDone("stderr"));
|
|
11047
|
+
stdout2.on("close", () => markDone("stdout"));
|
|
11048
|
+
stderr2.on("error", (error) => {
|
|
11049
|
+
logger2.info({ callID, error: String(error) }, "git stderr stream error");
|
|
11050
|
+
markDone("stderr");
|
|
11037
11051
|
});
|
|
11038
|
-
stdout2.on("
|
|
11039
|
-
|
|
11040
|
-
|
|
11052
|
+
stdout2.on("error", (error) => {
|
|
11053
|
+
logger2.info({ callID, error: String(error) }, "git stdout stream error");
|
|
11054
|
+
markDone("stdout");
|
|
11041
11055
|
});
|
|
11042
11056
|
});
|
|
11043
11057
|
}
|
|
@@ -11749,14 +11763,10 @@ import open3 from "open";
|
|
|
11749
11763
|
import tmp2 from "tmp";
|
|
11750
11764
|
import { z as z31 } from "zod";
|
|
11751
11765
|
|
|
11752
|
-
// src/commands/handleMobbLogin.ts
|
|
11753
|
-
import chalk4 from "chalk";
|
|
11754
|
-
import Debug10 from "debug";
|
|
11755
|
-
|
|
11756
11766
|
// src/commands/AuthManager.ts
|
|
11757
11767
|
import crypto from "crypto";
|
|
11758
11768
|
import os3 from "os";
|
|
11759
|
-
import
|
|
11769
|
+
import Debug10 from "debug";
|
|
11760
11770
|
import open from "open";
|
|
11761
11771
|
|
|
11762
11772
|
// src/features/analysis/graphql/gql.ts
|
|
@@ -11771,12 +11781,6 @@ var ApiConnectionError = class extends Error {
|
|
|
11771
11781
|
this.name = "ApiConnectionError";
|
|
11772
11782
|
}
|
|
11773
11783
|
};
|
|
11774
|
-
var CliLoginError = class extends Error {
|
|
11775
|
-
constructor(message = "CLI login failed") {
|
|
11776
|
-
super(message);
|
|
11777
|
-
this.name = "CliLoginError";
|
|
11778
|
-
}
|
|
11779
|
-
};
|
|
11780
11784
|
var AuthenticationError = class extends Error {
|
|
11781
11785
|
constructor(message = "Authentication failed") {
|
|
11782
11786
|
super(message);
|
|
@@ -12106,9 +12110,19 @@ function isAuthError(error) {
|
|
|
12106
12110
|
}
|
|
12107
12111
|
return false;
|
|
12108
12112
|
}
|
|
12109
|
-
function
|
|
12113
|
+
function isTransientError(error) {
|
|
12110
12114
|
const errorString = error?.toString() ?? "";
|
|
12111
|
-
|
|
12115
|
+
if (errorString.includes("FetchError") || errorString.includes("TypeError") || errorString.includes("ECONNREFUSED") || errorString.includes("ENOTFOUND") || errorString.includes("ETIMEDOUT") || errorString.includes("UND_ERR")) {
|
|
12116
|
+
return true;
|
|
12117
|
+
}
|
|
12118
|
+
if (error instanceof ClientError) {
|
|
12119
|
+
const status = error.response?.status;
|
|
12120
|
+
if (status && status >= 502 && status <= 504) return true;
|
|
12121
|
+
}
|
|
12122
|
+
if (errorString.includes("Gateway Time-out") || errorString.includes("Bad Gateway") || errorString.includes("Service Unavailable")) {
|
|
12123
|
+
return true;
|
|
12124
|
+
}
|
|
12125
|
+
return false;
|
|
12112
12126
|
}
|
|
12113
12127
|
var API_KEY_HEADER_NAME = "x-mobb-key";
|
|
12114
12128
|
var REPORT_STATE_CHECK_DELAY = 5 * 1e3;
|
|
@@ -12169,8 +12183,8 @@ var GQLClient = class {
|
|
|
12169
12183
|
try {
|
|
12170
12184
|
await this.getUserInfo();
|
|
12171
12185
|
} catch (e) {
|
|
12172
|
-
if (
|
|
12173
|
-
debug7("verify connection failed (
|
|
12186
|
+
if (isTransientError(e)) {
|
|
12187
|
+
debug7("verify connection failed (transient error) %o", e);
|
|
12174
12188
|
return false;
|
|
12175
12189
|
}
|
|
12176
12190
|
debug7("verify connection: endpoint reachable but request failed %o", e);
|
|
@@ -12191,11 +12205,7 @@ var GQLClient = class {
|
|
|
12191
12205
|
debug7("verify token failed - auth error %o", e);
|
|
12192
12206
|
return false;
|
|
12193
12207
|
}
|
|
12194
|
-
|
|
12195
|
-
debug7("verify token failed - network error, rethrowing %o", e);
|
|
12196
|
-
throw e;
|
|
12197
|
-
}
|
|
12198
|
-
debug7("verify token failed - unexpected error, rethrowing %o", e);
|
|
12208
|
+
debug7("verify token failed - transient/unknown error, rethrowing %o", e);
|
|
12199
12209
|
throw e;
|
|
12200
12210
|
}
|
|
12201
12211
|
}
|
|
@@ -12252,11 +12262,7 @@ var GQLClient = class {
|
|
|
12252
12262
|
return res?.cli_login_by_pk?.encryptedApiToken || null;
|
|
12253
12263
|
}
|
|
12254
12264
|
async createCommunityUser() {
|
|
12255
|
-
|
|
12256
|
-
await this._clientSdk.CreateCommunityUser();
|
|
12257
|
-
} catch (e) {
|
|
12258
|
-
debug7("create community user failed %o", e);
|
|
12259
|
-
}
|
|
12265
|
+
await this._clientSdk.CreateCommunityUser();
|
|
12260
12266
|
}
|
|
12261
12267
|
async updateScmToken(args) {
|
|
12262
12268
|
const { scmType, url, token, org, refreshToken } = args;
|
|
@@ -12579,23 +12585,127 @@ var GQLClient = class {
|
|
|
12579
12585
|
// src/features/analysis/graphql/tracy-batch-upload.ts
|
|
12580
12586
|
import { promisify } from "util";
|
|
12581
12587
|
import { gzip } from "zlib";
|
|
12582
|
-
import
|
|
12588
|
+
import Debug9 from "debug";
|
|
12583
12589
|
|
|
12584
12590
|
// src/args/commands/upload_ai_blame.ts
|
|
12585
12591
|
import fsPromises2 from "fs/promises";
|
|
12586
12592
|
import * as os2 from "os";
|
|
12587
12593
|
import path7 from "path";
|
|
12588
|
-
import
|
|
12594
|
+
import chalk4 from "chalk";
|
|
12589
12595
|
import { withFile } from "tmp-promise";
|
|
12590
12596
|
import z27 from "zod";
|
|
12597
|
+
|
|
12598
|
+
// src/commands/handleMobbLogin.ts
|
|
12599
|
+
import chalk3 from "chalk";
|
|
12600
|
+
import Debug7 from "debug";
|
|
12601
|
+
var debug8 = Debug7("mobbdev:commands");
|
|
12602
|
+
var MOBB_LOGIN_REQUIRED_MSG = `\u{1F513} Login to Mobb is Required, you will be redirected to our login page, once the authorization is complete return to this prompt, ${chalk3.bgBlue(
|
|
12603
|
+
"press any key to continue"
|
|
12604
|
+
)};`;
|
|
12605
|
+
async function getAuthenticatedGQLClient({
|
|
12606
|
+
inputApiKey = "",
|
|
12607
|
+
isSkipPrompts = true,
|
|
12608
|
+
apiUrl,
|
|
12609
|
+
webAppUrl
|
|
12610
|
+
}) {
|
|
12611
|
+
debug8(
|
|
12612
|
+
"getAuthenticatedGQLClient called with: apiUrl=%s, webAppUrl=%s",
|
|
12613
|
+
apiUrl || "undefined",
|
|
12614
|
+
webAppUrl || "undefined"
|
|
12615
|
+
);
|
|
12616
|
+
const authManager = new AuthManager(webAppUrl, apiUrl);
|
|
12617
|
+
let gqlClient = authManager.getGQLClient(inputApiKey);
|
|
12618
|
+
gqlClient = await handleMobbLogin({
|
|
12619
|
+
inGqlClient: gqlClient,
|
|
12620
|
+
skipPrompts: isSkipPrompts,
|
|
12621
|
+
apiUrl,
|
|
12622
|
+
webAppUrl
|
|
12623
|
+
});
|
|
12624
|
+
return gqlClient;
|
|
12625
|
+
}
|
|
12626
|
+
async function handleMobbLogin({
|
|
12627
|
+
inGqlClient,
|
|
12628
|
+
apiKey,
|
|
12629
|
+
skipPrompts,
|
|
12630
|
+
apiUrl,
|
|
12631
|
+
webAppUrl,
|
|
12632
|
+
loginContext,
|
|
12633
|
+
loginPath
|
|
12634
|
+
}) {
|
|
12635
|
+
debug8(
|
|
12636
|
+
"handleMobbLogin: resolved URLs - apiUrl=%s (from param: %s), webAppUrl=%s (from param: %s)",
|
|
12637
|
+
apiUrl || "fallback",
|
|
12638
|
+
apiUrl || "fallback",
|
|
12639
|
+
webAppUrl || "fallback",
|
|
12640
|
+
webAppUrl || "fallback"
|
|
12641
|
+
);
|
|
12642
|
+
const { createSpinner: createSpinner5 } = Spinner({ ci: skipPrompts });
|
|
12643
|
+
const authManager = new AuthManager(webAppUrl, apiUrl);
|
|
12644
|
+
authManager.setGQLClient(inGqlClient);
|
|
12645
|
+
const authResult = await authManager.checkAuthentication();
|
|
12646
|
+
if (authResult.isAuthenticated) {
|
|
12647
|
+
createSpinner5().start().success({
|
|
12648
|
+
text: `\u{1F513} Login to Mobb succeeded. Already authenticated`
|
|
12649
|
+
});
|
|
12650
|
+
return authManager.getGQLClient();
|
|
12651
|
+
}
|
|
12652
|
+
if (authResult.reason === "unknown") {
|
|
12653
|
+
debug8("Auth check returned unknown: %s", authResult.message);
|
|
12654
|
+
throw new CliError(`Cannot verify authentication: ${authResult.message}`);
|
|
12655
|
+
}
|
|
12656
|
+
if (apiKey) {
|
|
12657
|
+
createSpinner5().start().error({
|
|
12658
|
+
text: "\u{1F513} Login to Mobb failed: The provided API key does not match any configured API key on the system"
|
|
12659
|
+
});
|
|
12660
|
+
throw new CliError(
|
|
12661
|
+
"Login to Mobb failed: The provided API key does not match any configured API key on the system"
|
|
12662
|
+
);
|
|
12663
|
+
}
|
|
12664
|
+
const loginSpinner = createSpinner5().start();
|
|
12665
|
+
if (!skipPrompts) {
|
|
12666
|
+
loginSpinner.update({ text: MOBB_LOGIN_REQUIRED_MSG });
|
|
12667
|
+
await keypress();
|
|
12668
|
+
}
|
|
12669
|
+
loginSpinner.update({
|
|
12670
|
+
text: "\u{1F513} Waiting for Mobb login..."
|
|
12671
|
+
});
|
|
12672
|
+
try {
|
|
12673
|
+
const loginUrl = await authManager.generateLoginUrl(loginPath, loginContext);
|
|
12674
|
+
if (!loginUrl) {
|
|
12675
|
+
loginSpinner.error({
|
|
12676
|
+
text: "Failed to generate login URL"
|
|
12677
|
+
});
|
|
12678
|
+
throw new CliError("Failed to generate login URL");
|
|
12679
|
+
}
|
|
12680
|
+
!skipPrompts && console.log(
|
|
12681
|
+
`If the page does not open automatically, kindly access it through ${loginUrl}.`
|
|
12682
|
+
);
|
|
12683
|
+
authManager.openUrlInBrowser();
|
|
12684
|
+
const authSuccess = await authManager.waitForAuthentication();
|
|
12685
|
+
if (!authSuccess) {
|
|
12686
|
+
loginSpinner.error({
|
|
12687
|
+
text: "Login timeout error"
|
|
12688
|
+
});
|
|
12689
|
+
throw new CliError("Login timeout error");
|
|
12690
|
+
}
|
|
12691
|
+
loginSpinner.success({
|
|
12692
|
+
text: `\u{1F513} Login to Mobb successful!`
|
|
12693
|
+
});
|
|
12694
|
+
return authManager.getGQLClient();
|
|
12695
|
+
} finally {
|
|
12696
|
+
authManager.cleanup();
|
|
12697
|
+
}
|
|
12698
|
+
}
|
|
12699
|
+
|
|
12700
|
+
// src/args/commands/upload_ai_blame.ts
|
|
12591
12701
|
init_client_generates();
|
|
12592
12702
|
init_GitService();
|
|
12593
12703
|
init_urlParser2();
|
|
12594
12704
|
|
|
12595
12705
|
// src/features/analysis/upload-file.ts
|
|
12596
|
-
import
|
|
12706
|
+
import Debug8 from "debug";
|
|
12597
12707
|
import fetch3, { File, fileFrom, FormData } from "node-fetch";
|
|
12598
|
-
var
|
|
12708
|
+
var debug9 = Debug8("mobbdev:upload-file");
|
|
12599
12709
|
async function uploadFile({
|
|
12600
12710
|
file,
|
|
12601
12711
|
url,
|
|
@@ -12608,9 +12718,9 @@ async function uploadFile({
|
|
|
12608
12718
|
logInfo2(`FileUpload: upload file start ${url}`);
|
|
12609
12719
|
logInfo2(`FileUpload: upload fields`, uploadFields);
|
|
12610
12720
|
logInfo2(`FileUpload: upload key ${uploadKey}`);
|
|
12611
|
-
|
|
12612
|
-
|
|
12613
|
-
|
|
12721
|
+
debug9("upload file start %s", url);
|
|
12722
|
+
debug9("upload fields %o", uploadFields);
|
|
12723
|
+
debug9("upload key %s", uploadKey);
|
|
12614
12724
|
const form = new FormData();
|
|
12615
12725
|
Object.entries(uploadFields).forEach(([key, value]) => {
|
|
12616
12726
|
form.append(key, value);
|
|
@@ -12619,11 +12729,11 @@ async function uploadFile({
|
|
|
12619
12729
|
form.append("key", uploadKey);
|
|
12620
12730
|
}
|
|
12621
12731
|
if (typeof file === "string") {
|
|
12622
|
-
|
|
12732
|
+
debug9("upload file from path %s", file);
|
|
12623
12733
|
logInfo2(`FileUpload: upload file from path ${file}`);
|
|
12624
12734
|
form.append("file", await fileFrom(file));
|
|
12625
12735
|
} else {
|
|
12626
|
-
|
|
12736
|
+
debug9("upload file from buffer");
|
|
12627
12737
|
logInfo2(`FileUpload: upload file from buffer`);
|
|
12628
12738
|
form.append("file", new File([new Uint8Array(file)], "file"));
|
|
12629
12739
|
}
|
|
@@ -12634,11 +12744,11 @@ async function uploadFile({
|
|
|
12634
12744
|
agent
|
|
12635
12745
|
});
|
|
12636
12746
|
if (!response.ok) {
|
|
12637
|
-
|
|
12747
|
+
debug9("error from S3 %s %s", response.body, response.status);
|
|
12638
12748
|
logInfo2(`FileUpload: error from S3 ${response.body} ${response.status}`);
|
|
12639
12749
|
throw new Error(`Failed to upload the file: ${response.status}`);
|
|
12640
12750
|
}
|
|
12641
|
-
|
|
12751
|
+
debug9("upload file done");
|
|
12642
12752
|
logInfo2(`FileUpload: upload file done`);
|
|
12643
12753
|
}
|
|
12644
12754
|
|
|
@@ -12978,33 +13088,33 @@ function uploadAiBlameBuilder(args) {
|
|
|
12978
13088
|
type: "string",
|
|
12979
13089
|
array: true,
|
|
12980
13090
|
demandOption: true,
|
|
12981
|
-
describe:
|
|
13091
|
+
describe: chalk4.bold("Path(s) to prompt artifact(s) (one per session)")
|
|
12982
13092
|
}).option("inference", {
|
|
12983
13093
|
type: "string",
|
|
12984
13094
|
array: true,
|
|
12985
13095
|
demandOption: true,
|
|
12986
|
-
describe:
|
|
13096
|
+
describe: chalk4.bold(
|
|
12987
13097
|
"Path(s) to inference artifact(s) (one per session)"
|
|
12988
13098
|
)
|
|
12989
13099
|
}).option("ai-response-at", {
|
|
12990
13100
|
type: "string",
|
|
12991
13101
|
array: true,
|
|
12992
|
-
describe:
|
|
13102
|
+
describe: chalk4.bold(
|
|
12993
13103
|
"ISO timestamp(s) for AI response (one per session, defaults to now)"
|
|
12994
13104
|
)
|
|
12995
13105
|
}).option("model", {
|
|
12996
13106
|
type: "string",
|
|
12997
13107
|
array: true,
|
|
12998
|
-
describe:
|
|
13108
|
+
describe: chalk4.bold("AI model name(s) (optional, one per session)")
|
|
12999
13109
|
}).option("tool-name", {
|
|
13000
13110
|
type: "string",
|
|
13001
13111
|
array: true,
|
|
13002
|
-
describe:
|
|
13112
|
+
describe: chalk4.bold("Tool/IDE name(s) (optional, one per session)")
|
|
13003
13113
|
}).option("blame-type", {
|
|
13004
13114
|
type: "string",
|
|
13005
13115
|
array: true,
|
|
13006
13116
|
choices: Object.values(AiBlameInferenceType),
|
|
13007
|
-
describe:
|
|
13117
|
+
describe: chalk4.bold(
|
|
13008
13118
|
"Blame type(s) (optional, one per session, defaults to CHAT)"
|
|
13009
13119
|
)
|
|
13010
13120
|
}).strict();
|
|
@@ -13086,7 +13196,7 @@ async function uploadAiBlameHandler(options) {
|
|
|
13086
13196
|
const sessionIds = args.sessionId || args["session-id"] || [];
|
|
13087
13197
|
if (prompts.length !== inferences.length) {
|
|
13088
13198
|
const errorMsg = "prompt and inference must have the same number of entries";
|
|
13089
|
-
logger2.error(
|
|
13199
|
+
logger2.error(chalk4.red(errorMsg));
|
|
13090
13200
|
if (exitOnError) {
|
|
13091
13201
|
process.exit(1);
|
|
13092
13202
|
}
|
|
@@ -13106,7 +13216,7 @@ async function uploadAiBlameHandler(options) {
|
|
|
13106
13216
|
]);
|
|
13107
13217
|
} catch {
|
|
13108
13218
|
const errorMsg = `File not found for session ${i + 1}`;
|
|
13109
|
-
logger2.error(
|
|
13219
|
+
logger2.error(chalk4.red(errorMsg));
|
|
13110
13220
|
if (exitOnError) {
|
|
13111
13221
|
process.exit(1);
|
|
13112
13222
|
}
|
|
@@ -13139,7 +13249,7 @@ async function uploadAiBlameHandler(options) {
|
|
|
13139
13249
|
const uploadSessions = initRes.uploadAIBlameInferencesInit?.uploadSessions ?? [];
|
|
13140
13250
|
if (uploadSessions.length !== sessions.length) {
|
|
13141
13251
|
const errorMsg = "Init failed to return expected number of sessions";
|
|
13142
|
-
logger2.error(
|
|
13252
|
+
logger2.error(chalk4.red(errorMsg));
|
|
13143
13253
|
if (exitOnError) {
|
|
13144
13254
|
process.exit(1);
|
|
13145
13255
|
}
|
|
@@ -13196,7 +13306,7 @@ async function uploadAiBlameHandler(options) {
|
|
|
13196
13306
|
if (status !== "OK") {
|
|
13197
13307
|
const errorMsg = finRes?.finalizeAIBlameInferencesUpload?.error || "unknown error";
|
|
13198
13308
|
logger2.error(
|
|
13199
|
-
|
|
13309
|
+
chalk4.red(
|
|
13200
13310
|
`[UPLOAD] Finalize failed with status: ${status}, error: ${errorMsg}`
|
|
13201
13311
|
)
|
|
13202
13312
|
);
|
|
@@ -13205,7 +13315,7 @@ async function uploadAiBlameHandler(options) {
|
|
|
13205
13315
|
}
|
|
13206
13316
|
throw new Error(errorMsg);
|
|
13207
13317
|
}
|
|
13208
|
-
logger2.info(
|
|
13318
|
+
logger2.info(chalk4.green("[UPLOAD] AI Blame uploads finalized successfully"));
|
|
13209
13319
|
} catch (error) {
|
|
13210
13320
|
logger2.error("[UPLOAD] Finalize threw error:", error);
|
|
13211
13321
|
throw error;
|
|
@@ -13217,7 +13327,7 @@ async function uploadAiBlameCommandHandler(args) {
|
|
|
13217
13327
|
|
|
13218
13328
|
// src/features/analysis/graphql/tracy-batch-upload.ts
|
|
13219
13329
|
var gzipAsync = promisify(gzip);
|
|
13220
|
-
var
|
|
13330
|
+
var debug10 = Debug9("mobbdev:tracy-batch-upload");
|
|
13221
13331
|
var MAX_BATCH_PAYLOAD_BYTES = 3 * 1024 * 1024;
|
|
13222
13332
|
|
|
13223
13333
|
// src/mcp/services/types.ts
|
|
@@ -13253,9 +13363,9 @@ function buildLoginUrl(baseUrl, loginId, hostname, context) {
|
|
|
13253
13363
|
}
|
|
13254
13364
|
|
|
13255
13365
|
// src/commands/AuthManager.ts
|
|
13256
|
-
var
|
|
13257
|
-
var LOGIN_MAX_WAIT =
|
|
13258
|
-
var LOGIN_CHECK_DELAY =
|
|
13366
|
+
var debug11 = Debug10("mobbdev:auth");
|
|
13367
|
+
var LOGIN_MAX_WAIT = 2 * 60 * 1e3;
|
|
13368
|
+
var LOGIN_CHECK_DELAY = 2 * 1e3;
|
|
13259
13369
|
var _AuthManager = class _AuthManager {
|
|
13260
13370
|
constructor(webAppUrl, apiUrl) {
|
|
13261
13371
|
__publicField(this, "publicKey");
|
|
@@ -13269,22 +13379,33 @@ var _AuthManager = class _AuthManager {
|
|
|
13269
13379
|
this.resolvedWebAppUrl = webAppUrl || WEB_APP_URL;
|
|
13270
13380
|
this.resolvedApiUrl = apiUrl || API_URL;
|
|
13271
13381
|
}
|
|
13382
|
+
/** Set the minimum interval between browser opens (MCP sets this to 24h) */
|
|
13383
|
+
static setBrowserCooldown(ms) {
|
|
13384
|
+
_AuthManager.browserCooldownMs = ms;
|
|
13385
|
+
}
|
|
13386
|
+
/** Reset cooldown state. Used by tests to ensure isolation. */
|
|
13387
|
+
static resetCooldown() {
|
|
13388
|
+
_AuthManager.lastBrowserOpenTime = 0;
|
|
13389
|
+
_AuthManager.browserCooldownMs = 0;
|
|
13390
|
+
}
|
|
13272
13391
|
openUrlInBrowser() {
|
|
13273
|
-
if (this.currentBrowserUrl) {
|
|
13274
|
-
|
|
13275
|
-
return true;
|
|
13392
|
+
if (!this.currentBrowserUrl) {
|
|
13393
|
+
return false;
|
|
13276
13394
|
}
|
|
13277
|
-
|
|
13395
|
+
if (_AuthManager.browserCooldownMs > 0 && Date.now() - _AuthManager.lastBrowserOpenTime < _AuthManager.browserCooldownMs) {
|
|
13396
|
+
debug11("browser cooldown active, skipping open");
|
|
13397
|
+
return false;
|
|
13398
|
+
}
|
|
13399
|
+
open(this.currentBrowserUrl);
|
|
13400
|
+
_AuthManager.lastBrowserOpenTime = Date.now();
|
|
13401
|
+
return true;
|
|
13278
13402
|
}
|
|
13403
|
+
/**
|
|
13404
|
+
* Polls for the encrypted API token, decrypts it, validates it, and stores it.
|
|
13405
|
+
* Returns true if login succeeded.
|
|
13406
|
+
*/
|
|
13279
13407
|
async waitForAuthentication() {
|
|
13280
|
-
|
|
13281
|
-
for (let i = 0; i < _AuthManager.loginMaxWait / LOGIN_CHECK_DELAY; i++) {
|
|
13282
|
-
newApiToken = await this.getApiToken();
|
|
13283
|
-
if (newApiToken) {
|
|
13284
|
-
break;
|
|
13285
|
-
}
|
|
13286
|
-
await sleep(LOGIN_CHECK_DELAY);
|
|
13287
|
-
}
|
|
13408
|
+
const newApiToken = await this.waitForApiToken();
|
|
13288
13409
|
if (!newApiToken) {
|
|
13289
13410
|
return false;
|
|
13290
13411
|
}
|
|
@@ -13302,52 +13423,75 @@ var _AuthManager = class _AuthManager {
|
|
|
13302
13423
|
return false;
|
|
13303
13424
|
}
|
|
13304
13425
|
/**
|
|
13305
|
-
*
|
|
13426
|
+
* Polls for the encrypted API token and decrypts it.
|
|
13427
|
+
* Does NOT validate or store the token — use this when the caller
|
|
13428
|
+
* needs to validate on a specific client type (e.g. McpGQLClient).
|
|
13429
|
+
*/
|
|
13430
|
+
async waitForApiToken() {
|
|
13431
|
+
for (let i = 0; i < _AuthManager.loginMaxWait / LOGIN_CHECK_DELAY; i++) {
|
|
13432
|
+
const token = await this.getApiToken();
|
|
13433
|
+
if (token) {
|
|
13434
|
+
return token;
|
|
13435
|
+
}
|
|
13436
|
+
await sleep(LOGIN_CHECK_DELAY);
|
|
13437
|
+
}
|
|
13438
|
+
return null;
|
|
13439
|
+
}
|
|
13440
|
+
/**
|
|
13441
|
+
* Checks if the user is already authenticated.
|
|
13442
|
+
* Returns the full AuthResult so callers can distinguish 'invalid' from 'unknown'.
|
|
13306
13443
|
*/
|
|
13307
13444
|
async isAuthenticated() {
|
|
13308
13445
|
if (this.authenticated === null) {
|
|
13309
13446
|
const result = await this.checkAuthentication();
|
|
13310
13447
|
this.authenticated = result.isAuthenticated;
|
|
13311
13448
|
if (!result.isAuthenticated) {
|
|
13312
|
-
|
|
13449
|
+
debug11("isAuthenticated: false \u2014 %s (%s)", result.message, result.reason);
|
|
13313
13450
|
}
|
|
13314
13451
|
}
|
|
13315
13452
|
return this.authenticated;
|
|
13316
13453
|
}
|
|
13317
13454
|
/**
|
|
13318
|
-
*
|
|
13455
|
+
* Full 3-state auth check returning an {@link AuthResult}.
|
|
13456
|
+
*
|
|
13457
|
+
* - `isAuthenticated: true` — token is valid.
|
|
13458
|
+
* - `reason: 'invalid'` — definitive auth failure (access-denied). Caller should trigger login.
|
|
13459
|
+
* - `reason: 'unknown'` — transient/network error. Caller should NOT trigger login.
|
|
13319
13460
|
*/
|
|
13320
13461
|
async checkAuthentication(apiKey) {
|
|
13462
|
+
if (!this.gqlClient) {
|
|
13463
|
+
this.gqlClient = this.getGQLClient(apiKey);
|
|
13464
|
+
}
|
|
13465
|
+
const isConnected = await this.gqlClient.verifyApiConnection();
|
|
13466
|
+
if (!isConnected) {
|
|
13467
|
+
return {
|
|
13468
|
+
isAuthenticated: false,
|
|
13469
|
+
reason: "unknown",
|
|
13470
|
+
message: "Failed to connect to Mobb server"
|
|
13471
|
+
};
|
|
13472
|
+
}
|
|
13321
13473
|
try {
|
|
13322
|
-
if (!this.gqlClient) {
|
|
13323
|
-
this.gqlClient = this.getGQLClient(apiKey);
|
|
13324
|
-
}
|
|
13325
|
-
const isConnected = await this.gqlClient.verifyApiConnection();
|
|
13326
|
-
if (!isConnected) {
|
|
13327
|
-
return {
|
|
13328
|
-
isAuthenticated: false,
|
|
13329
|
-
message: "Failed to connect to Mobb server"
|
|
13330
|
-
};
|
|
13331
|
-
}
|
|
13332
13474
|
const userVerify = await this.gqlClient.validateUserToken();
|
|
13333
13475
|
if (!userVerify) {
|
|
13334
13476
|
return {
|
|
13335
13477
|
isAuthenticated: false,
|
|
13478
|
+
reason: "invalid",
|
|
13336
13479
|
message: "User token validation failed"
|
|
13337
13480
|
};
|
|
13338
13481
|
}
|
|
13339
13482
|
} catch (error) {
|
|
13340
13483
|
return {
|
|
13341
13484
|
isAuthenticated: false,
|
|
13485
|
+
reason: "unknown",
|
|
13342
13486
|
message: error instanceof Error ? error.message : "Unknown authentication error"
|
|
13343
13487
|
};
|
|
13344
13488
|
}
|
|
13345
|
-
return { isAuthenticated: true
|
|
13489
|
+
return { isAuthenticated: true };
|
|
13346
13490
|
}
|
|
13347
13491
|
/**
|
|
13348
13492
|
* Generates a login URL for manual authentication
|
|
13349
13493
|
*/
|
|
13350
|
-
async generateLoginUrl(loginContext) {
|
|
13494
|
+
async generateLoginUrl(loginPath, loginContext) {
|
|
13351
13495
|
try {
|
|
13352
13496
|
if (!this.gqlClient) {
|
|
13353
13497
|
this.gqlClient = this.getGQLClient();
|
|
@@ -13360,7 +13504,7 @@ var _AuthManager = class _AuthManager {
|
|
|
13360
13504
|
this.loginId = await this.gqlClient.createCliLogin({
|
|
13361
13505
|
publicKey: this.publicKey.export({ format: "pem", type: "pkcs1" }).toString()
|
|
13362
13506
|
});
|
|
13363
|
-
const webLoginUrl = `${this.resolvedWebAppUrl}/cli-login`;
|
|
13507
|
+
const webLoginUrl = `${this.resolvedWebAppUrl}${loginPath || "/cli-login"}`;
|
|
13364
13508
|
const browserUrl = loginContext ? buildLoginUrl(webLoginUrl, this.loginId, os3.hostname(), loginContext) : `${webLoginUrl}/${this.loginId}?hostname=${os3.hostname()}`;
|
|
13365
13509
|
this.currentBrowserUrl = browserUrl;
|
|
13366
13510
|
return browserUrl;
|
|
@@ -13370,22 +13514,32 @@ var _AuthManager = class _AuthManager {
|
|
|
13370
13514
|
}
|
|
13371
13515
|
}
|
|
13372
13516
|
/**
|
|
13373
|
-
* Retrieves and decrypts the API token after authentication
|
|
13517
|
+
* Retrieves and decrypts the API token after authentication.
|
|
13518
|
+
* Returns null if the token is not yet available or on transient errors.
|
|
13374
13519
|
*/
|
|
13375
13520
|
async getApiToken() {
|
|
13376
13521
|
if (!this.gqlClient || !this.loginId || !this.privateKey) {
|
|
13377
13522
|
return null;
|
|
13378
13523
|
}
|
|
13379
|
-
|
|
13380
|
-
|
|
13381
|
-
|
|
13382
|
-
|
|
13383
|
-
|
|
13384
|
-
|
|
13385
|
-
|
|
13386
|
-
|
|
13524
|
+
try {
|
|
13525
|
+
const encryptedApiToken = await this.gqlClient.getEncryptedApiToken({
|
|
13526
|
+
loginId: this.loginId
|
|
13527
|
+
});
|
|
13528
|
+
if (encryptedApiToken) {
|
|
13529
|
+
return crypto.privateDecrypt(
|
|
13530
|
+
this.privateKey,
|
|
13531
|
+
Buffer.from(encryptedApiToken, "base64")
|
|
13532
|
+
).toString("utf-8");
|
|
13533
|
+
}
|
|
13534
|
+
return null;
|
|
13535
|
+
} catch (error) {
|
|
13536
|
+
if (isTransientError(error)) {
|
|
13537
|
+
debug11("getApiToken: transient error, will retry");
|
|
13538
|
+
} else {
|
|
13539
|
+
debug11("getApiToken: unexpected error: %O", error);
|
|
13540
|
+
}
|
|
13541
|
+
return null;
|
|
13387
13542
|
}
|
|
13388
|
-
return null;
|
|
13389
13543
|
}
|
|
13390
13544
|
/**
|
|
13391
13545
|
* Returns true if a non-empty API token is stored in the configStore.
|
|
@@ -13429,109 +13583,11 @@ var _AuthManager = class _AuthManager {
|
|
|
13429
13583
|
};
|
|
13430
13584
|
/** Maximum time (ms) to wait for login authentication. Override in tests for faster failures. */
|
|
13431
13585
|
__publicField(_AuthManager, "loginMaxWait", LOGIN_MAX_WAIT);
|
|
13586
|
+
/** Browser cooldown: minimum ms between browser opens (0 = no cooldown) */
|
|
13587
|
+
__publicField(_AuthManager, "browserCooldownMs", 0);
|
|
13588
|
+
__publicField(_AuthManager, "lastBrowserOpenTime", 0);
|
|
13432
13589
|
var AuthManager = _AuthManager;
|
|
13433
13590
|
|
|
13434
|
-
// src/commands/handleMobbLogin.ts
|
|
13435
|
-
var debug11 = Debug10("mobbdev:commands");
|
|
13436
|
-
var LOGIN_MAX_WAIT2 = 10 * 60 * 1e3;
|
|
13437
|
-
var LOGIN_CHECK_DELAY2 = 5 * 1e3;
|
|
13438
|
-
var MOBB_LOGIN_REQUIRED_MSG = `\u{1F513} Login to Mobb is Required, you will be redirected to our login page, once the authorization is complete return to this prompt, ${chalk4.bgBlue(
|
|
13439
|
-
"press any key to continue"
|
|
13440
|
-
)};`;
|
|
13441
|
-
async function getAuthenticatedGQLClient({
|
|
13442
|
-
inputApiKey = "",
|
|
13443
|
-
isSkipPrompts = true,
|
|
13444
|
-
apiUrl,
|
|
13445
|
-
webAppUrl
|
|
13446
|
-
}) {
|
|
13447
|
-
debug11(
|
|
13448
|
-
"getAuthenticatedGQLClient called with: apiUrl=%s, webAppUrl=%s",
|
|
13449
|
-
apiUrl || "undefined",
|
|
13450
|
-
webAppUrl || "undefined"
|
|
13451
|
-
);
|
|
13452
|
-
const authManager = new AuthManager(webAppUrl, apiUrl);
|
|
13453
|
-
let gqlClient = authManager.getGQLClient(inputApiKey);
|
|
13454
|
-
gqlClient = await handleMobbLogin({
|
|
13455
|
-
inGqlClient: gqlClient,
|
|
13456
|
-
skipPrompts: isSkipPrompts,
|
|
13457
|
-
apiUrl,
|
|
13458
|
-
webAppUrl
|
|
13459
|
-
});
|
|
13460
|
-
return gqlClient;
|
|
13461
|
-
}
|
|
13462
|
-
async function handleMobbLogin({
|
|
13463
|
-
inGqlClient,
|
|
13464
|
-
apiKey,
|
|
13465
|
-
skipPrompts,
|
|
13466
|
-
apiUrl,
|
|
13467
|
-
webAppUrl,
|
|
13468
|
-
loginContext
|
|
13469
|
-
}) {
|
|
13470
|
-
debug11(
|
|
13471
|
-
"handleMobbLogin: resolved URLs - apiUrl=%s (from param: %s), webAppUrl=%s (from param: %s)",
|
|
13472
|
-
apiUrl || "fallback",
|
|
13473
|
-
apiUrl || "fallback",
|
|
13474
|
-
webAppUrl || "fallback",
|
|
13475
|
-
webAppUrl || "fallback"
|
|
13476
|
-
);
|
|
13477
|
-
const { createSpinner: createSpinner5 } = Spinner({ ci: skipPrompts });
|
|
13478
|
-
const authManager = new AuthManager(webAppUrl, apiUrl);
|
|
13479
|
-
authManager.setGQLClient(inGqlClient);
|
|
13480
|
-
try {
|
|
13481
|
-
const isAuthenticated = await authManager.isAuthenticated();
|
|
13482
|
-
if (isAuthenticated) {
|
|
13483
|
-
createSpinner5().start().success({
|
|
13484
|
-
text: `\u{1F513} Login to Mobb succeeded. Already authenticated`
|
|
13485
|
-
});
|
|
13486
|
-
return authManager.getGQLClient();
|
|
13487
|
-
}
|
|
13488
|
-
} catch (error) {
|
|
13489
|
-
debug11("Authentication check failed:", error);
|
|
13490
|
-
}
|
|
13491
|
-
if (apiKey) {
|
|
13492
|
-
createSpinner5().start().error({
|
|
13493
|
-
text: "\u{1F513} Login to Mobb failed: The provided API key does not match any configured API key on the system"
|
|
13494
|
-
});
|
|
13495
|
-
throw new CliError(
|
|
13496
|
-
"Login to Mobb failed: The provided API key does not match any configured API key on the system"
|
|
13497
|
-
);
|
|
13498
|
-
}
|
|
13499
|
-
const loginSpinner = createSpinner5().start();
|
|
13500
|
-
if (!skipPrompts) {
|
|
13501
|
-
loginSpinner.update({ text: MOBB_LOGIN_REQUIRED_MSG });
|
|
13502
|
-
await keypress();
|
|
13503
|
-
}
|
|
13504
|
-
loginSpinner.update({
|
|
13505
|
-
text: "\u{1F513} Waiting for Mobb login..."
|
|
13506
|
-
});
|
|
13507
|
-
try {
|
|
13508
|
-
const loginUrl = await authManager.generateLoginUrl(loginContext);
|
|
13509
|
-
if (!loginUrl) {
|
|
13510
|
-
loginSpinner.error({
|
|
13511
|
-
text: "Failed to generate login URL"
|
|
13512
|
-
});
|
|
13513
|
-
throw new CliError("Failed to generate login URL");
|
|
13514
|
-
}
|
|
13515
|
-
!skipPrompts && console.log(
|
|
13516
|
-
`If the page does not open automatically, kindly access it through ${loginUrl}.`
|
|
13517
|
-
);
|
|
13518
|
-
authManager.openUrlInBrowser();
|
|
13519
|
-
const authSuccess = await authManager.waitForAuthentication();
|
|
13520
|
-
if (!authSuccess) {
|
|
13521
|
-
loginSpinner.error({
|
|
13522
|
-
text: "Login timeout error"
|
|
13523
|
-
});
|
|
13524
|
-
throw new CliError("Login timeout error");
|
|
13525
|
-
}
|
|
13526
|
-
loginSpinner.success({
|
|
13527
|
-
text: `\u{1F513} Login to Mobb successful!`
|
|
13528
|
-
});
|
|
13529
|
-
return authManager.getGQLClient();
|
|
13530
|
-
} finally {
|
|
13531
|
-
authManager.cleanup();
|
|
13532
|
-
}
|
|
13533
|
-
}
|
|
13534
|
-
|
|
13535
13591
|
// src/features/analysis/add_fix_comments_for_pr/add_fix_comments_for_pr.ts
|
|
13536
13592
|
import Debug14 from "debug";
|
|
13537
13593
|
|
|
@@ -14490,8 +14546,8 @@ if (typeof __filename !== "undefined") {
|
|
|
14490
14546
|
}
|
|
14491
14547
|
var costumeRequire = createRequire(moduleUrl);
|
|
14492
14548
|
var getCheckmarxPath = () => {
|
|
14493
|
-
const
|
|
14494
|
-
const cxFileName =
|
|
14549
|
+
const os13 = type();
|
|
14550
|
+
const cxFileName = os13 === "Windows_NT" ? "cx.exe" : "cx";
|
|
14495
14551
|
try {
|
|
14496
14552
|
return costumeRequire.resolve(`.bin/${cxFileName}`);
|
|
14497
14553
|
} catch (e) {
|
|
@@ -15082,7 +15138,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
15082
15138
|
`If the page does not open automatically, kindly access it through ${scmAuthUrl2}.`
|
|
15083
15139
|
);
|
|
15084
15140
|
await open3(scmAuthUrl2);
|
|
15085
|
-
for (let i = 0; i <
|
|
15141
|
+
for (let i = 0; i < LOGIN_MAX_WAIT / LOGIN_CHECK_DELAY; i++) {
|
|
15086
15142
|
const userInfo2 = await gqlClient.getUserInfo();
|
|
15087
15143
|
if (!userInfo2) {
|
|
15088
15144
|
throw new CliError2("User info not found");
|
|
@@ -15101,7 +15157,7 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
15101
15157
|
return tokenInfo2.accessToken;
|
|
15102
15158
|
}
|
|
15103
15159
|
scmSpinner.spin();
|
|
15104
|
-
await sleep(
|
|
15160
|
+
await sleep(LOGIN_CHECK_DELAY);
|
|
15105
15161
|
}
|
|
15106
15162
|
scmSpinner.error({
|
|
15107
15163
|
text: `${scmName} login timeout error`
|
|
@@ -16429,9 +16485,7 @@ var logDebug = (message, data) => logger.log(message, "debug", data);
|
|
|
16429
16485
|
var log = logger.log.bind(logger);
|
|
16430
16486
|
|
|
16431
16487
|
// src/mcp/services/McpGQLClient.ts
|
|
16432
|
-
import
|
|
16433
|
-
import { ClientError as ClientError2, GraphQLClient as GraphQLClient2 } from "graphql-request";
|
|
16434
|
-
import { v4 as uuidv42 } from "uuid";
|
|
16488
|
+
import crypto2 from "crypto";
|
|
16435
16489
|
init_client_generates();
|
|
16436
16490
|
init_configs();
|
|
16437
16491
|
|
|
@@ -16564,197 +16618,37 @@ var GetLatestReportByRepoUrlResponseSchema = z34.object({
|
|
|
16564
16618
|
expiredReport: z34.array(ExpiredReportSchema)
|
|
16565
16619
|
});
|
|
16566
16620
|
|
|
16567
|
-
// src/mcp/services/McpAuthService.ts
|
|
16568
|
-
import crypto2 from "crypto";
|
|
16569
|
-
import os5 from "os";
|
|
16570
|
-
import open4 from "open";
|
|
16571
|
-
init_configs();
|
|
16572
|
-
var _McpAuthService = class _McpAuthService {
|
|
16573
|
-
constructor(client) {
|
|
16574
|
-
__publicField(this, "client");
|
|
16575
|
-
this.client = client;
|
|
16576
|
-
}
|
|
16577
|
-
/** Reset cooldown state. Used by tests to ensure isolation. */
|
|
16578
|
-
static resetCooldown() {
|
|
16579
|
-
_McpAuthService.lastBrowserOpenTime = 0;
|
|
16580
|
-
}
|
|
16581
|
-
/**
|
|
16582
|
-
* Opens a browser window for authentication
|
|
16583
|
-
* @param url URL to open in browser
|
|
16584
|
-
* @param isBackgoundCall Whether this is called from tools context
|
|
16585
|
-
*/
|
|
16586
|
-
async openBrowser(url, isBackgoundCall) {
|
|
16587
|
-
if (isBackgoundCall) {
|
|
16588
|
-
const now = Date.now();
|
|
16589
|
-
if (now - _McpAuthService.lastBrowserOpenTime < MCP_TOOLS_BROWSER_COOLDOWN_MS) {
|
|
16590
|
-
logDebug(`browser cooldown active, skipping open for ${url}`);
|
|
16591
|
-
return false;
|
|
16592
|
-
}
|
|
16593
|
-
}
|
|
16594
|
-
logDebug(`opening browser url ${url}`);
|
|
16595
|
-
await open4(url);
|
|
16596
|
-
_McpAuthService.lastBrowserOpenTime = Date.now();
|
|
16597
|
-
return true;
|
|
16598
|
-
}
|
|
16599
|
-
/**
|
|
16600
|
-
* Handles the complete authentication flow
|
|
16601
|
-
* @param isBackgoundCall Whether this is called from tools context
|
|
16602
|
-
* @param loginContext Context information about who triggered the login
|
|
16603
|
-
* @returns Authenticated API token
|
|
16604
|
-
*/
|
|
16605
|
-
async authenticate(isBackgoundCall = false, loginContext) {
|
|
16606
|
-
const { publicKey, privateKey } = crypto2.generateKeyPairSync("rsa", {
|
|
16607
|
-
modulusLength: 2048
|
|
16608
|
-
});
|
|
16609
|
-
logDebug("creating cli login");
|
|
16610
|
-
const loginId = await this.client.createCliLogin({
|
|
16611
|
-
publicKey: publicKey.export({ format: "pem", type: "pkcs1" }).toString()
|
|
16612
|
-
});
|
|
16613
|
-
if (!loginId) {
|
|
16614
|
-
throw new CliLoginError("Error: createCliLogin failed");
|
|
16615
|
-
}
|
|
16616
|
-
logDebug(`cli login created ${loginId}`);
|
|
16617
|
-
const webLoginUrl = `${WEB_APP_URL}/mvs-login`;
|
|
16618
|
-
const browserUrl = loginContext ? buildLoginUrl(webLoginUrl, loginId, os5.hostname(), loginContext) : `${webLoginUrl}/${loginId}?hostname=${os5.hostname()}`;
|
|
16619
|
-
const browserOpened = await this.openBrowser(browserUrl, isBackgoundCall);
|
|
16620
|
-
if (!browserOpened) {
|
|
16621
|
-
throw new AuthenticationError(
|
|
16622
|
-
"Authentication required but browser cooldown is active"
|
|
16623
|
-
);
|
|
16624
|
-
}
|
|
16625
|
-
logDebug(`waiting for login to complete`);
|
|
16626
|
-
let newApiToken = null;
|
|
16627
|
-
for (let i = 0; i < MCP_LOGIN_MAX_WAIT / MCP_LOGIN_CHECK_DELAY; i++) {
|
|
16628
|
-
const encryptedApiToken = await this.client.getEncryptedApiToken({
|
|
16629
|
-
loginId
|
|
16630
|
-
});
|
|
16631
|
-
if (encryptedApiToken) {
|
|
16632
|
-
logDebug("encrypted API token received");
|
|
16633
|
-
newApiToken = crypto2.privateDecrypt(privateKey, Buffer.from(encryptedApiToken, "base64")).toString("utf-8");
|
|
16634
|
-
logDebug("API token decrypted");
|
|
16635
|
-
break;
|
|
16636
|
-
}
|
|
16637
|
-
await sleep(MCP_LOGIN_CHECK_DELAY);
|
|
16638
|
-
}
|
|
16639
|
-
if (!newApiToken) {
|
|
16640
|
-
throw new FailedToGetApiTokenError(
|
|
16641
|
-
"Error: failed to get encrypted api token"
|
|
16642
|
-
);
|
|
16643
|
-
}
|
|
16644
|
-
const verifyClient = new McpGQLClient({
|
|
16645
|
-
apiKey: newApiToken,
|
|
16646
|
-
type: "apiKey"
|
|
16647
|
-
});
|
|
16648
|
-
const loginSuccess = await verifyClient.validateUserToken();
|
|
16649
|
-
if (!loginSuccess) {
|
|
16650
|
-
throw new AuthenticationError("Invalid API token");
|
|
16651
|
-
}
|
|
16652
|
-
return newApiToken;
|
|
16653
|
-
}
|
|
16654
|
-
};
|
|
16655
|
-
// Static so cooldown persists across McpAuthService instances
|
|
16656
|
-
__publicField(_McpAuthService, "lastBrowserOpenTime", 0);
|
|
16657
|
-
var McpAuthService = _McpAuthService;
|
|
16658
|
-
|
|
16659
16621
|
// src/mcp/services/McpGQLClient.ts
|
|
16660
|
-
|
|
16661
|
-
if (error instanceof ClientError2) {
|
|
16662
|
-
const gqlErrors = error.response?.errors;
|
|
16663
|
-
return gqlErrors?.some(
|
|
16664
|
-
(e) => e.extensions?.["code"] === "access-denied" || e.message?.includes("Authentication hook unauthorized")
|
|
16665
|
-
) ?? false;
|
|
16666
|
-
}
|
|
16667
|
-
return false;
|
|
16668
|
-
}
|
|
16669
|
-
function isNetworkError2(error) {
|
|
16670
|
-
const errorString = error?.toString() ?? "";
|
|
16671
|
-
return errorString.includes("FetchError") || errorString.includes("TypeError") || errorString.includes("ECONNREFUSED") || errorString.includes("ENOTFOUND") || errorString.includes("ETIMEDOUT") || errorString.includes("UND_ERR");
|
|
16672
|
-
}
|
|
16673
|
-
var McpGQLClient = class {
|
|
16622
|
+
var McpGQLClient = class extends GQLClient {
|
|
16674
16623
|
constructor(args) {
|
|
16675
|
-
|
|
16676
|
-
|
|
16677
|
-
|
|
16678
|
-
__publicField(this, "currentUser", null);
|
|
16679
|
-
__publicField(this, "apiUrl");
|
|
16680
|
-
this._auth = args;
|
|
16681
|
-
this.apiUrl = process.env["API_URL"] || DEFAULT_API_URL;
|
|
16682
|
-
logDebug(`[GraphQL] Creating graphql client with api url ${this.apiUrl}`, {
|
|
16683
|
-
args
|
|
16684
|
-
});
|
|
16685
|
-
this.client = new GraphQLClient2(this.apiUrl, {
|
|
16686
|
-
headers: args.type === "apiKey" ? { [MCP_API_KEY_HEADER_NAME]: args.apiKey || "" } : {
|
|
16687
|
-
Authorization: `Bearer ${args.token}`
|
|
16688
|
-
},
|
|
16689
|
-
fetch: fetchWithProxy,
|
|
16690
|
-
requestMiddleware: (request) => {
|
|
16691
|
-
const requestId = uuidv42();
|
|
16692
|
-
return {
|
|
16693
|
-
...request,
|
|
16694
|
-
headers: {
|
|
16695
|
-
...request.headers,
|
|
16696
|
-
"x-hasura-request-id": requestId
|
|
16697
|
-
}
|
|
16698
|
-
};
|
|
16699
|
-
}
|
|
16624
|
+
super({
|
|
16625
|
+
...args,
|
|
16626
|
+
apiUrl: process.env["API_URL"] || void 0
|
|
16700
16627
|
});
|
|
16701
|
-
this
|
|
16628
|
+
__publicField(this, "currentUser", null);
|
|
16702
16629
|
}
|
|
16703
16630
|
getErrorContext() {
|
|
16704
16631
|
return {
|
|
16705
|
-
endpoint: this.
|
|
16632
|
+
endpoint: this._apiUrl,
|
|
16706
16633
|
apiKey: this._auth.type === "apiKey" ? this._auth.apiKey : "",
|
|
16707
16634
|
headers: {
|
|
16708
|
-
|
|
16635
|
+
"x-mobb-key": this._auth.type === "apiKey" ? "[REDACTED]" : "undefined",
|
|
16709
16636
|
"x-hasura-request-id": "[DYNAMIC]"
|
|
16710
16637
|
}
|
|
16711
16638
|
};
|
|
16712
16639
|
}
|
|
16713
|
-
async
|
|
16714
|
-
|
|
16715
|
-
|
|
16716
|
-
|
|
16717
|
-
return await this.clientSdk.FinalizeAIBlameInferencesUpload(variables);
|
|
16718
|
-
}
|
|
16719
|
-
async isApiEndpointReachable() {
|
|
16720
|
-
try {
|
|
16721
|
-
logDebug("[GraphQL] Calling Me query for API connection verification");
|
|
16722
|
-
const result = await this.getUserInfo();
|
|
16723
|
-
logDebug("[GraphQL] Me query successful", { result });
|
|
16724
|
-
return true;
|
|
16725
|
-
} catch (e) {
|
|
16726
|
-
logDebug("[GraphQL] API connection verification failed", { error: e });
|
|
16727
|
-
if (isNetworkError2(e)) {
|
|
16728
|
-
logError("[GraphQL] API endpoint unreachable (network error)", {
|
|
16729
|
-
error: e
|
|
16730
|
-
});
|
|
16731
|
-
return false;
|
|
16732
|
-
}
|
|
16733
|
-
logDebug("[GraphQL] API endpoint is reachable (non-network error)");
|
|
16734
|
-
return true;
|
|
16735
|
-
}
|
|
16640
|
+
async getUserInfo() {
|
|
16641
|
+
const me = await super.getUserInfo();
|
|
16642
|
+
this.currentUser = me;
|
|
16643
|
+
return me;
|
|
16736
16644
|
}
|
|
16737
|
-
|
|
16738
|
-
|
|
16739
|
-
* @returns true if both API is reachable and user is authenticated
|
|
16740
|
-
*/
|
|
16741
|
-
async verifyApiConnection() {
|
|
16742
|
-
const isReachable = await this.isApiEndpointReachable();
|
|
16743
|
-
if (!isReachable) {
|
|
16744
|
-
return false;
|
|
16745
|
-
}
|
|
16746
|
-
try {
|
|
16747
|
-
await this.validateUserToken();
|
|
16748
|
-
return true;
|
|
16749
|
-
} catch (e) {
|
|
16750
|
-
logError("User token validation failed", { error: e });
|
|
16751
|
-
return false;
|
|
16752
|
-
}
|
|
16645
|
+
getCurrentUser() {
|
|
16646
|
+
return this.currentUser;
|
|
16753
16647
|
}
|
|
16754
16648
|
async uploadS3BucketInfo() {
|
|
16755
16649
|
try {
|
|
16756
16650
|
logDebug("[GraphQL] Calling uploadS3BucketInfo mutation");
|
|
16757
|
-
const result = await this.
|
|
16651
|
+
const result = await this._clientSdk.uploadS3BucketInfo({
|
|
16758
16652
|
fileName: "report.json"
|
|
16759
16653
|
});
|
|
16760
16654
|
logDebug("[GraphQL] uploadS3BucketInfo successful", { result });
|
|
@@ -16770,7 +16664,7 @@ var McpGQLClient = class {
|
|
|
16770
16664
|
async getAnalysis(analysisId) {
|
|
16771
16665
|
try {
|
|
16772
16666
|
logDebug("[GraphQL] Calling getAnalysis query", { analysisId });
|
|
16773
|
-
const res = await this.
|
|
16667
|
+
const res = await this._clientSdk.getAnalysis({
|
|
16774
16668
|
analysisId
|
|
16775
16669
|
});
|
|
16776
16670
|
logDebug("[GraphQL] getAnalysis successful", { result: res });
|
|
@@ -16792,7 +16686,7 @@ var McpGQLClient = class {
|
|
|
16792
16686
|
logDebug("[GraphQL] Calling SubmitVulnerabilityReport mutation", {
|
|
16793
16687
|
variables
|
|
16794
16688
|
});
|
|
16795
|
-
const result = await this.
|
|
16689
|
+
const result = await this._clientSdk.SubmitVulnerabilityReport(variables);
|
|
16796
16690
|
logDebug("[GraphQL] SubmitVulnerabilityReport successful", { result });
|
|
16797
16691
|
return result;
|
|
16798
16692
|
} catch (e) {
|
|
@@ -16871,15 +16765,15 @@ var McpGQLClient = class {
|
|
|
16871
16765
|
this._auth.type === "apiKey" ? {
|
|
16872
16766
|
apiKey: this._auth.apiKey,
|
|
16873
16767
|
type: "apiKey",
|
|
16874
|
-
url: httpToWsUrl(this.
|
|
16768
|
+
url: httpToWsUrl(this._apiUrl),
|
|
16875
16769
|
timeoutInMs: params.timeoutInMs,
|
|
16876
|
-
proxyAgent: getProxyAgent(this.
|
|
16770
|
+
proxyAgent: getProxyAgent(this._apiUrl)
|
|
16877
16771
|
} : {
|
|
16878
16772
|
token: this._auth.token,
|
|
16879
16773
|
type: "token",
|
|
16880
|
-
url: httpToWsUrl(this.
|
|
16774
|
+
url: httpToWsUrl(this._apiUrl),
|
|
16881
16775
|
timeoutInMs: params.timeoutInMs,
|
|
16882
|
-
proxyAgent: getProxyAgent(this.
|
|
16776
|
+
proxyAgent: getProxyAgent(this._apiUrl)
|
|
16883
16777
|
}
|
|
16884
16778
|
);
|
|
16885
16779
|
}
|
|
@@ -16903,12 +16797,12 @@ var McpGQLClient = class {
|
|
|
16903
16797
|
if (!userEmail) {
|
|
16904
16798
|
throw new Error("User email not found");
|
|
16905
16799
|
}
|
|
16906
|
-
const shortEmailHash =
|
|
16800
|
+
const shortEmailHash = crypto2.createHash("sha256").update(userEmail).digest("hex").slice(0, 8).toUpperCase();
|
|
16907
16801
|
const projectName = `MCP Scans ${shortEmailHash}`;
|
|
16908
16802
|
logDebug("[GraphQL] Calling getLastOrgAndNamedProject query", {
|
|
16909
16803
|
projectName
|
|
16910
16804
|
});
|
|
16911
|
-
const orgAndProjectRes = await this.
|
|
16805
|
+
const orgAndProjectRes = await this._clientSdk.getLastOrgAndNamedProject({
|
|
16912
16806
|
email: userEmail,
|
|
16913
16807
|
projectName
|
|
16914
16808
|
});
|
|
@@ -16934,7 +16828,7 @@ var McpGQLClient = class {
|
|
|
16934
16828
|
projectName
|
|
16935
16829
|
});
|
|
16936
16830
|
try {
|
|
16937
|
-
const createdProject = await this.
|
|
16831
|
+
const createdProject = await this._clientSdk.CreateProject({
|
|
16938
16832
|
organizationId: organization.id,
|
|
16939
16833
|
projectName
|
|
16940
16834
|
});
|
|
@@ -16956,7 +16850,7 @@ var McpGQLClient = class {
|
|
|
16956
16850
|
error: errorMessage
|
|
16957
16851
|
}
|
|
16958
16852
|
);
|
|
16959
|
-
const retryOrgAndProjectRes = await this.
|
|
16853
|
+
const retryOrgAndProjectRes = await this._clientSdk.getLastOrgAndNamedProject({
|
|
16960
16854
|
email: userEmail,
|
|
16961
16855
|
projectName
|
|
16962
16856
|
});
|
|
@@ -16990,71 +16884,6 @@ var McpGQLClient = class {
|
|
|
16990
16884
|
throw e;
|
|
16991
16885
|
}
|
|
16992
16886
|
}
|
|
16993
|
-
async getUserInfo() {
|
|
16994
|
-
const { me } = await this.clientSdk.Me();
|
|
16995
|
-
this.currentUser = me;
|
|
16996
|
-
return me;
|
|
16997
|
-
}
|
|
16998
|
-
getCurrentUser() {
|
|
16999
|
-
return this.currentUser;
|
|
17000
|
-
}
|
|
17001
|
-
async validateUserToken() {
|
|
17002
|
-
logDebug("[GraphQL] Validating user token");
|
|
17003
|
-
try {
|
|
17004
|
-
await this.clientSdk.CreateCommunityUser();
|
|
17005
|
-
const info = await this.getUserInfo();
|
|
17006
|
-
if (!info) {
|
|
17007
|
-
logDebug("[GraphQL] User token is invalid (no user info returned)");
|
|
17008
|
-
return false;
|
|
17009
|
-
}
|
|
17010
|
-
logDebug("[GraphQL] User token validated successfully");
|
|
17011
|
-
return info.email || true;
|
|
17012
|
-
} catch (e) {
|
|
17013
|
-
if (isAuthError2(e)) {
|
|
17014
|
-
logDebug("[GraphQL] User token is invalid (auth error from server)");
|
|
17015
|
-
return false;
|
|
17016
|
-
}
|
|
17017
|
-
if (isNetworkError2(e)) {
|
|
17018
|
-
logError("[GraphQL] Token validation failed due to network error", {
|
|
17019
|
-
error: e
|
|
17020
|
-
});
|
|
17021
|
-
throw e;
|
|
17022
|
-
}
|
|
17023
|
-
logError("[GraphQL] Token validation failed with unexpected error", {
|
|
17024
|
-
error: e
|
|
17025
|
-
});
|
|
17026
|
-
throw e;
|
|
17027
|
-
}
|
|
17028
|
-
}
|
|
17029
|
-
async createCliLogin(variables) {
|
|
17030
|
-
try {
|
|
17031
|
-
const res = await this.clientSdk.CreateCliLogin(variables, {
|
|
17032
|
-
// We may have outdated API key in the config storage. Avoid using it for the login request.
|
|
17033
|
-
[MCP_API_KEY_HEADER_NAME]: ""
|
|
17034
|
-
});
|
|
17035
|
-
const loginId = res.insert_cli_login_one?.id || "";
|
|
17036
|
-
if (!loginId) {
|
|
17037
|
-
logError("[GraphQL] Create cli login failed - no login ID returned");
|
|
17038
|
-
return "";
|
|
17039
|
-
}
|
|
17040
|
-
return loginId;
|
|
17041
|
-
} catch (e) {
|
|
17042
|
-
logError("[GraphQL] Create cli login failed", { error: e });
|
|
17043
|
-
return "";
|
|
17044
|
-
}
|
|
17045
|
-
}
|
|
17046
|
-
async getEncryptedApiToken(variables) {
|
|
17047
|
-
try {
|
|
17048
|
-
const res = await this.clientSdk.GetEncryptedApiToken(variables, {
|
|
17049
|
-
// We may have outdated API key in the config storage. Avoid using it for the login request.
|
|
17050
|
-
[MCP_API_KEY_HEADER_NAME]: ""
|
|
17051
|
-
});
|
|
17052
|
-
return res?.cli_login_by_pk?.encryptedApiToken || null;
|
|
17053
|
-
} catch (e) {
|
|
17054
|
-
logError("[GraphQL] Get encrypted api token failed", { error: e });
|
|
17055
|
-
return null;
|
|
17056
|
-
}
|
|
17057
|
-
}
|
|
17058
16887
|
generateFixUrl({
|
|
17059
16888
|
fixId,
|
|
17060
16889
|
organizationId,
|
|
@@ -17064,7 +16893,7 @@ var McpGQLClient = class {
|
|
|
17064
16893
|
if (!organizationId || !projectId || !reportId) {
|
|
17065
16894
|
return void 0;
|
|
17066
16895
|
}
|
|
17067
|
-
const appBaseUrl = this.
|
|
16896
|
+
const appBaseUrl = this._apiUrl.replace("/v1/graphql", "").replace("api.", "");
|
|
17068
16897
|
return `${appBaseUrl}/organization/${organizationId}/project/${projectId}/report/${reportId}/fix/${fixId}`;
|
|
17069
16898
|
}
|
|
17070
16899
|
mergeUserAndSystemFixes({
|
|
@@ -17111,7 +16940,7 @@ var McpGQLClient = class {
|
|
|
17111
16940
|
}
|
|
17112
16941
|
async updateFixesDownloadStatus(fixIds) {
|
|
17113
16942
|
if (fixIds.length > 0) {
|
|
17114
|
-
const resUpdate = await this.
|
|
16943
|
+
const resUpdate = await this._clientSdk.updateDownloadedFixData({
|
|
17115
16944
|
fixIds,
|
|
17116
16945
|
source: "MCP" /* Mcp */
|
|
17117
16946
|
});
|
|
@@ -17125,7 +16954,7 @@ var McpGQLClient = class {
|
|
|
17125
16954
|
}
|
|
17126
16955
|
async updateAutoAppliedFixesStatus(fixIds) {
|
|
17127
16956
|
if (fixIds.length > 0) {
|
|
17128
|
-
const resUpdate = await this.
|
|
16957
|
+
const resUpdate = await this._clientSdk.updateDownloadedFixData({
|
|
17129
16958
|
fixIds,
|
|
17130
16959
|
source: "AUTO_MVS" /* AutoMvs */
|
|
17131
16960
|
});
|
|
@@ -17156,7 +16985,7 @@ var McpGQLClient = class {
|
|
|
17156
16985
|
logDebug("[GraphQL] Calling GetUserMvsAutoFix query", {
|
|
17157
16986
|
userEmail: userInfo2.email
|
|
17158
16987
|
});
|
|
17159
|
-
const result = await this.
|
|
16988
|
+
const result = await this._clientSdk.GetUserMvsAutoFix({
|
|
17160
16989
|
userEmail: userInfo2.email
|
|
17161
16990
|
});
|
|
17162
16991
|
logDebug("[GraphQL] GetUserMvsAutoFix successful", { result });
|
|
@@ -17199,7 +17028,7 @@ var McpGQLClient = class {
|
|
|
17199
17028
|
codeNodes: { path: { _in: fileFilter } }
|
|
17200
17029
|
};
|
|
17201
17030
|
}
|
|
17202
|
-
const resp = await this.
|
|
17031
|
+
const resp = await this._clientSdk.GetLatestReportByRepoUrl({
|
|
17203
17032
|
repoUrl,
|
|
17204
17033
|
limit,
|
|
17205
17034
|
offset,
|
|
@@ -17272,7 +17101,7 @@ var McpGQLClient = class {
|
|
|
17272
17101
|
error: err
|
|
17273
17102
|
});
|
|
17274
17103
|
}
|
|
17275
|
-
const res = await this.
|
|
17104
|
+
const res = await this._clientSdk.GetReportFixes({
|
|
17276
17105
|
reportId,
|
|
17277
17106
|
limit,
|
|
17278
17107
|
offset,
|
|
@@ -17317,45 +17146,65 @@ async function createAuthenticatedMcpGQLClient({
|
|
|
17317
17146
|
isBackgroundCall = false,
|
|
17318
17147
|
loginContext
|
|
17319
17148
|
} = {}) {
|
|
17149
|
+
if (isBackgroundCall) {
|
|
17150
|
+
AuthManager.setBrowserCooldown(MCP_TOOLS_BROWSER_COOLDOWN_MS);
|
|
17151
|
+
}
|
|
17320
17152
|
logDebug("[GraphQL] Getting config", {
|
|
17321
17153
|
apiToken: configStore.get("apiToken")
|
|
17322
17154
|
});
|
|
17323
|
-
const
|
|
17324
|
-
|
|
17325
|
-
|
|
17326
|
-
|
|
17327
|
-
});
|
|
17328
|
-
|
|
17329
|
-
|
|
17330
|
-
if (
|
|
17331
|
-
|
|
17155
|
+
const apiKey = process.env["MOBB_API_KEY"] || process.env["API_KEY"] || // fallback for backward compatibility
|
|
17156
|
+
configStore.get("apiToken") || "";
|
|
17157
|
+
const resolvedApiUrl = process.env["API_URL"] || void 0;
|
|
17158
|
+
const authManager = new AuthManager(void 0, resolvedApiUrl);
|
|
17159
|
+
const initialClient = new McpGQLClient({ apiKey, type: "apiKey" });
|
|
17160
|
+
authManager.setGQLClient(initialClient);
|
|
17161
|
+
const authResult = await authManager.checkAuthentication();
|
|
17162
|
+
if (authResult.isAuthenticated) {
|
|
17163
|
+
return initialClient;
|
|
17332
17164
|
}
|
|
17333
|
-
|
|
17334
|
-
|
|
17335
|
-
|
|
17336
|
-
userVerify = await initialClient.validateUserToken();
|
|
17337
|
-
} catch (e) {
|
|
17338
|
-
logError("[GraphQL] Token validation failed due to transient error", {
|
|
17339
|
-
error: e
|
|
17165
|
+
if (authResult.reason === "unknown") {
|
|
17166
|
+
logError("[GraphQL] Auth check failed with transient error", {
|
|
17167
|
+
message: authResult.message
|
|
17340
17168
|
});
|
|
17341
|
-
throw
|
|
17342
|
-
|
|
17343
|
-
|
|
17344
|
-
return initialClient;
|
|
17169
|
+
throw new ApiConnectionError(
|
|
17170
|
+
`Cannot verify authentication: ${authResult.message}`
|
|
17171
|
+
);
|
|
17345
17172
|
}
|
|
17346
|
-
const
|
|
17347
|
-
|
|
17348
|
-
isBackgroundCall,
|
|
17173
|
+
const loginUrl = await authManager.generateLoginUrl(
|
|
17174
|
+
"/mvs-login",
|
|
17349
17175
|
loginContext
|
|
17350
17176
|
);
|
|
17177
|
+
if (!loginUrl) {
|
|
17178
|
+
throw new AuthenticationError("Failed to generate login URL");
|
|
17179
|
+
}
|
|
17180
|
+
const opened = authManager.openUrlInBrowser();
|
|
17181
|
+
if (!opened) {
|
|
17182
|
+
throw new AuthenticationError(
|
|
17183
|
+
"Authentication required but browser cooldown is active"
|
|
17184
|
+
);
|
|
17185
|
+
}
|
|
17186
|
+
const newApiToken = await authManager.waitForApiToken();
|
|
17187
|
+
if (!newApiToken) {
|
|
17188
|
+
throw new FailedToGetApiTokenError(
|
|
17189
|
+
`Login timeout: authentication not completed within ${AuthManager.loginMaxWait / 1e3 / 60} minutes`
|
|
17190
|
+
);
|
|
17191
|
+
}
|
|
17192
|
+
const authenticatedClient = new McpGQLClient({
|
|
17193
|
+
apiKey: newApiToken,
|
|
17194
|
+
type: "apiKey"
|
|
17195
|
+
});
|
|
17196
|
+
const loginSuccess = await authenticatedClient.validateUserToken();
|
|
17197
|
+
if (!loginSuccess) {
|
|
17198
|
+
throw new AuthenticationError("Login failed: token validation failed");
|
|
17199
|
+
}
|
|
17351
17200
|
configStore.set("apiToken", newApiToken);
|
|
17352
|
-
return
|
|
17201
|
+
return authenticatedClient;
|
|
17353
17202
|
}
|
|
17354
17203
|
|
|
17355
17204
|
// src/mcp/services/McpUsageService/host.ts
|
|
17356
17205
|
import { execSync as execSync2 } from "child_process";
|
|
17357
17206
|
import fs13 from "fs";
|
|
17358
|
-
import
|
|
17207
|
+
import os5 from "os";
|
|
17359
17208
|
import path14 from "path";
|
|
17360
17209
|
var IDEs = ["cursor", "windsurf", "webstorm", "vscode", "claude"];
|
|
17361
17210
|
var runCommand = (cmd) => {
|
|
@@ -17370,7 +17219,7 @@ var gitInfo = {
|
|
|
17370
17219
|
email: runCommand("git config user.email")
|
|
17371
17220
|
};
|
|
17372
17221
|
var getClaudeWorkspacePaths = () => {
|
|
17373
|
-
const home =
|
|
17222
|
+
const home = os5.homedir();
|
|
17374
17223
|
const claudeIdePath = path14.join(home, ".claude", "ide");
|
|
17375
17224
|
const workspacePaths = [];
|
|
17376
17225
|
if (!fs13.existsSync(claudeIdePath)) {
|
|
@@ -17399,7 +17248,7 @@ var getClaudeWorkspacePaths = () => {
|
|
|
17399
17248
|
return workspacePaths;
|
|
17400
17249
|
};
|
|
17401
17250
|
var getMCPConfigPaths = (hostName) => {
|
|
17402
|
-
const home =
|
|
17251
|
+
const home = os5.homedir();
|
|
17403
17252
|
const currentDir = process.env["WORKSPACE_FOLDER_PATHS"] || process.env["PWD"] || process.cwd();
|
|
17404
17253
|
switch (hostName.toLowerCase()) {
|
|
17405
17254
|
case "cursor":
|
|
@@ -17489,7 +17338,7 @@ var readMCPConfig = (hostName) => {
|
|
|
17489
17338
|
};
|
|
17490
17339
|
var getRunningProcesses = () => {
|
|
17491
17340
|
try {
|
|
17492
|
-
return
|
|
17341
|
+
return os5.platform() === "win32" ? execSync2("tasklist", { encoding: "utf8" }) : execSync2("ps aux", { encoding: "utf8" });
|
|
17493
17342
|
} catch {
|
|
17494
17343
|
return "";
|
|
17495
17344
|
}
|
|
@@ -17564,7 +17413,7 @@ var versionCommands = {
|
|
|
17564
17413
|
}
|
|
17565
17414
|
};
|
|
17566
17415
|
var getProcessInfo = (pid) => {
|
|
17567
|
-
const platform2 =
|
|
17416
|
+
const platform2 = os5.platform();
|
|
17568
17417
|
try {
|
|
17569
17418
|
if (platform2 === "linux" || platform2 === "darwin") {
|
|
17570
17419
|
const output = execSync2(`ps -o pid=,ppid=,comm= -p ${pid}`, {
|
|
@@ -17683,7 +17532,7 @@ var getHostInfo = (additionalMcpList) => {
|
|
|
17683
17532
|
const config2 = allConfigs[ide] || null;
|
|
17684
17533
|
const ideName = ide.charAt(0).toUpperCase() + ide.slice(1) || "Unknown";
|
|
17685
17534
|
let ideVersion = "Unknown";
|
|
17686
|
-
const platform2 =
|
|
17535
|
+
const platform2 = os5.platform();
|
|
17687
17536
|
const cmds = versionCommands[ideName]?.[platform2] ?? [];
|
|
17688
17537
|
for (const cmd of cmds) {
|
|
17689
17538
|
try {
|
|
@@ -17716,14 +17565,14 @@ var getHostInfo = (additionalMcpList) => {
|
|
|
17716
17565
|
|
|
17717
17566
|
// src/mcp/services/McpUsageService/McpUsageService.ts
|
|
17718
17567
|
import fetch5 from "node-fetch";
|
|
17719
|
-
import
|
|
17720
|
-
import { v4 as
|
|
17568
|
+
import os7 from "os";
|
|
17569
|
+
import { v4 as uuidv42, v5 as uuidv5 } from "uuid";
|
|
17721
17570
|
init_configs();
|
|
17722
17571
|
|
|
17723
17572
|
// src/mcp/services/McpUsageService/system.ts
|
|
17724
17573
|
init_configs();
|
|
17725
17574
|
import fs14 from "fs";
|
|
17726
|
-
import
|
|
17575
|
+
import os6 from "os";
|
|
17727
17576
|
import path15 from "path";
|
|
17728
17577
|
var MAX_DEPTH = 2;
|
|
17729
17578
|
var patterns = ["mcp", "claude"];
|
|
@@ -17758,8 +17607,8 @@ var searchDir = async (dir, depth = 0) => {
|
|
|
17758
17607
|
};
|
|
17759
17608
|
var findSystemMCPConfigs = async () => {
|
|
17760
17609
|
try {
|
|
17761
|
-
const home =
|
|
17762
|
-
const platform2 =
|
|
17610
|
+
const home = os6.homedir();
|
|
17611
|
+
const platform2 = os6.platform();
|
|
17763
17612
|
const knownDirs = platform2 === "win32" ? [
|
|
17764
17613
|
path15.join(home, ".cursor"),
|
|
17765
17614
|
path15.join(home, "Documents"),
|
|
@@ -17831,7 +17680,7 @@ var McpUsageService = class {
|
|
|
17831
17680
|
generateHostId() {
|
|
17832
17681
|
const stored = configStore.get(this.configKey);
|
|
17833
17682
|
if (stored?.mcpHostId) return stored.mcpHostId;
|
|
17834
|
-
const interfaces =
|
|
17683
|
+
const interfaces = os7.networkInterfaces();
|
|
17835
17684
|
const macs = [];
|
|
17836
17685
|
for (const iface of Object.values(interfaces)) {
|
|
17837
17686
|
if (!iface) continue;
|
|
@@ -17839,7 +17688,7 @@ var McpUsageService = class {
|
|
|
17839
17688
|
if (net.mac && net.mac !== "00:00:00:00:00:00") macs.push(net.mac);
|
|
17840
17689
|
}
|
|
17841
17690
|
}
|
|
17842
|
-
const macString = macs.length ? macs.sort().join(",") : `${
|
|
17691
|
+
const macString = macs.length ? macs.sort().join(",") : `${os7.hostname()}-${uuidv42()}`;
|
|
17843
17692
|
const hostId = uuidv5(macString, uuidv5.DNS);
|
|
17844
17693
|
logDebug("[UsageService] Generated new host ID", { hostId });
|
|
17845
17694
|
return hostId;
|
|
@@ -17862,7 +17711,7 @@ var McpUsageService = class {
|
|
|
17862
17711
|
mcpHostId,
|
|
17863
17712
|
organizationId,
|
|
17864
17713
|
mcpVersion: packageJson.version,
|
|
17865
|
-
mcpOsName:
|
|
17714
|
+
mcpOsName: os7.platform(),
|
|
17866
17715
|
mcps: JSON.stringify(mcps),
|
|
17867
17716
|
status,
|
|
17868
17717
|
userName: user.name,
|
|
@@ -20183,7 +20032,7 @@ For a complete security audit workflow, use the \`full-security-audit\` prompt.
|
|
|
20183
20032
|
|
|
20184
20033
|
// src/mcp/services/McpDetectionService/CursorMcpDetectionService.ts
|
|
20185
20034
|
import * as fs17 from "fs";
|
|
20186
|
-
import * as
|
|
20035
|
+
import * as os9 from "os";
|
|
20187
20036
|
import * as path17 from "path";
|
|
20188
20037
|
|
|
20189
20038
|
// src/mcp/services/McpDetectionService/BaseMcpDetectionService.ts
|
|
@@ -20194,11 +20043,11 @@ import * as path16 from "path";
|
|
|
20194
20043
|
|
|
20195
20044
|
// src/mcp/services/McpDetectionService/McpDetectionServiceUtils.ts
|
|
20196
20045
|
import * as fs15 from "fs";
|
|
20197
|
-
import * as
|
|
20046
|
+
import * as os8 from "os";
|
|
20198
20047
|
|
|
20199
20048
|
// src/mcp/services/McpDetectionService/VscodeMcpDetectionService.ts
|
|
20200
20049
|
import * as fs18 from "fs";
|
|
20201
|
-
import * as
|
|
20050
|
+
import * as os10 from "os";
|
|
20202
20051
|
import * as path18 from "path";
|
|
20203
20052
|
|
|
20204
20053
|
// src/mcp/tools/checkForNewAvailableFixes/CheckForNewAvailableFixesTool.ts
|
|
@@ -24643,18 +24492,18 @@ async function getGrpcClient(port, csrf3) {
|
|
|
24643
24492
|
|
|
24644
24493
|
// src/features/codeium_intellij/parse_intellij_logs.ts
|
|
24645
24494
|
import fs25 from "fs";
|
|
24646
|
-
import
|
|
24495
|
+
import os11 from "os";
|
|
24647
24496
|
import path24 from "path";
|
|
24648
24497
|
function getLogsDir() {
|
|
24649
24498
|
if (process.platform === "darwin") {
|
|
24650
|
-
return path24.join(
|
|
24499
|
+
return path24.join(os11.homedir(), "Library/Logs/JetBrains");
|
|
24651
24500
|
} else if (process.platform === "win32") {
|
|
24652
24501
|
return path24.join(
|
|
24653
|
-
process.env["LOCALAPPDATA"] || path24.join(
|
|
24502
|
+
process.env["LOCALAPPDATA"] || path24.join(os11.homedir(), "AppData/Local"),
|
|
24654
24503
|
"JetBrains"
|
|
24655
24504
|
);
|
|
24656
24505
|
} else {
|
|
24657
|
-
return path24.join(
|
|
24506
|
+
return path24.join(os11.homedir(), ".cache/JetBrains");
|
|
24658
24507
|
}
|
|
24659
24508
|
}
|
|
24660
24509
|
function parseIdeLogDir(ideLogDir) {
|
|
@@ -24877,11 +24726,11 @@ function processChatStepCodeAction(step) {
|
|
|
24877
24726
|
|
|
24878
24727
|
// src/features/codeium_intellij/install_hook.ts
|
|
24879
24728
|
import fsPromises6 from "fs/promises";
|
|
24880
|
-
import
|
|
24729
|
+
import os12 from "os";
|
|
24881
24730
|
import path25 from "path";
|
|
24882
24731
|
import chalk14 from "chalk";
|
|
24883
24732
|
function getCodeiumHooksPath() {
|
|
24884
|
-
return path25.join(
|
|
24733
|
+
return path25.join(os12.homedir(), ".codeium", "hooks.json");
|
|
24885
24734
|
}
|
|
24886
24735
|
async function readCodeiumHooks() {
|
|
24887
24736
|
const hooksPath = getCodeiumHooksPath();
|