mobbdev 1.1.26 → 1.1.28
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.
|
@@ -16,6 +16,10 @@ type SanitizationCounts = {
|
|
|
16
16
|
};
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
+
type Logger = {
|
|
20
|
+
info: (msg: string, data?: unknown) => void;
|
|
21
|
+
error: (msg: string, data?: unknown) => void;
|
|
22
|
+
};
|
|
19
23
|
declare const PromptItemZ: z.ZodObject<{
|
|
20
24
|
type: z.ZodEnum<["USER_PROMPT", "AI_RESPONSE", "TOOL_EXECUTION", "AI_THINKING"]>;
|
|
21
25
|
attachedFiles: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
@@ -210,7 +214,17 @@ declare function uploadAiBlameHandlerFromExtension(args: {
|
|
|
210
214
|
responseTime: string;
|
|
211
215
|
blameType?: AiBlameInferenceType;
|
|
212
216
|
sessionId?: string;
|
|
217
|
+
apiUrl?: string;
|
|
218
|
+
webAppUrl?: string;
|
|
213
219
|
}): Promise<UploadAiBlameResult>;
|
|
214
|
-
|
|
220
|
+
type UploadAiBlameHandlerOptions = {
|
|
221
|
+
args: UploadAiBlameOptions;
|
|
222
|
+
exitOnError?: boolean;
|
|
223
|
+
apiUrl?: string;
|
|
224
|
+
webAppUrl?: string;
|
|
225
|
+
logger?: Logger;
|
|
226
|
+
};
|
|
227
|
+
declare function uploadAiBlameHandler(options: UploadAiBlameHandlerOptions): Promise<void>;
|
|
228
|
+
declare function uploadAiBlameCommandHandler(args: UploadAiBlameOptions): Promise<void>;
|
|
215
229
|
|
|
216
|
-
export { type PromptItem, type PromptItemArray, type UploadAiBlameOptions, type UploadAiBlameResult, uploadAiBlameBuilder, uploadAiBlameHandler, uploadAiBlameHandlerFromExtension };
|
|
230
|
+
export { type PromptItem, type PromptItemArray, type UploadAiBlameOptions, type UploadAiBlameResult, uploadAiBlameBuilder, uploadAiBlameCommandHandler, uploadAiBlameHandler, uploadAiBlameHandlerFromExtension };
|
|
@@ -4734,6 +4734,11 @@ var GQLClient = class {
|
|
|
4734
4734
|
debug6(`init with ${args}`);
|
|
4735
4735
|
this._auth = args;
|
|
4736
4736
|
this._apiUrl = args.apiUrl || API_URL;
|
|
4737
|
+
debug6(
|
|
4738
|
+
"GQLClient constructor: resolved apiUrl=%s (from param: %s)",
|
|
4739
|
+
this._apiUrl,
|
|
4740
|
+
args.apiUrl || "fallback to API_URL constant"
|
|
4741
|
+
);
|
|
4737
4742
|
this._client = new GraphQLClient(this._apiUrl, {
|
|
4738
4743
|
headers: args.type === "apiKey" ? { [API_KEY_HEADER_NAME]: args.apiKey || "" } : {
|
|
4739
4744
|
Authorization: `Bearer ${args.token}`
|
|
@@ -5100,6 +5105,18 @@ var GQLClient = class {
|
|
|
5100
5105
|
}
|
|
5101
5106
|
};
|
|
5102
5107
|
|
|
5108
|
+
// src/mcp/services/types.ts
|
|
5109
|
+
function buildLoginUrl(baseUrl, loginId, hostname2, context) {
|
|
5110
|
+
const url = new URL(`${baseUrl}/${loginId}`);
|
|
5111
|
+
url.searchParams.set("hostname", hostname2);
|
|
5112
|
+
url.searchParams.set("trigger", context.trigger);
|
|
5113
|
+
url.searchParams.set("source", context.source);
|
|
5114
|
+
if (context.ide) {
|
|
5115
|
+
url.searchParams.set("ide", context.ide);
|
|
5116
|
+
}
|
|
5117
|
+
return url.toString();
|
|
5118
|
+
}
|
|
5119
|
+
|
|
5103
5120
|
// src/utils/ConfigStoreService.ts
|
|
5104
5121
|
import Configstore from "configstore";
|
|
5105
5122
|
function createConfigStore(defaultValues = { apiToken: "" }) {
|
|
@@ -5132,6 +5149,11 @@ async function getAuthenticatedGQLClient({
|
|
|
5132
5149
|
apiUrl,
|
|
5133
5150
|
webAppUrl
|
|
5134
5151
|
}) {
|
|
5152
|
+
debug7(
|
|
5153
|
+
"getAuthenticatedGQLClient called with: apiUrl=%s, webAppUrl=%s",
|
|
5154
|
+
apiUrl || "undefined",
|
|
5155
|
+
webAppUrl || "undefined"
|
|
5156
|
+
);
|
|
5135
5157
|
let gqlClient = new GQLClient({
|
|
5136
5158
|
apiKey: inputApiKey || configStore.get("apiToken") || "",
|
|
5137
5159
|
type: "apiKey",
|
|
@@ -5150,10 +5172,18 @@ async function handleMobbLogin({
|
|
|
5150
5172
|
apiKey,
|
|
5151
5173
|
skipPrompts,
|
|
5152
5174
|
apiUrl,
|
|
5153
|
-
webAppUrl
|
|
5175
|
+
webAppUrl,
|
|
5176
|
+
loginContext
|
|
5154
5177
|
}) {
|
|
5155
5178
|
const resolvedWebAppUrl = webAppUrl || WEB_APP_URL;
|
|
5156
5179
|
const resolvedApiUrl = apiUrl || API_URL;
|
|
5180
|
+
debug7(
|
|
5181
|
+
"handleMobbLogin: resolved URLs - apiUrl=%s (from param: %s), webAppUrl=%s (from param: %s)",
|
|
5182
|
+
resolvedApiUrl,
|
|
5183
|
+
apiUrl || "fallback",
|
|
5184
|
+
resolvedWebAppUrl,
|
|
5185
|
+
webAppUrl || "fallback"
|
|
5186
|
+
);
|
|
5157
5187
|
const { createSpinner } = Spinner({ ci: skipPrompts });
|
|
5158
5188
|
const isConnected = await inGqlClient.verifyApiConnection();
|
|
5159
5189
|
if (!isConnected) {
|
|
@@ -5195,7 +5225,8 @@ async function handleMobbLogin({
|
|
|
5195
5225
|
const loginId = await inGqlClient.createCliLogin({
|
|
5196
5226
|
publicKey: publicKey.export({ format: "pem", type: "pkcs1" }).toString()
|
|
5197
5227
|
});
|
|
5198
|
-
const
|
|
5228
|
+
const webLoginUrl = `${resolvedWebAppUrl}/cli-login`;
|
|
5229
|
+
const browserUrl = loginContext ? buildLoginUrl(webLoginUrl, loginId, os.hostname(), loginContext) : `${webLoginUrl}/${loginId}?hostname=${os.hostname()}`;
|
|
5199
5230
|
!skipPrompts && console.log(
|
|
5200
5231
|
`If the page does not open automatically, kindly access it through ${browserUrl}.`
|
|
5201
5232
|
);
|
|
@@ -5433,6 +5464,22 @@ async function sanitizeDataWithCounts(obj) {
|
|
|
5433
5464
|
}
|
|
5434
5465
|
|
|
5435
5466
|
// src/args/commands/upload_ai_blame.ts
|
|
5467
|
+
var defaultLogger = {
|
|
5468
|
+
info: (msg, data) => {
|
|
5469
|
+
if (data !== void 0) {
|
|
5470
|
+
console.log(msg, data);
|
|
5471
|
+
} else {
|
|
5472
|
+
console.log(msg);
|
|
5473
|
+
}
|
|
5474
|
+
},
|
|
5475
|
+
error: (msg, data) => {
|
|
5476
|
+
if (data !== void 0) {
|
|
5477
|
+
console.error(msg, data);
|
|
5478
|
+
} else {
|
|
5479
|
+
console.error(msg);
|
|
5480
|
+
}
|
|
5481
|
+
}
|
|
5482
|
+
};
|
|
5436
5483
|
var PromptItemZ = z26.object({
|
|
5437
5484
|
type: z26.enum(["USER_PROMPT", "AI_RESPONSE", "TOOL_EXECUTION", "AI_THINKING"]),
|
|
5438
5485
|
attachedFiles: z26.array(
|
|
@@ -5548,7 +5595,12 @@ async function uploadAiBlameHandlerFromExtension(args) {
|
|
|
5548
5595
|
if (args.sessionId) {
|
|
5549
5596
|
uploadArgs.sessionId.push(args.sessionId);
|
|
5550
5597
|
}
|
|
5551
|
-
await uploadAiBlameHandler(
|
|
5598
|
+
await uploadAiBlameHandler({
|
|
5599
|
+
args: uploadArgs,
|
|
5600
|
+
exitOnError: false,
|
|
5601
|
+
apiUrl: args.apiUrl,
|
|
5602
|
+
webAppUrl: args.webAppUrl
|
|
5603
|
+
});
|
|
5552
5604
|
});
|
|
5553
5605
|
});
|
|
5554
5606
|
return {
|
|
@@ -5558,7 +5610,14 @@ async function uploadAiBlameHandlerFromExtension(args) {
|
|
|
5558
5610
|
inferenceUUID
|
|
5559
5611
|
};
|
|
5560
5612
|
}
|
|
5561
|
-
async function uploadAiBlameHandler(
|
|
5613
|
+
async function uploadAiBlameHandler(options) {
|
|
5614
|
+
const {
|
|
5615
|
+
args,
|
|
5616
|
+
exitOnError = true,
|
|
5617
|
+
apiUrl,
|
|
5618
|
+
webAppUrl,
|
|
5619
|
+
logger = defaultLogger
|
|
5620
|
+
} = options;
|
|
5562
5621
|
const prompts = args.prompt || [];
|
|
5563
5622
|
const inferences = args.inference || [];
|
|
5564
5623
|
const models = args.model || [];
|
|
@@ -5568,7 +5627,7 @@ async function uploadAiBlameHandler(args, exitOnError = true) {
|
|
|
5568
5627
|
const sessionIds = args.sessionId || args["session-id"] || [];
|
|
5569
5628
|
if (prompts.length !== inferences.length) {
|
|
5570
5629
|
const errorMsg = "prompt and inference must have the same number of entries";
|
|
5571
|
-
|
|
5630
|
+
logger.error(chalk3.red(errorMsg));
|
|
5572
5631
|
if (exitOnError) {
|
|
5573
5632
|
process.exit(1);
|
|
5574
5633
|
}
|
|
@@ -5587,7 +5646,7 @@ async function uploadAiBlameHandler(args, exitOnError = true) {
|
|
|
5587
5646
|
]);
|
|
5588
5647
|
} catch {
|
|
5589
5648
|
const errorMsg = `File not found for session ${i + 1}`;
|
|
5590
|
-
|
|
5649
|
+
logger.error(chalk3.red(errorMsg));
|
|
5591
5650
|
if (exitOnError) {
|
|
5592
5651
|
process.exit(1);
|
|
5593
5652
|
}
|
|
@@ -5606,7 +5665,9 @@ async function uploadAiBlameHandler(args, exitOnError = true) {
|
|
|
5606
5665
|
});
|
|
5607
5666
|
}
|
|
5608
5667
|
const authenticatedClient = await getAuthenticatedGQLClient({
|
|
5609
|
-
isSkipPrompts: true
|
|
5668
|
+
isSkipPrompts: true,
|
|
5669
|
+
apiUrl,
|
|
5670
|
+
webAppUrl
|
|
5610
5671
|
});
|
|
5611
5672
|
const initSessions = sessions.map(
|
|
5612
5673
|
({ sessionId: _sessionId, ...rest }) => rest
|
|
@@ -5617,7 +5678,7 @@ async function uploadAiBlameHandler(args, exitOnError = true) {
|
|
|
5617
5678
|
const uploadSessions = initRes.uploadAIBlameInferencesInit?.uploadSessions ?? [];
|
|
5618
5679
|
if (uploadSessions.length !== sessions.length) {
|
|
5619
5680
|
const errorMsg = "Init failed to return expected number of sessions";
|
|
5620
|
-
|
|
5681
|
+
logger.error(chalk3.red(errorMsg));
|
|
5621
5682
|
if (exitOnError) {
|
|
5622
5683
|
process.exit(1);
|
|
5623
5684
|
}
|
|
@@ -5659,22 +5720,41 @@ async function uploadAiBlameHandler(args, exitOnError = true) {
|
|
|
5659
5720
|
sessionId: s.sessionId
|
|
5660
5721
|
};
|
|
5661
5722
|
});
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
5670
|
-
|
|
5723
|
+
try {
|
|
5724
|
+
logger.info(
|
|
5725
|
+
`[UPLOAD] Calling finalizeAIBlameInferencesUploadRaw with ${finalizeSessions.length} sessions`
|
|
5726
|
+
);
|
|
5727
|
+
const finRes = await authenticatedClient.finalizeAIBlameInferencesUploadRaw(
|
|
5728
|
+
{
|
|
5729
|
+
sessions: finalizeSessions
|
|
5730
|
+
}
|
|
5731
|
+
);
|
|
5732
|
+
logger.info("[UPLOAD] Finalize response:", JSON.stringify(finRes, null, 2));
|
|
5733
|
+
const status = finRes?.finalizeAIBlameInferencesUpload?.status;
|
|
5734
|
+
if (status !== "OK") {
|
|
5735
|
+
const errorMsg = finRes?.finalizeAIBlameInferencesUpload?.error || "unknown error";
|
|
5736
|
+
logger.error(
|
|
5737
|
+
chalk3.red(
|
|
5738
|
+
`[UPLOAD] Finalize failed with status: ${status}, error: ${errorMsg}`
|
|
5739
|
+
)
|
|
5740
|
+
);
|
|
5741
|
+
if (exitOnError) {
|
|
5742
|
+
process.exit(1);
|
|
5743
|
+
}
|
|
5744
|
+
throw new Error(errorMsg);
|
|
5671
5745
|
}
|
|
5672
|
-
|
|
5746
|
+
logger.info(chalk3.green("[UPLOAD] AI Blame uploads finalized successfully"));
|
|
5747
|
+
} catch (error) {
|
|
5748
|
+
logger.error("[UPLOAD] Finalize threw error:", error);
|
|
5749
|
+
throw error;
|
|
5673
5750
|
}
|
|
5674
|
-
|
|
5751
|
+
}
|
|
5752
|
+
async function uploadAiBlameCommandHandler(args) {
|
|
5753
|
+
await uploadAiBlameHandler({ args });
|
|
5675
5754
|
}
|
|
5676
5755
|
export {
|
|
5677
5756
|
uploadAiBlameBuilder,
|
|
5757
|
+
uploadAiBlameCommandHandler,
|
|
5678
5758
|
uploadAiBlameHandler,
|
|
5679
5759
|
uploadAiBlameHandlerFromExtension
|
|
5680
5760
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -11034,6 +11034,11 @@ var GQLClient = class {
|
|
|
11034
11034
|
debug6(`init with ${args}`);
|
|
11035
11035
|
this._auth = args;
|
|
11036
11036
|
this._apiUrl = args.apiUrl || API_URL;
|
|
11037
|
+
debug6(
|
|
11038
|
+
"GQLClient constructor: resolved apiUrl=%s (from param: %s)",
|
|
11039
|
+
this._apiUrl,
|
|
11040
|
+
args.apiUrl || "fallback to API_URL constant"
|
|
11041
|
+
);
|
|
11037
11042
|
this._client = new GraphQLClient(this._apiUrl, {
|
|
11038
11043
|
headers: args.type === "apiKey" ? { [API_KEY_HEADER_NAME]: args.apiKey || "" } : {
|
|
11039
11044
|
Authorization: `Bearer ${args.token}`
|
|
@@ -11400,6 +11405,38 @@ var GQLClient = class {
|
|
|
11400
11405
|
}
|
|
11401
11406
|
};
|
|
11402
11407
|
|
|
11408
|
+
// src/mcp/services/types.ts
|
|
11409
|
+
function detectIDE() {
|
|
11410
|
+
const env3 = process.env;
|
|
11411
|
+
if (env3["CURSOR_TRACE_ID"] || env3["CURSOR_SESSION_ID"]) return "cursor";
|
|
11412
|
+
if (env3["WINDSURF_IPC_HOOK"] || env3["WINDSURF_PID"]) return "windsurf";
|
|
11413
|
+
if (env3["CLAUDE_DESKTOP"] || env3["ANTHROPIC_CLAUDE"]) return "claude";
|
|
11414
|
+
if (env3["WEBSTORM_VM_OPTIONS"] || env3["IDEA_VM_OPTIONS"] || env3["JETBRAINS_IDE"])
|
|
11415
|
+
return "webstorm";
|
|
11416
|
+
if (env3["VSCODE_IPC_HOOK"] || env3["VSCODE_PID"]) return "vscode";
|
|
11417
|
+
const termProgram = env3["TERM_PROGRAM"]?.toLowerCase();
|
|
11418
|
+
if (termProgram === "windsurf") return "windsurf";
|
|
11419
|
+
if (termProgram === "vscode") return "vscode";
|
|
11420
|
+
return void 0;
|
|
11421
|
+
}
|
|
11422
|
+
function createMcpLoginContext(trigger) {
|
|
11423
|
+
return {
|
|
11424
|
+
trigger,
|
|
11425
|
+
source: "mcp",
|
|
11426
|
+
ide: detectIDE()
|
|
11427
|
+
};
|
|
11428
|
+
}
|
|
11429
|
+
function buildLoginUrl(baseUrl, loginId, hostname2, context) {
|
|
11430
|
+
const url = new URL(`${baseUrl}/${loginId}`);
|
|
11431
|
+
url.searchParams.set("hostname", hostname2);
|
|
11432
|
+
url.searchParams.set("trigger", context.trigger);
|
|
11433
|
+
url.searchParams.set("source", context.source);
|
|
11434
|
+
if (context.ide) {
|
|
11435
|
+
url.searchParams.set("ide", context.ide);
|
|
11436
|
+
}
|
|
11437
|
+
return url.toString();
|
|
11438
|
+
}
|
|
11439
|
+
|
|
11403
11440
|
// src/utils/ConfigStoreService.ts
|
|
11404
11441
|
import Configstore from "configstore";
|
|
11405
11442
|
function createConfigStore(defaultValues = { apiToken: "" }) {
|
|
@@ -11432,6 +11469,11 @@ async function getAuthenticatedGQLClient({
|
|
|
11432
11469
|
apiUrl,
|
|
11433
11470
|
webAppUrl
|
|
11434
11471
|
}) {
|
|
11472
|
+
debug7(
|
|
11473
|
+
"getAuthenticatedGQLClient called with: apiUrl=%s, webAppUrl=%s",
|
|
11474
|
+
apiUrl || "undefined",
|
|
11475
|
+
webAppUrl || "undefined"
|
|
11476
|
+
);
|
|
11435
11477
|
let gqlClient = new GQLClient({
|
|
11436
11478
|
apiKey: inputApiKey || configStore.get("apiToken") || "",
|
|
11437
11479
|
type: "apiKey",
|
|
@@ -11450,10 +11492,18 @@ async function handleMobbLogin({
|
|
|
11450
11492
|
apiKey,
|
|
11451
11493
|
skipPrompts,
|
|
11452
11494
|
apiUrl,
|
|
11453
|
-
webAppUrl
|
|
11495
|
+
webAppUrl,
|
|
11496
|
+
loginContext
|
|
11454
11497
|
}) {
|
|
11455
11498
|
const resolvedWebAppUrl = webAppUrl || WEB_APP_URL;
|
|
11456
11499
|
const resolvedApiUrl = apiUrl || API_URL;
|
|
11500
|
+
debug7(
|
|
11501
|
+
"handleMobbLogin: resolved URLs - apiUrl=%s (from param: %s), webAppUrl=%s (from param: %s)",
|
|
11502
|
+
resolvedApiUrl,
|
|
11503
|
+
apiUrl || "fallback",
|
|
11504
|
+
resolvedWebAppUrl,
|
|
11505
|
+
webAppUrl || "fallback"
|
|
11506
|
+
);
|
|
11457
11507
|
const { createSpinner: createSpinner5 } = Spinner({ ci: skipPrompts });
|
|
11458
11508
|
const isConnected = await inGqlClient.verifyApiConnection();
|
|
11459
11509
|
if (!isConnected) {
|
|
@@ -11495,7 +11545,8 @@ async function handleMobbLogin({
|
|
|
11495
11545
|
const loginId = await inGqlClient.createCliLogin({
|
|
11496
11546
|
publicKey: publicKey.export({ format: "pem", type: "pkcs1" }).toString()
|
|
11497
11547
|
});
|
|
11498
|
-
const
|
|
11548
|
+
const webLoginUrl = `${resolvedWebAppUrl}/cli-login`;
|
|
11549
|
+
const browserUrl = loginContext ? buildLoginUrl(webLoginUrl, loginId, os.hostname(), loginContext) : `${webLoginUrl}/${loginId}?hostname=${os.hostname()}`;
|
|
11499
11550
|
!skipPrompts && console.log(
|
|
11500
11551
|
`If the page does not open automatically, kindly access it through ${browserUrl}.`
|
|
11501
11552
|
);
|
|
@@ -13767,6 +13818,22 @@ async function sanitizeDataWithCounts(obj) {
|
|
|
13767
13818
|
}
|
|
13768
13819
|
|
|
13769
13820
|
// src/args/commands/upload_ai_blame.ts
|
|
13821
|
+
var defaultLogger2 = {
|
|
13822
|
+
info: (msg, data) => {
|
|
13823
|
+
if (data !== void 0) {
|
|
13824
|
+
console.log(msg, data);
|
|
13825
|
+
} else {
|
|
13826
|
+
console.log(msg);
|
|
13827
|
+
}
|
|
13828
|
+
},
|
|
13829
|
+
error: (msg, data) => {
|
|
13830
|
+
if (data !== void 0) {
|
|
13831
|
+
console.error(msg, data);
|
|
13832
|
+
} else {
|
|
13833
|
+
console.error(msg);
|
|
13834
|
+
}
|
|
13835
|
+
}
|
|
13836
|
+
};
|
|
13770
13837
|
var PromptItemZ = z31.object({
|
|
13771
13838
|
type: z31.enum(["USER_PROMPT", "AI_RESPONSE", "TOOL_EXECUTION", "AI_THINKING"]),
|
|
13772
13839
|
attachedFiles: z31.array(
|
|
@@ -13882,7 +13949,12 @@ async function uploadAiBlameHandlerFromExtension(args) {
|
|
|
13882
13949
|
if (args.sessionId) {
|
|
13883
13950
|
uploadArgs.sessionId.push(args.sessionId);
|
|
13884
13951
|
}
|
|
13885
|
-
await uploadAiBlameHandler(
|
|
13952
|
+
await uploadAiBlameHandler({
|
|
13953
|
+
args: uploadArgs,
|
|
13954
|
+
exitOnError: false,
|
|
13955
|
+
apiUrl: args.apiUrl,
|
|
13956
|
+
webAppUrl: args.webAppUrl
|
|
13957
|
+
});
|
|
13886
13958
|
});
|
|
13887
13959
|
});
|
|
13888
13960
|
return {
|
|
@@ -13892,7 +13964,14 @@ async function uploadAiBlameHandlerFromExtension(args) {
|
|
|
13892
13964
|
inferenceUUID
|
|
13893
13965
|
};
|
|
13894
13966
|
}
|
|
13895
|
-
async function uploadAiBlameHandler(
|
|
13967
|
+
async function uploadAiBlameHandler(options) {
|
|
13968
|
+
const {
|
|
13969
|
+
args,
|
|
13970
|
+
exitOnError = true,
|
|
13971
|
+
apiUrl,
|
|
13972
|
+
webAppUrl,
|
|
13973
|
+
logger: logger2 = defaultLogger2
|
|
13974
|
+
} = options;
|
|
13896
13975
|
const prompts = args.prompt || [];
|
|
13897
13976
|
const inferences = args.inference || [];
|
|
13898
13977
|
const models = args.model || [];
|
|
@@ -13902,7 +13981,7 @@ async function uploadAiBlameHandler(args, exitOnError = true) {
|
|
|
13902
13981
|
const sessionIds = args.sessionId || args["session-id"] || [];
|
|
13903
13982
|
if (prompts.length !== inferences.length) {
|
|
13904
13983
|
const errorMsg = "prompt and inference must have the same number of entries";
|
|
13905
|
-
|
|
13984
|
+
logger2.error(chalk9.red(errorMsg));
|
|
13906
13985
|
if (exitOnError) {
|
|
13907
13986
|
process.exit(1);
|
|
13908
13987
|
}
|
|
@@ -13921,7 +14000,7 @@ async function uploadAiBlameHandler(args, exitOnError = true) {
|
|
|
13921
14000
|
]);
|
|
13922
14001
|
} catch {
|
|
13923
14002
|
const errorMsg = `File not found for session ${i + 1}`;
|
|
13924
|
-
|
|
14003
|
+
logger2.error(chalk9.red(errorMsg));
|
|
13925
14004
|
if (exitOnError) {
|
|
13926
14005
|
process.exit(1);
|
|
13927
14006
|
}
|
|
@@ -13940,7 +14019,9 @@ async function uploadAiBlameHandler(args, exitOnError = true) {
|
|
|
13940
14019
|
});
|
|
13941
14020
|
}
|
|
13942
14021
|
const authenticatedClient = await getAuthenticatedGQLClient({
|
|
13943
|
-
isSkipPrompts: true
|
|
14022
|
+
isSkipPrompts: true,
|
|
14023
|
+
apiUrl,
|
|
14024
|
+
webAppUrl
|
|
13944
14025
|
});
|
|
13945
14026
|
const initSessions = sessions.map(
|
|
13946
14027
|
({ sessionId: _sessionId, ...rest }) => rest
|
|
@@ -13951,7 +14032,7 @@ async function uploadAiBlameHandler(args, exitOnError = true) {
|
|
|
13951
14032
|
const uploadSessions = initRes.uploadAIBlameInferencesInit?.uploadSessions ?? [];
|
|
13952
14033
|
if (uploadSessions.length !== sessions.length) {
|
|
13953
14034
|
const errorMsg = "Init failed to return expected number of sessions";
|
|
13954
|
-
|
|
14035
|
+
logger2.error(chalk9.red(errorMsg));
|
|
13955
14036
|
if (exitOnError) {
|
|
13956
14037
|
process.exit(1);
|
|
13957
14038
|
}
|
|
@@ -13993,19 +14074,37 @@ async function uploadAiBlameHandler(args, exitOnError = true) {
|
|
|
13993
14074
|
sessionId: s.sessionId
|
|
13994
14075
|
};
|
|
13995
14076
|
});
|
|
13996
|
-
|
|
13997
|
-
|
|
13998
|
-
|
|
13999
|
-
|
|
14000
|
-
|
|
14001
|
-
|
|
14002
|
-
|
|
14003
|
-
|
|
14004
|
-
|
|
14077
|
+
try {
|
|
14078
|
+
logger2.info(
|
|
14079
|
+
`[UPLOAD] Calling finalizeAIBlameInferencesUploadRaw with ${finalizeSessions.length} sessions`
|
|
14080
|
+
);
|
|
14081
|
+
const finRes = await authenticatedClient.finalizeAIBlameInferencesUploadRaw(
|
|
14082
|
+
{
|
|
14083
|
+
sessions: finalizeSessions
|
|
14084
|
+
}
|
|
14085
|
+
);
|
|
14086
|
+
logger2.info("[UPLOAD] Finalize response:", JSON.stringify(finRes, null, 2));
|
|
14087
|
+
const status = finRes?.finalizeAIBlameInferencesUpload?.status;
|
|
14088
|
+
if (status !== "OK") {
|
|
14089
|
+
const errorMsg = finRes?.finalizeAIBlameInferencesUpload?.error || "unknown error";
|
|
14090
|
+
logger2.error(
|
|
14091
|
+
chalk9.red(
|
|
14092
|
+
`[UPLOAD] Finalize failed with status: ${status}, error: ${errorMsg}`
|
|
14093
|
+
)
|
|
14094
|
+
);
|
|
14095
|
+
if (exitOnError) {
|
|
14096
|
+
process.exit(1);
|
|
14097
|
+
}
|
|
14098
|
+
throw new Error(errorMsg);
|
|
14005
14099
|
}
|
|
14006
|
-
|
|
14100
|
+
logger2.info(chalk9.green("[UPLOAD] AI Blame uploads finalized successfully"));
|
|
14101
|
+
} catch (error) {
|
|
14102
|
+
logger2.error("[UPLOAD] Finalize threw error:", error);
|
|
14103
|
+
throw error;
|
|
14007
14104
|
}
|
|
14008
|
-
|
|
14105
|
+
}
|
|
14106
|
+
async function uploadAiBlameCommandHandler(args) {
|
|
14107
|
+
await uploadAiBlameHandler({ args });
|
|
14009
14108
|
}
|
|
14010
14109
|
|
|
14011
14110
|
// src/features/claude_code/transcript_parser.ts
|
|
@@ -14263,7 +14362,8 @@ async function processAndUploadHookData() {
|
|
|
14263
14362
|
model: result.tracePayload.model,
|
|
14264
14363
|
tool: result.tracePayload.tool,
|
|
14265
14364
|
responseTime: result.tracePayload.responseTime,
|
|
14266
|
-
blameType: "CHAT" /* Chat
|
|
14365
|
+
blameType: "CHAT" /* Chat */,
|
|
14366
|
+
sessionId: result.hookData.session_id
|
|
14267
14367
|
});
|
|
14268
14368
|
uploadSuccess = true;
|
|
14269
14369
|
} catch (error) {
|
|
@@ -14776,9 +14876,10 @@ var McpAuthService = class {
|
|
|
14776
14876
|
/**
|
|
14777
14877
|
* Handles the complete authentication flow
|
|
14778
14878
|
* @param isBackgoundCall Whether this is called from tools context
|
|
14879
|
+
* @param loginContext Context information about who triggered the login
|
|
14779
14880
|
* @returns Authenticated API token
|
|
14780
14881
|
*/
|
|
14781
|
-
async authenticate(isBackgoundCall = false) {
|
|
14882
|
+
async authenticate(isBackgoundCall = false, loginContext) {
|
|
14782
14883
|
const { publicKey, privateKey } = crypto2.generateKeyPairSync("rsa", {
|
|
14783
14884
|
modulusLength: 2048
|
|
14784
14885
|
});
|
|
@@ -14791,7 +14892,7 @@ var McpAuthService = class {
|
|
|
14791
14892
|
}
|
|
14792
14893
|
logDebug(`cli login created ${loginId}`);
|
|
14793
14894
|
const webLoginUrl = `${WEB_APP_URL}/mvs-login`;
|
|
14794
|
-
const browserUrl = `${webLoginUrl}/${loginId}?hostname=${os4.hostname()}`;
|
|
14895
|
+
const browserUrl = loginContext ? buildLoginUrl(webLoginUrl, loginId, os4.hostname(), loginContext) : `${webLoginUrl}/${loginId}?hostname=${os4.hostname()}`;
|
|
14795
14896
|
await this.openBrowser(browserUrl, isBackgoundCall);
|
|
14796
14897
|
logDebug(`waiting for login to complete`);
|
|
14797
14898
|
let newApiToken = null;
|
|
@@ -15465,7 +15566,8 @@ var McpGQLClient = class {
|
|
|
15465
15566
|
}
|
|
15466
15567
|
};
|
|
15467
15568
|
async function createAuthenticatedMcpGQLClient({
|
|
15468
|
-
isBackgroundCall = false
|
|
15569
|
+
isBackgroundCall = false,
|
|
15570
|
+
loginContext
|
|
15469
15571
|
} = {}) {
|
|
15470
15572
|
logDebug("[GraphQL] Getting config", {
|
|
15471
15573
|
apiToken: configStore.get("apiToken")
|
|
@@ -15486,7 +15588,10 @@ async function createAuthenticatedMcpGQLClient({
|
|
|
15486
15588
|
return initialClient;
|
|
15487
15589
|
}
|
|
15488
15590
|
const authService = new McpAuthService(initialClient);
|
|
15489
|
-
const newApiToken = await authService.authenticate(
|
|
15591
|
+
const newApiToken = await authService.authenticate(
|
|
15592
|
+
isBackgroundCall,
|
|
15593
|
+
loginContext
|
|
15594
|
+
);
|
|
15490
15595
|
configStore.set("apiToken", newApiToken);
|
|
15491
15596
|
return new McpGQLClient({ apiKey: newApiToken, type: "apiKey" });
|
|
15492
15597
|
}
|
|
@@ -18430,7 +18535,10 @@ var BaseTool = class {
|
|
|
18430
18535
|
async execute(args) {
|
|
18431
18536
|
if (this.hasAuthentication) {
|
|
18432
18537
|
logDebug(`Authenticating tool: ${this.name}`, { args });
|
|
18433
|
-
const
|
|
18538
|
+
const loginContext = createMcpLoginContext(this.name);
|
|
18539
|
+
const mcpGqlClient = await createAuthenticatedMcpGQLClient({
|
|
18540
|
+
loginContext
|
|
18541
|
+
});
|
|
18434
18542
|
const userInfo2 = await mcpGqlClient.getUserInfo();
|
|
18435
18543
|
logDebug("User authenticated successfully", { userInfo: userInfo2 });
|
|
18436
18544
|
}
|
|
@@ -21664,7 +21772,8 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
|
|
|
21664
21772
|
logInfo(`[${scanContext}] Reset service state for new path`, { path: path22 });
|
|
21665
21773
|
}
|
|
21666
21774
|
try {
|
|
21667
|
-
|
|
21775
|
+
const loginContext = createMcpLoginContext("check_new_fixes");
|
|
21776
|
+
this.gqlClient = await createAuthenticatedMcpGQLClient({ loginContext });
|
|
21668
21777
|
} catch (error) {
|
|
21669
21778
|
const errorMessage = error.message;
|
|
21670
21779
|
if (errorMessage.includes("Authentication failed") || errorMessage.includes("access-denied") || errorMessage.includes("Authentication hook unauthorized")) {
|
|
@@ -21916,7 +22025,8 @@ var _FetchAvailableFixesService = class _FetchAvailableFixesService {
|
|
|
21916
22025
|
}
|
|
21917
22026
|
async initializeGqlClient() {
|
|
21918
22027
|
if (!this.gqlClient) {
|
|
21919
|
-
|
|
22028
|
+
const loginContext = createMcpLoginContext("fetch_fixes");
|
|
22029
|
+
this.gqlClient = await createAuthenticatedMcpGQLClient({ loginContext });
|
|
21920
22030
|
}
|
|
21921
22031
|
return this.gqlClient;
|
|
21922
22032
|
}
|
|
@@ -22313,7 +22423,8 @@ var _ScanAndFixVulnerabilitiesService = class _ScanAndFixVulnerabilitiesService
|
|
|
22313
22423
|
}
|
|
22314
22424
|
}
|
|
22315
22425
|
async initializeGqlClient() {
|
|
22316
|
-
const
|
|
22426
|
+
const loginContext = createMcpLoginContext("scan_vulnerabilities");
|
|
22427
|
+
const gqlClient = await createAuthenticatedMcpGQLClient({ loginContext });
|
|
22317
22428
|
const isConnected = await gqlClient.verifyApiConnection();
|
|
22318
22429
|
if (!isConnected) {
|
|
22319
22430
|
throw new ApiConnectionError(
|
|
@@ -22746,7 +22857,7 @@ var parseArgs = async (args) => {
|
|
|
22746
22857
|
"Upload AI Blame inference artifacts (prompt + inference) and finalize them."
|
|
22747
22858
|
),
|
|
22748
22859
|
uploadAiBlameBuilder,
|
|
22749
|
-
|
|
22860
|
+
uploadAiBlameCommandHandler
|
|
22750
22861
|
).command(
|
|
22751
22862
|
mobbCliCommand.claudeCodeInstallHook,
|
|
22752
22863
|
chalk12.bold("Install Claude Code hooks for data collection."),
|