mobbdev 1.0.217 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.mjs +984 -486
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -1323,7 +1323,7 @@ import Debug20 from "debug";
1323
1323
  import { hideBin } from "yargs/helpers";
1324
1324
 
1325
1325
  // src/args/yargs.ts
1326
- import chalk11 from "chalk";
1326
+ import chalk12 from "chalk";
1327
1327
  import yargs from "yargs/yargs";
1328
1328
 
1329
1329
  // src/args/commands/convert_to_sarif.ts
@@ -6247,7 +6247,7 @@ async function getAdoSdk(params) {
6247
6247
  const url = new URL(repoUrl);
6248
6248
  const origin2 = url.origin.toLowerCase().endsWith(".visualstudio.com") ? DEFUALT_ADO_ORIGIN : url.origin.toLowerCase();
6249
6249
  const params2 = `path=/&versionDescriptor[versionOptions]=0&versionDescriptor[versionType]=commit&versionDescriptor[version]=${branch}&resolveLfs=true&$format=zip&api-version=5.0&download=true`;
6250
- const path21 = [
6250
+ const path22 = [
6251
6251
  prefixPath,
6252
6252
  owner,
6253
6253
  projectName,
@@ -6258,7 +6258,7 @@ async function getAdoSdk(params) {
6258
6258
  "items",
6259
6259
  "items"
6260
6260
  ].filter(Boolean).join("/");
6261
- return new URL(`${path21}?${params2}`, origin2).toString();
6261
+ return new URL(`${path22}?${params2}`, origin2).toString();
6262
6262
  },
6263
6263
  async getAdoBranchList({ repoUrl }) {
6264
6264
  try {
@@ -7805,14 +7805,14 @@ function getGithubSdk(params = {}) {
7805
7805
  };
7806
7806
  },
7807
7807
  async getGithubBlameRanges(params2) {
7808
- const { ref, gitHubUrl, path: path21 } = params2;
7808
+ const { ref, gitHubUrl, path: path22 } = params2;
7809
7809
  const { owner, repo } = parseGithubOwnerAndRepo(gitHubUrl);
7810
7810
  const res = await octokit.graphql(
7811
7811
  GET_BLAME_DOCUMENT,
7812
7812
  {
7813
7813
  owner,
7814
7814
  repo,
7815
- path: path21,
7815
+ path: path22,
7816
7816
  ref
7817
7817
  }
7818
7818
  );
@@ -8179,11 +8179,11 @@ var GithubSCMLib = class extends SCMLib {
8179
8179
  markdownComment: comment
8180
8180
  });
8181
8181
  }
8182
- async getRepoBlameRanges(ref, path21) {
8182
+ async getRepoBlameRanges(ref, path22) {
8183
8183
  this._validateUrl();
8184
8184
  return await this.githubSdk.getGithubBlameRanges({
8185
8185
  ref,
8186
- path: path21,
8186
+ path: path22,
8187
8187
  gitHubUrl: this.url
8188
8188
  });
8189
8189
  }
@@ -8863,13 +8863,13 @@ function parseGitlabOwnerAndRepo(gitlabUrl) {
8863
8863
  const { organization, repoName, projectPath } = parsingResult;
8864
8864
  return { owner: organization, repo: repoName, projectPath };
8865
8865
  }
8866
- async function getGitlabBlameRanges({ ref, gitlabUrl, path: path21 }, options) {
8866
+ async function getGitlabBlameRanges({ ref, gitlabUrl, path: path22 }, options) {
8867
8867
  const { projectPath } = parseGitlabOwnerAndRepo(gitlabUrl);
8868
8868
  const api2 = getGitBeaker({
8869
8869
  url: gitlabUrl,
8870
8870
  gitlabAuthToken: options?.gitlabAuthToken
8871
8871
  });
8872
- const resp = await api2.RepositoryFiles.allFileBlames(projectPath, path21, ref);
8872
+ const resp = await api2.RepositoryFiles.allFileBlames(projectPath, path22, ref);
8873
8873
  let lineNumber = 1;
8874
8874
  return resp.filter((range) => range.lines).map((range) => {
8875
8875
  const oldLineNumber = lineNumber;
@@ -9046,10 +9046,10 @@ var GitlabSCMLib = class extends SCMLib {
9046
9046
  markdownComment: comment
9047
9047
  });
9048
9048
  }
9049
- async getRepoBlameRanges(ref, path21) {
9049
+ async getRepoBlameRanges(ref, path22) {
9050
9050
  this._validateUrl();
9051
9051
  return await getGitlabBlameRanges(
9052
- { ref, path: path21, gitlabUrl: this.url },
9052
+ { ref, path: path22, gitlabUrl: this.url },
9053
9053
  {
9054
9054
  url: this.url,
9055
9055
  gitlabAuthToken: this.accessToken
@@ -10051,7 +10051,9 @@ var mobbCliCommand = {
10051
10051
  review: "review",
10052
10052
  convertToSarif: "convert-to-sarif",
10053
10053
  mcp: "mcp",
10054
- uploadAiBlame: "upload-ai-blame"
10054
+ uploadAiBlame: "upload-ai-blame",
10055
+ claudeCodeInstallHook: "claude-code-install-hook",
10056
+ claudeCodeProcessHook: "claude-code-process-hook"
10055
10057
  };
10056
10058
  var ScanContext = {
10057
10059
  FULL_SCAN: "FULL_SCAN",
@@ -11088,7 +11090,7 @@ async function postIssueComment(params) {
11088
11090
  fpDescription
11089
11091
  } = params;
11090
11092
  const {
11091
- path: path21,
11093
+ path: path22,
11092
11094
  startLine,
11093
11095
  vulnerabilityReportIssue: {
11094
11096
  vulnerabilityReportIssueTags,
@@ -11103,7 +11105,7 @@ async function postIssueComment(params) {
11103
11105
  Refresh the page in order to see the changes.`,
11104
11106
  pull_number: pullRequest,
11105
11107
  commit_id: commitSha,
11106
- path: path21,
11108
+ path: path22,
11107
11109
  line: startLine
11108
11110
  });
11109
11111
  const commentId = commentRes.data.id;
@@ -11137,7 +11139,7 @@ async function postFixComment(params) {
11137
11139
  scanner
11138
11140
  } = params;
11139
11141
  const {
11140
- path: path21,
11142
+ path: path22,
11141
11143
  startLine,
11142
11144
  vulnerabilityReportIssue: { fixId, vulnerabilityReportIssueTags, category },
11143
11145
  vulnerabilityReportIssueId
@@ -11155,7 +11157,7 @@ async function postFixComment(params) {
11155
11157
  Refresh the page in order to see the changes.`,
11156
11158
  pull_number: pullRequest,
11157
11159
  commit_id: commitSha,
11158
- path: path21,
11160
+ path: path22,
11159
11161
  line: startLine
11160
11162
  });
11161
11163
  const commentId = commentRes.data.id;
@@ -11736,8 +11738,8 @@ if (typeof __filename !== "undefined") {
11736
11738
  }
11737
11739
  var costumeRequire = createRequire(moduleUrl);
11738
11740
  var getCheckmarxPath = () => {
11739
- const os9 = type();
11740
- const cxFileName = os9 === "Windows_NT" ? "cx.exe" : "cx";
11741
+ const os10 = type();
11742
+ const cxFileName = os10 === "Windows_NT" ? "cx.exe" : "cx";
11741
11743
  try {
11742
11744
  return costumeRequire.resolve(`.bin/${cxFileName}`);
11743
11745
  } catch (e) {
@@ -11881,8 +11883,8 @@ async function forkSnyk(args, { display }) {
11881
11883
  }
11882
11884
  async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
11883
11885
  debug17("get snyk report start %s %s", reportPath, repoRoot);
11884
- const config6 = await forkSnyk(["config"], { display: false });
11885
- const { message: configMessage } = config6;
11886
+ const config7 = await forkSnyk(["config"], { display: false });
11887
+ const { message: configMessage } = config7;
11886
11888
  if (!configMessage.includes("api: ")) {
11887
11889
  const snykLoginSpinner = createSpinner3().start();
11888
11890
  if (!skipPrompts) {
@@ -11894,7 +11896,7 @@ async function getSnykReport(reportPath, repoRoot, { skipPrompts = false }) {
11894
11896
  snykLoginSpinner.update({
11895
11897
  text: "\u{1F513} Waiting for Snyk login to complete"
11896
11898
  });
11897
- debug17("no token in the config %s", config6);
11899
+ debug17("no token in the config %s", config7);
11898
11900
  await forkSnyk(["auth"], { display: true });
11899
11901
  snykLoginSpinner.success({ text: "\u{1F513} Login to Snyk Successful" });
11900
11902
  }
@@ -12894,6 +12896,673 @@ async function analyzeHandler(args) {
12894
12896
  await analyze(args, { skipPrompts: args.yes });
12895
12897
  }
12896
12898
 
12899
+ // src/args/commands/claude_code.ts
12900
+ import Configstore5 from "configstore";
12901
+
12902
+ // src/features/claude_code/data_collector.ts
12903
+ import { z as z32 } from "zod";
12904
+
12905
+ // src/args/commands/upload_ai_blame.ts
12906
+ import fsPromises3 from "fs/promises";
12907
+ import path11 from "path";
12908
+ import chalk9 from "chalk";
12909
+ import Configstore4 from "configstore";
12910
+ import { withFile } from "tmp-promise";
12911
+ import z31 from "zod";
12912
+ var PromptItemZ = z31.object({
12913
+ type: z31.enum(["USER_PROMPT", "AI_RESPONSE", "TOOL_EXECUTION", "AI_THINKING"]),
12914
+ attachedFiles: z31.array(
12915
+ z31.object({
12916
+ relativePath: z31.string(),
12917
+ startLine: z31.number().optional()
12918
+ })
12919
+ ).optional(),
12920
+ tokens: z31.object({
12921
+ inputCount: z31.number(),
12922
+ outputCount: z31.number()
12923
+ }).optional(),
12924
+ text: z31.string().optional(),
12925
+ date: z31.date().optional(),
12926
+ tool: z31.object({
12927
+ name: z31.string(),
12928
+ parameters: z31.string(),
12929
+ result: z31.string(),
12930
+ rawArguments: z31.string().optional(),
12931
+ accepted: z31.boolean().optional()
12932
+ }).optional()
12933
+ });
12934
+ var PromptItemArrayZ = z31.array(PromptItemZ);
12935
+ function uploadAiBlameBuilder(args) {
12936
+ return args.option("prompt", {
12937
+ type: "string",
12938
+ array: true,
12939
+ demandOption: true,
12940
+ describe: chalk9.bold("Path(s) to prompt artifact(s) (one per session)")
12941
+ }).option("inference", {
12942
+ type: "string",
12943
+ array: true,
12944
+ demandOption: true,
12945
+ describe: chalk9.bold(
12946
+ "Path(s) to inference artifact(s) (one per session)"
12947
+ )
12948
+ }).option("ai-response-at", {
12949
+ type: "string",
12950
+ array: true,
12951
+ describe: chalk9.bold(
12952
+ "ISO timestamp(s) for AI response (one per session, defaults to now)"
12953
+ )
12954
+ }).option("model", {
12955
+ type: "string",
12956
+ array: true,
12957
+ describe: chalk9.bold("AI model name(s) (optional, one per session)")
12958
+ }).option("tool-name", {
12959
+ type: "string",
12960
+ array: true,
12961
+ describe: chalk9.bold("Tool/IDE name(s) (optional, one per session)")
12962
+ }).option("blame-type", {
12963
+ type: "string",
12964
+ array: true,
12965
+ choices: Object.values(AiBlameInferenceType),
12966
+ describe: chalk9.bold(
12967
+ "Blame type(s) (optional, one per session, defaults to CHAT)"
12968
+ )
12969
+ }).strict();
12970
+ }
12971
+ async function uploadAiBlameHandlerFromExtension(args) {
12972
+ const uploadArgs = {
12973
+ prompt: [],
12974
+ inference: [],
12975
+ model: [],
12976
+ toolName: [],
12977
+ aiResponseAt: [],
12978
+ blameType: []
12979
+ };
12980
+ await withFile(async (promptFile) => {
12981
+ await fsPromises3.writeFile(
12982
+ promptFile.path,
12983
+ JSON.stringify(args.prompts, null, 2),
12984
+ "utf-8"
12985
+ );
12986
+ uploadArgs.prompt.push(promptFile.path);
12987
+ await withFile(async (inferenceFile) => {
12988
+ await fsPromises3.writeFile(inferenceFile.path, args.inference, "utf-8");
12989
+ uploadArgs.inference.push(inferenceFile.path);
12990
+ uploadArgs.model.push(args.model);
12991
+ uploadArgs.toolName.push(args.tool);
12992
+ uploadArgs.aiResponseAt.push(args.responseTime);
12993
+ uploadArgs.blameType.push(args.blameType || "CHAT" /* Chat */);
12994
+ await uploadAiBlameHandler(uploadArgs, false);
12995
+ });
12996
+ });
12997
+ }
12998
+ var config5 = new Configstore4(packageJson.name, { apiToken: "" });
12999
+ async function getAuthenticatedGQLClientForIdeExtension() {
13000
+ let gqlClient = new GQLClient({
13001
+ apiKey: config5.get("apiToken") ?? "",
13002
+ type: "apiKey"
13003
+ });
13004
+ gqlClient = await handleMobbLogin({
13005
+ inGqlClient: gqlClient,
13006
+ skipPrompts: true
13007
+ });
13008
+ return gqlClient;
13009
+ }
13010
+ async function uploadAiBlameHandler(args, exitOnError = true) {
13011
+ const prompts = args.prompt || [];
13012
+ const inferences = args.inference || [];
13013
+ const models = args.model || [];
13014
+ const tools = args.toolName || args["tool-name"] || [];
13015
+ const responseTimes = args.aiResponseAt || args["ai-response-at"] || [];
13016
+ const blameTypes = args.blameType || args["blame-type"] || [];
13017
+ if (prompts.length !== inferences.length) {
13018
+ const errorMsg = "prompt and inference must have the same number of entries";
13019
+ console.error(chalk9.red(errorMsg));
13020
+ if (exitOnError) {
13021
+ process.exit(1);
13022
+ }
13023
+ throw new Error(errorMsg);
13024
+ }
13025
+ const nowIso = (/* @__PURE__ */ new Date()).toISOString();
13026
+ const sessions = [];
13027
+ for (let i = 0; i < prompts.length; i++) {
13028
+ const promptPath = String(prompts[i]);
13029
+ const inferencePath = String(inferences[i]);
13030
+ try {
13031
+ await Promise.all([
13032
+ fsPromises3.access(promptPath),
13033
+ fsPromises3.access(inferencePath)
13034
+ ]);
13035
+ } catch {
13036
+ const errorMsg = `File not found for session ${i + 1}`;
13037
+ console.error(chalk9.red(errorMsg));
13038
+ if (exitOnError) {
13039
+ process.exit(1);
13040
+ }
13041
+ throw new Error(errorMsg);
13042
+ }
13043
+ sessions.push({
13044
+ promptFileName: path11.basename(promptPath),
13045
+ inferenceFileName: path11.basename(inferencePath),
13046
+ aiResponseAt: responseTimes[i] || nowIso,
13047
+ model: models[i],
13048
+ toolName: tools[i],
13049
+ blameType: blameTypes[i] || "CHAT" /* Chat */
13050
+ });
13051
+ }
13052
+ const authenticatedClient = await getAuthenticatedGQLClientForIdeExtension();
13053
+ const initRes = await authenticatedClient.uploadAIBlameInferencesInitRaw({
13054
+ sessions
13055
+ });
13056
+ const uploadSessions = initRes.uploadAIBlameInferencesInit?.uploadSessions ?? [];
13057
+ if (uploadSessions.length !== sessions.length) {
13058
+ const errorMsg = "Init failed to return expected number of sessions";
13059
+ console.error(chalk9.red(errorMsg));
13060
+ if (exitOnError) {
13061
+ process.exit(1);
13062
+ }
13063
+ throw new Error(errorMsg);
13064
+ }
13065
+ for (let i = 0; i < uploadSessions.length; i++) {
13066
+ const us = uploadSessions[i];
13067
+ const promptPath = String(prompts[i]);
13068
+ const inferencePath = String(inferences[i]);
13069
+ await Promise.all([
13070
+ // Prompt
13071
+ uploadFile({
13072
+ file: promptPath,
13073
+ url: us.prompt.url,
13074
+ uploadFields: JSON.parse(us.prompt.uploadFieldsJSON),
13075
+ uploadKey: us.prompt.uploadKey
13076
+ }),
13077
+ // Inference
13078
+ uploadFile({
13079
+ file: inferencePath,
13080
+ url: us.inference.url,
13081
+ uploadFields: JSON.parse(us.inference.uploadFieldsJSON),
13082
+ uploadKey: us.inference.uploadKey
13083
+ })
13084
+ ]);
13085
+ }
13086
+ const finalizeSessions = uploadSessions.map((us, i) => {
13087
+ const s = sessions[i];
13088
+ return {
13089
+ aiBlameInferenceId: us.aiBlameInferenceId,
13090
+ promptKey: us.prompt.uploadKey,
13091
+ inferenceKey: us.inference.uploadKey,
13092
+ aiResponseAt: s.aiResponseAt,
13093
+ model: s.model,
13094
+ toolName: s.toolName,
13095
+ blameType: s.blameType
13096
+ };
13097
+ });
13098
+ const finRes = await authenticatedClient.finalizeAIBlameInferencesUploadRaw({
13099
+ sessions: finalizeSessions
13100
+ });
13101
+ const status = finRes?.finalizeAIBlameInferencesUpload?.status;
13102
+ if (status !== "OK") {
13103
+ const errorMsg = finRes?.finalizeAIBlameInferencesUpload?.error || "unknown error";
13104
+ console.error(chalk9.red(errorMsg));
13105
+ if (exitOnError) {
13106
+ process.exit(1);
13107
+ }
13108
+ throw new Error(errorMsg);
13109
+ }
13110
+ console.log(chalk9.green("AI Blame uploads finalized successfully"));
13111
+ }
13112
+
13113
+ // src/features/claude_code/transcript_parser.ts
13114
+ import fsPromises4 from "fs/promises";
13115
+ function processTranscriptLine(entry) {
13116
+ const prompts = [];
13117
+ let model;
13118
+ let inputTokens = 0;
13119
+ let outputTokens = 0;
13120
+ let date;
13121
+ if (entry.message?.model) {
13122
+ model = entry.message.model;
13123
+ }
13124
+ if (entry.message?.usage) {
13125
+ inputTokens = entry.message.usage.input_tokens || 0;
13126
+ outputTokens = entry.message.usage.output_tokens || 0;
13127
+ }
13128
+ if (entry.timestamp) {
13129
+ date = new Date(entry.timestamp);
13130
+ }
13131
+ if (entry.type === "user" && entry.message?.role === "user") {
13132
+ if (typeof entry.message.content === "string") {
13133
+ prompts.push({
13134
+ type: "USER_PROMPT",
13135
+ text: entry.message.content,
13136
+ date: date || /* @__PURE__ */ new Date(),
13137
+ tokens: inputTokens > 0 ? {
13138
+ inputCount: inputTokens,
13139
+ outputCount: 0
13140
+ } : void 0
13141
+ });
13142
+ }
13143
+ } else if (entry.type === "assistant" && entry.message?.role === "assistant") {
13144
+ if (Array.isArray(entry.message.content)) {
13145
+ for (const item of entry.message.content) {
13146
+ if (item.type === "text" && item.text) {
13147
+ prompts.push({
13148
+ type: "AI_RESPONSE",
13149
+ text: item.text,
13150
+ date: date || /* @__PURE__ */ new Date(),
13151
+ tokens: outputTokens > 0 ? {
13152
+ inputCount: 0,
13153
+ outputCount: outputTokens
13154
+ } : void 0
13155
+ });
13156
+ } else if (item.type === "thinking" && item.thinking) {
13157
+ prompts.push({
13158
+ type: "AI_THINKING",
13159
+ text: item.thinking,
13160
+ date: date || /* @__PURE__ */ new Date()
13161
+ });
13162
+ }
13163
+ }
13164
+ }
13165
+ }
13166
+ return {
13167
+ prompts,
13168
+ model,
13169
+ inputTokens,
13170
+ outputTokens,
13171
+ date
13172
+ };
13173
+ }
13174
+ async function parseTranscriptAndCreateTrace(transcriptPath, hookData, inference) {
13175
+ const content = await fsPromises4.readFile(transcriptPath, "utf-8");
13176
+ const lines = content.trim().split("\n");
13177
+ let currentToolIndex = -1;
13178
+ for (let i = lines.length - 1; i >= 0; i--) {
13179
+ const line = lines[i]?.trim() ?? "";
13180
+ if (!line.includes('"type":"tool_use"')) continue;
13181
+ const isEditTool = line.includes('"name":"Edit"');
13182
+ const isWriteTool = line.includes('"name":"Write"');
13183
+ if (isEditTool || isWriteTool) {
13184
+ currentToolIndex = i;
13185
+ break;
13186
+ }
13187
+ }
13188
+ const startIndex = 0;
13189
+ const endIndex = currentToolIndex === -1 ? lines.length - 1 : currentToolIndex - 1;
13190
+ const prompts = [];
13191
+ let model;
13192
+ let latestDate;
13193
+ for (let i = startIndex; i <= endIndex; i++) {
13194
+ const line = lines[i]?.trim() ?? "";
13195
+ const entry = JSON.parse(line);
13196
+ const lineResult = processTranscriptLine(entry);
13197
+ prompts.push(...lineResult.prompts);
13198
+ if (lineResult.model && !model) {
13199
+ model = lineResult.model;
13200
+ }
13201
+ if (lineResult.date) {
13202
+ if (!latestDate || lineResult.date > latestDate) {
13203
+ latestDate = lineResult.date;
13204
+ }
13205
+ }
13206
+ }
13207
+ prompts.push({
13208
+ type: "TOOL_EXECUTION",
13209
+ date: latestDate || /* @__PURE__ */ new Date(),
13210
+ tool: {
13211
+ name: hookData.tool_name,
13212
+ parameters: JSON.stringify(hookData.tool_input, null, 2),
13213
+ result: JSON.stringify(hookData.tool_response, null, 2),
13214
+ rawArguments: JSON.stringify(hookData.tool_input),
13215
+ accepted: true
13216
+ }
13217
+ });
13218
+ return {
13219
+ prompts,
13220
+ inference,
13221
+ model: model || "claude-sonnet-4",
13222
+ // Use extracted model or fallback
13223
+ tool: "Claude Code",
13224
+ responseTime: (latestDate || /* @__PURE__ */ new Date()).toISOString()
13225
+ };
13226
+ }
13227
+
13228
+ // src/features/claude_code/data_collector.ts
13229
+ var StructuredPatchItemSchema = z32.object({
13230
+ oldStart: z32.number(),
13231
+ oldLines: z32.number(),
13232
+ newStart: z32.number(),
13233
+ newLines: z32.number(),
13234
+ lines: z32.array(z32.string())
13235
+ });
13236
+ var EditToolInputSchema = z32.object({
13237
+ file_path: z32.string(),
13238
+ old_string: z32.string(),
13239
+ new_string: z32.string()
13240
+ });
13241
+ var WriteToolInputSchema = z32.object({
13242
+ file_path: z32.string(),
13243
+ content: z32.string()
13244
+ });
13245
+ var EditToolResponseSchema = z32.object({
13246
+ filePath: z32.string(),
13247
+ oldString: z32.string().optional(),
13248
+ newString: z32.string().optional(),
13249
+ originalFile: z32.string().optional(),
13250
+ structuredPatch: z32.array(StructuredPatchItemSchema),
13251
+ userModified: z32.boolean().optional(),
13252
+ replaceAll: z32.boolean().optional()
13253
+ });
13254
+ var WriteToolResponseSchema = z32.object({
13255
+ type: z32.string().optional(),
13256
+ filePath: z32.string(),
13257
+ content: z32.string().optional(),
13258
+ structuredPatch: z32.array(z32.any()).optional()
13259
+ });
13260
+ var HookDataSchema = z32.object({
13261
+ session_id: z32.string(),
13262
+ transcript_path: z32.string(),
13263
+ cwd: z32.string(),
13264
+ permission_mode: z32.string().optional(),
13265
+ hook_event_name: z32.literal("PostToolUse"),
13266
+ tool_name: z32.enum(["Edit", "Write"]),
13267
+ tool_input: z32.union([EditToolInputSchema, WriteToolInputSchema]),
13268
+ tool_response: z32.union([EditToolResponseSchema, WriteToolResponseSchema])
13269
+ });
13270
+ async function readStdinData() {
13271
+ return new Promise((resolve, reject) => {
13272
+ let inputData = "";
13273
+ process.stdin.setEncoding("utf-8");
13274
+ process.stdin.on("data", (chunk) => {
13275
+ inputData += chunk;
13276
+ });
13277
+ process.stdin.on("end", () => {
13278
+ try {
13279
+ const parsedData = JSON.parse(inputData);
13280
+ resolve(parsedData);
13281
+ } catch (error) {
13282
+ reject(
13283
+ new Error(
13284
+ `Failed to parse JSON from stdin: ${error.message}`
13285
+ )
13286
+ );
13287
+ }
13288
+ });
13289
+ process.stdin.on("error", (error) => {
13290
+ reject(new Error(`Error reading from stdin: ${error.message}`));
13291
+ });
13292
+ });
13293
+ }
13294
+ function validateHookData(data) {
13295
+ return HookDataSchema.parse(data);
13296
+ }
13297
+ function extractInference(hookData) {
13298
+ if (hookData.tool_name === "Write") {
13299
+ const writeInput = hookData.tool_input;
13300
+ return writeInput.content || "";
13301
+ }
13302
+ if (hookData.tool_name === "Edit") {
13303
+ const editResponse = hookData.tool_response;
13304
+ const additions = [];
13305
+ for (const patch of editResponse.structuredPatch) {
13306
+ for (const line of patch.lines) {
13307
+ if (line.startsWith("+")) {
13308
+ additions.push(line.slice(1));
13309
+ }
13310
+ }
13311
+ }
13312
+ return additions.join("\n");
13313
+ }
13314
+ return "";
13315
+ }
13316
+ async function collectHookData() {
13317
+ const rawData = await readStdinData();
13318
+ const hookData = validateHookData(rawData);
13319
+ const inference = extractInference(hookData);
13320
+ let tracePayload;
13321
+ try {
13322
+ tracePayload = await parseTranscriptAndCreateTrace(
13323
+ hookData.transcript_path,
13324
+ hookData,
13325
+ inference
13326
+ );
13327
+ } catch (error) {
13328
+ console.warn(
13329
+ "Warning: Could not parse transcript:",
13330
+ error.message
13331
+ );
13332
+ tracePayload = {
13333
+ prompts: [
13334
+ {
13335
+ type: "TOOL_EXECUTION",
13336
+ date: /* @__PURE__ */ new Date(),
13337
+ tool: {
13338
+ name: hookData.tool_name,
13339
+ parameters: JSON.stringify(hookData.tool_input, null, 2),
13340
+ result: JSON.stringify(hookData.tool_response, null, 2),
13341
+ rawArguments: JSON.stringify(hookData.tool_input),
13342
+ accepted: true
13343
+ }
13344
+ }
13345
+ ],
13346
+ inference,
13347
+ model: "claude-sonnet-4",
13348
+ tool: "Claude Code",
13349
+ responseTime: (/* @__PURE__ */ new Date()).toISOString()
13350
+ };
13351
+ }
13352
+ return {
13353
+ hookData,
13354
+ inference,
13355
+ tracePayload
13356
+ };
13357
+ }
13358
+ async function processAndUploadHookData() {
13359
+ const result = await collectHookData();
13360
+ let uploadSuccess;
13361
+ try {
13362
+ await uploadAiBlameHandlerFromExtension({
13363
+ prompts: result.tracePayload.prompts,
13364
+ inference: result.tracePayload.inference,
13365
+ model: result.tracePayload.model,
13366
+ tool: result.tracePayload.tool,
13367
+ responseTime: result.tracePayload.responseTime,
13368
+ blameType: "CHAT" /* Chat */
13369
+ });
13370
+ uploadSuccess = true;
13371
+ } catch (error) {
13372
+ console.warn(
13373
+ "Warning: Failed to upload trace data:",
13374
+ error.message
13375
+ );
13376
+ uploadSuccess = false;
13377
+ }
13378
+ return {
13379
+ ...result,
13380
+ uploadSuccess
13381
+ };
13382
+ }
13383
+
13384
+ // src/features/claude_code/install_hook.ts
13385
+ import fsPromises5 from "fs/promises";
13386
+ import os2 from "os";
13387
+ import path12 from "path";
13388
+ import chalk10 from "chalk";
13389
+ var CLAUDE_SETTINGS_PATH = path12.join(os2.homedir(), ".claude", "settings.json");
13390
+ async function claudeSettingsExists() {
13391
+ try {
13392
+ await fsPromises5.access(CLAUDE_SETTINGS_PATH);
13393
+ return true;
13394
+ } catch {
13395
+ return false;
13396
+ }
13397
+ }
13398
+ async function readClaudeSettings() {
13399
+ const settingsContent = await fsPromises5.readFile(
13400
+ CLAUDE_SETTINGS_PATH,
13401
+ "utf-8"
13402
+ );
13403
+ return JSON.parse(settingsContent);
13404
+ }
13405
+ async function writeClaudeSettings(settings) {
13406
+ await fsPromises5.writeFile(
13407
+ CLAUDE_SETTINGS_PATH,
13408
+ JSON.stringify(settings, null, 2),
13409
+ "utf-8"
13410
+ );
13411
+ }
13412
+ async function installMobbHooks(options = {}) {
13413
+ console.log(chalk10.blue("Installing Mobb hooks in Claude Code settings..."));
13414
+ if (!await claudeSettingsExists()) {
13415
+ console.log(chalk10.red("\u274C Claude Code settings file not found"));
13416
+ console.log(chalk10.yellow(`Expected location: ${CLAUDE_SETTINGS_PATH}`));
13417
+ console.log(chalk10.yellow("Is Claude Code installed on your system?"));
13418
+ console.log(chalk10.yellow("Please install Claude Code and try again."));
13419
+ throw new Error(
13420
+ "Claude Code settings file not found. Is Claude Code installed?"
13421
+ );
13422
+ }
13423
+ const settings = await readClaudeSettings();
13424
+ if (!settings.hooks) {
13425
+ settings.hooks = {};
13426
+ }
13427
+ if (!settings.hooks.PostToolUse) {
13428
+ settings.hooks.PostToolUse = [];
13429
+ }
13430
+ let command = "npx --yes mobbdev@latest claude-code-process-hook";
13431
+ if (options.saveEnv) {
13432
+ const envVars = [];
13433
+ if (process.env["WEB_LOGIN_URL"]) {
13434
+ envVars.push(`WEB_LOGIN_URL="${process.env["WEB_LOGIN_URL"]}"`);
13435
+ }
13436
+ if (process.env["WEB_APP_URL"]) {
13437
+ envVars.push(`WEB_APP_URL="${process.env["WEB_APP_URL"]}"`);
13438
+ }
13439
+ if (process.env["API_URL"]) {
13440
+ envVars.push(`API_URL="${process.env["API_URL"]}"`);
13441
+ }
13442
+ if (envVars.length > 0) {
13443
+ command = `${envVars.join(" ")} ${command}`;
13444
+ console.log(
13445
+ chalk10.blue(
13446
+ `Adding environment variables to hook command: ${envVars.join(", ")}`
13447
+ )
13448
+ );
13449
+ }
13450
+ }
13451
+ const mobbHookConfig = {
13452
+ matcher: "Edit|Write",
13453
+ hooks: [
13454
+ {
13455
+ type: "command",
13456
+ command
13457
+ }
13458
+ ]
13459
+ };
13460
+ const existingHookIndex = settings.hooks.PostToolUse.findIndex(
13461
+ (hook) => hook.matcher === "Edit|Write" && hook.hooks.some(
13462
+ (h) => h.command?.includes("mobbdev@latest claude-code-process-hook")
13463
+ )
13464
+ );
13465
+ if (existingHookIndex >= 0) {
13466
+ console.log(chalk10.yellow("Mobb hook already exists, updating..."));
13467
+ settings.hooks.PostToolUse[existingHookIndex] = mobbHookConfig;
13468
+ } else {
13469
+ console.log(chalk10.green("Adding new Mobb hook..."));
13470
+ settings.hooks.PostToolUse.push(mobbHookConfig);
13471
+ }
13472
+ await writeClaudeSettings(settings);
13473
+ console.log(
13474
+ chalk10.green(
13475
+ `\u2705 Mobb hooks ${options.saveEnv ? "and environment variables " : ""}installed successfully in ${CLAUDE_SETTINGS_PATH}`
13476
+ )
13477
+ );
13478
+ }
13479
+
13480
+ // src/args/commands/claude_code.ts
13481
+ var config6 = new Configstore5(packageJson.name, { apiToken: "" });
13482
+ var claudeCodeInstallHookBuilder = (yargs2) => {
13483
+ return yargs2.option("save-env", {
13484
+ type: "boolean",
13485
+ description: "Save WEB_LOGIN_URL, WEB_APP_URL, and API_URL environment variables to hooks config",
13486
+ default: false
13487
+ }).example(
13488
+ "$0 claude-code-install-hook",
13489
+ "Install Claude Code hooks for data collection"
13490
+ ).example(
13491
+ "$0 claude-code-install-hook --save-env",
13492
+ "Install hooks and save environment variables to config"
13493
+ ).strict();
13494
+ };
13495
+ var claudeCodeProcessHookBuilder = (yargs2) => {
13496
+ return yargs2.example(
13497
+ "$0 claude-code-process-hook",
13498
+ "Process Claude Code hook data and upload to backend"
13499
+ ).strict();
13500
+ };
13501
+ var claudeCodeInstallHookHandler = async (argv) => {
13502
+ try {
13503
+ const gqlClient = new GQLClient({
13504
+ apiKey: config6.get("apiToken") ?? "",
13505
+ type: "apiKey"
13506
+ });
13507
+ await handleMobbLogin({
13508
+ inGqlClient: gqlClient,
13509
+ skipPrompts: false
13510
+ });
13511
+ await installMobbHooks({ saveEnv: argv["save-env"] });
13512
+ process.exit(0);
13513
+ } catch (error) {
13514
+ console.error("Failed to install Claude Code hooks:", error);
13515
+ process.exit(1);
13516
+ }
13517
+ };
13518
+ var claudeCodeProcessHookHandler = async () => {
13519
+ try {
13520
+ const { hookData, inference, tracePayload, uploadSuccess } = await processAndUploadHookData();
13521
+ console.log("Successfully processed Claude Code hook:");
13522
+ console.log("Session ID:", hookData.session_id);
13523
+ console.log("Tool:", hookData.tool_name);
13524
+ console.log("Transcript path:", hookData.transcript_path);
13525
+ console.log("Inference length:", inference.length);
13526
+ const userPrompts = tracePayload.prompts.filter(
13527
+ (p) => p.type === "USER_PROMPT"
13528
+ );
13529
+ const assistantResponses = tracePayload.prompts.filter(
13530
+ (p) => p.type === "AI_RESPONSE"
13531
+ );
13532
+ const aiThinking = tracePayload.prompts.filter(
13533
+ (p) => p.type === "AI_THINKING"
13534
+ );
13535
+ console.log("Conversation context extracted:");
13536
+ console.log("- User prompts:", userPrompts.length);
13537
+ console.log("- Assistant responses:", assistantResponses.length);
13538
+ console.log("- AI thinking entries:", aiThinking.length);
13539
+ console.log("- Model:", tracePayload.model);
13540
+ const totalInputTokens = tracePayload.prompts.reduce(
13541
+ (sum, p) => sum + (p.tokens?.inputCount || 0),
13542
+ 0
13543
+ );
13544
+ const totalOutputTokens = tracePayload.prompts.reduce(
13545
+ (sum, p) => sum + (p.tokens?.outputCount || 0),
13546
+ 0
13547
+ );
13548
+ console.log("- Input tokens:", totalInputTokens);
13549
+ console.log("- Output tokens:", totalOutputTokens);
13550
+ console.log("Trace data formatted:");
13551
+ console.log("- Prompt items:", tracePayload.prompts.length);
13552
+ console.log("- Model:", tracePayload.model);
13553
+ console.log("- Tool:", tracePayload.tool);
13554
+ console.log("- Response time:", tracePayload.responseTime);
13555
+ console.log("- Upload success:", uploadSuccess ? "\u2705" : "\u274C");
13556
+ if (uploadSuccess) {
13557
+ console.log("\u2705 Claude Code trace uploaded successfully to Mobb backend");
13558
+ }
13559
+ process.exit(0);
13560
+ } catch (error) {
13561
+ console.error("Failed to process Claude Code hook data:", error);
13562
+ process.exit(1);
13563
+ }
13564
+ };
13565
+
12897
13566
  // src/mcp/core/McpServer.ts
12898
13567
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
12899
13568
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
@@ -12905,7 +13574,7 @@ import {
12905
13574
  } from "@modelcontextprotocol/sdk/types.js";
12906
13575
 
12907
13576
  // src/mcp/Logger.ts
12908
- import Configstore4 from "configstore";
13577
+ import Configstore6 from "configstore";
12909
13578
 
12910
13579
  // src/mcp/services/WorkspaceService.ts
12911
13580
  var WorkspaceService = class {
@@ -12913,8 +13582,8 @@ var WorkspaceService = class {
12913
13582
  * Sets a known workspace path that was discovered through successful validation
12914
13583
  * @param path The validated workspace path to store
12915
13584
  */
12916
- static setKnownWorkspacePath(path21) {
12917
- this.knownWorkspacePath = path21;
13585
+ static setKnownWorkspacePath(path22) {
13586
+ this.knownWorkspacePath = path22;
12918
13587
  }
12919
13588
  /**
12920
13589
  * Gets the known workspace path that was previously validated
@@ -12991,7 +13660,7 @@ var Logger = class {
12991
13660
  __publicField(this, "lastKnownPath", null);
12992
13661
  this.host = WorkspaceService.getHost();
12993
13662
  this.unknownPathSuffix = Math.floor(1e3 + Math.random() * 9e3).toString();
12994
- this.mobbConfigStore = new Configstore4("mobb-logs", {});
13663
+ this.mobbConfigStore = new Configstore6("mobb-logs", {});
12995
13664
  this.mobbConfigStore.set("version", packageJson.version);
12996
13665
  }
12997
13666
  /**
@@ -13061,135 +13730,135 @@ import { v4 as uuidv42 } from "uuid";
13061
13730
  init_configs();
13062
13731
 
13063
13732
  // src/mcp/types.ts
13064
- import { z as z31 } from "zod";
13065
- var ScanAndFixVulnerabilitiesToolSchema = z31.object({
13066
- path: z31.string()
13733
+ import { z as z33 } from "zod";
13734
+ var ScanAndFixVulnerabilitiesToolSchema = z33.object({
13735
+ path: z33.string()
13067
13736
  });
13068
- var VulnerabilityReportIssueTagSchema = z31.object({
13069
- vulnerability_report_issue_tag_value: z31.nativeEnum(
13737
+ var VulnerabilityReportIssueTagSchema = z33.object({
13738
+ vulnerability_report_issue_tag_value: z33.nativeEnum(
13070
13739
  Vulnerability_Report_Issue_Tag_Enum
13071
13740
  )
13072
13741
  });
13073
- var VulnerabilityReportIssueSchema = z31.object({
13074
- category: z31.any().optional().nullable(),
13075
- parsedIssueType: z31.nativeEnum(IssueType_Enum).nullable().optional(),
13076
- parsedSeverity: z31.nativeEnum(Vulnerability_Severity_Enum).nullable().optional(),
13077
- vulnerabilityReportIssueTags: z31.array(VulnerabilityReportIssueTagSchema)
13742
+ var VulnerabilityReportIssueSchema = z33.object({
13743
+ category: z33.any().optional().nullable(),
13744
+ parsedIssueType: z33.nativeEnum(IssueType_Enum).nullable().optional(),
13745
+ parsedSeverity: z33.nativeEnum(Vulnerability_Severity_Enum).nullable().optional(),
13746
+ vulnerabilityReportIssueTags: z33.array(VulnerabilityReportIssueTagSchema)
13078
13747
  });
13079
- var SharedStateSchema = z31.object({
13080
- __typename: z31.literal("fix_shared_state").optional(),
13081
- id: z31.any(),
13748
+ var SharedStateSchema = z33.object({
13749
+ __typename: z33.literal("fix_shared_state").optional(),
13750
+ id: z33.any(),
13082
13751
  // GraphQL uses `any` type for UUID
13083
- downloadedBy: z31.array(z31.any().nullable()).optional().nullable()
13752
+ downloadedBy: z33.array(z33.any().nullable()).optional().nullable()
13084
13753
  });
13085
- var UnstructuredFixExtraContextSchema = z31.object({
13086
- __typename: z31.literal("UnstructuredFixExtraContext").optional(),
13087
- key: z31.string(),
13088
- value: z31.any()
13754
+ var UnstructuredFixExtraContextSchema = z33.object({
13755
+ __typename: z33.literal("UnstructuredFixExtraContext").optional(),
13756
+ key: z33.string(),
13757
+ value: z33.any()
13089
13758
  // GraphQL JSON type
13090
13759
  });
13091
- var FixExtraContextResponseSchema = z31.object({
13092
- __typename: z31.literal("FixExtraContextResponse").optional(),
13093
- extraContext: z31.array(UnstructuredFixExtraContextSchema),
13094
- fixDescription: z31.string()
13760
+ var FixExtraContextResponseSchema = z33.object({
13761
+ __typename: z33.literal("FixExtraContextResponse").optional(),
13762
+ extraContext: z33.array(UnstructuredFixExtraContextSchema),
13763
+ fixDescription: z33.string()
13095
13764
  });
13096
- var FixDataSchema = z31.object({
13097
- __typename: z31.literal("FixData"),
13098
- patch: z31.string(),
13099
- patchOriginalEncodingBase64: z31.string(),
13765
+ var FixDataSchema = z33.object({
13766
+ __typename: z33.literal("FixData"),
13767
+ patch: z33.string(),
13768
+ patchOriginalEncodingBase64: z33.string(),
13100
13769
  extraContext: FixExtraContextResponseSchema
13101
13770
  });
13102
- var GetFixNoFixErrorSchema = z31.object({
13103
- __typename: z31.literal("GetFixNoFixError")
13771
+ var GetFixNoFixErrorSchema = z33.object({
13772
+ __typename: z33.literal("GetFixNoFixError")
13104
13773
  });
13105
- var PatchAndQuestionsSchema = z31.union([FixDataSchema, GetFixNoFixErrorSchema]);
13106
- var McpFixSchema = z31.object({
13107
- __typename: z31.literal("fix").optional(),
13108
- id: z31.any(),
13774
+ var PatchAndQuestionsSchema = z33.union([FixDataSchema, GetFixNoFixErrorSchema]);
13775
+ var McpFixSchema = z33.object({
13776
+ __typename: z33.literal("fix").optional(),
13777
+ id: z33.any(),
13109
13778
  // GraphQL uses `any` type for UUID
13110
- confidence: z31.number(),
13111
- safeIssueType: z31.string().nullable(),
13112
- severityText: z31.string().nullable(),
13113
- gitBlameLogin: z31.string().nullable().optional(),
13779
+ confidence: z33.number(),
13780
+ safeIssueType: z33.string().nullable(),
13781
+ severityText: z33.string().nullable(),
13782
+ gitBlameLogin: z33.string().nullable().optional(),
13114
13783
  // Optional in GraphQL
13115
- severityValue: z31.number().nullable(),
13116
- vulnerabilityReportIssues: z31.array(VulnerabilityReportIssueSchema),
13784
+ severityValue: z33.number().nullable(),
13785
+ vulnerabilityReportIssues: z33.array(VulnerabilityReportIssueSchema),
13117
13786
  sharedState: SharedStateSchema.nullable().optional(),
13118
13787
  // Optional in GraphQL
13119
13788
  patchAndQuestions: PatchAndQuestionsSchema,
13120
13789
  // Additional field added by the client
13121
- fixUrl: z31.string().optional()
13790
+ fixUrl: z33.string().optional()
13122
13791
  });
13123
- var FixAggregateSchema = z31.object({
13124
- __typename: z31.literal("fix_aggregate").optional(),
13125
- aggregate: z31.object({
13126
- __typename: z31.literal("fix_aggregate_fields").optional(),
13127
- count: z31.number()
13792
+ var FixAggregateSchema = z33.object({
13793
+ __typename: z33.literal("fix_aggregate").optional(),
13794
+ aggregate: z33.object({
13795
+ __typename: z33.literal("fix_aggregate_fields").optional(),
13796
+ count: z33.number()
13128
13797
  }).nullable()
13129
13798
  });
13130
- var VulnerabilityReportIssueAggregateSchema = z31.object({
13131
- __typename: z31.literal("vulnerability_report_issue_aggregate").optional(),
13132
- aggregate: z31.object({
13133
- __typename: z31.literal("vulnerability_report_issue_aggregate_fields").optional(),
13134
- count: z31.number()
13799
+ var VulnerabilityReportIssueAggregateSchema = z33.object({
13800
+ __typename: z33.literal("vulnerability_report_issue_aggregate").optional(),
13801
+ aggregate: z33.object({
13802
+ __typename: z33.literal("vulnerability_report_issue_aggregate_fields").optional(),
13803
+ count: z33.number()
13135
13804
  }).nullable()
13136
13805
  });
13137
- var RepoSchema = z31.object({
13138
- __typename: z31.literal("repo").optional(),
13139
- originalUrl: z31.string()
13806
+ var RepoSchema = z33.object({
13807
+ __typename: z33.literal("repo").optional(),
13808
+ originalUrl: z33.string()
13140
13809
  });
13141
- var ProjectSchema = z31.object({
13142
- id: z31.any(),
13810
+ var ProjectSchema = z33.object({
13811
+ id: z33.any(),
13143
13812
  // GraphQL uses `any` type for UUID
13144
- organizationId: z31.any()
13813
+ organizationId: z33.any()
13145
13814
  // GraphQL uses `any` type for UUID
13146
13815
  });
13147
- var VulnerabilityReportSchema = z31.object({
13148
- scanDate: z31.any().nullable(),
13816
+ var VulnerabilityReportSchema = z33.object({
13817
+ scanDate: z33.any().nullable(),
13149
13818
  // GraphQL uses `any` type for timestamp
13150
- vendor: z31.string(),
13819
+ vendor: z33.string(),
13151
13820
  // GraphQL generates as string, not enum
13152
- projectId: z31.any().optional(),
13821
+ projectId: z33.any().optional(),
13153
13822
  // GraphQL uses `any` type for UUID
13154
13823
  project: ProjectSchema,
13155
13824
  totalVulnerabilityReportIssuesCount: VulnerabilityReportIssueAggregateSchema,
13156
13825
  notFixableVulnerabilityReportIssuesCount: VulnerabilityReportIssueAggregateSchema
13157
13826
  });
13158
- var FixReportSummarySchema = z31.object({
13159
- __typename: z31.literal("fixReport").optional(),
13160
- id: z31.any(),
13827
+ var FixReportSummarySchema = z33.object({
13828
+ __typename: z33.literal("fixReport").optional(),
13829
+ id: z33.any(),
13161
13830
  // GraphQL uses `any` type for UUID
13162
- createdOn: z31.any(),
13831
+ createdOn: z33.any(),
13163
13832
  // GraphQL uses `any` type for timestamp
13164
13833
  repo: RepoSchema.nullable(),
13165
- issueTypes: z31.any().nullable(),
13834
+ issueTypes: z33.any().nullable(),
13166
13835
  // GraphQL uses `any` type for JSON
13167
13836
  CRITICAL: FixAggregateSchema,
13168
13837
  HIGH: FixAggregateSchema,
13169
13838
  MEDIUM: FixAggregateSchema,
13170
13839
  LOW: FixAggregateSchema,
13171
- fixes: z31.array(McpFixSchema),
13172
- userFixes: z31.array(McpFixSchema).optional(),
13840
+ fixes: z33.array(McpFixSchema),
13841
+ userFixes: z33.array(McpFixSchema).optional(),
13173
13842
  // Present in some responses but can be omitted
13174
13843
  filteredFixesCount: FixAggregateSchema,
13175
13844
  totalFixesCount: FixAggregateSchema,
13176
13845
  vulnerabilityReport: VulnerabilityReportSchema
13177
13846
  });
13178
- var ExpiredReportSchema = z31.object({
13179
- __typename: z31.literal("fixReport").optional(),
13180
- id: z31.any(),
13847
+ var ExpiredReportSchema = z33.object({
13848
+ __typename: z33.literal("fixReport").optional(),
13849
+ id: z33.any(),
13181
13850
  // GraphQL uses `any` type for UUID
13182
- expirationOn: z31.any().nullable()
13851
+ expirationOn: z33.any().nullable()
13183
13852
  // GraphQL uses `any` type for timestamp
13184
13853
  });
13185
- var GetLatestReportByRepoUrlResponseSchema = z31.object({
13186
- __typename: z31.literal("query_root").optional(),
13187
- fixReport: z31.array(FixReportSummarySchema),
13188
- expiredReport: z31.array(ExpiredReportSchema)
13854
+ var GetLatestReportByRepoUrlResponseSchema = z33.object({
13855
+ __typename: z33.literal("query_root").optional(),
13856
+ fixReport: z33.array(FixReportSummarySchema),
13857
+ expiredReport: z33.array(ExpiredReportSchema)
13189
13858
  });
13190
13859
 
13191
13860
  // src/mcp/services/ConfigStoreService.ts
13192
- import Configstore5 from "configstore";
13861
+ import Configstore7 from "configstore";
13193
13862
  init_configs();
13194
13863
  function createConfigStore(defaultValues = { apiToken: "" }) {
13195
13864
  const API_URL2 = process.env["API_URL"] || MCP_DEFAULT_API_URL;
@@ -13201,7 +13870,7 @@ function createConfigStore(defaultValues = { apiToken: "" }) {
13201
13870
  domain = API_URL2.replace(/^https?:\/\//, "").replace(/\/.*$/, "").replace(/:\d+$/, "");
13202
13871
  }
13203
13872
  const sanitizedDomain = domain.replace(/\./g, "_");
13204
- return new Configstore5(
13873
+ return new Configstore7(
13205
13874
  `${packageJson.name}-${sanitizedDomain}`,
13206
13875
  defaultValues
13207
13876
  );
@@ -13213,7 +13882,7 @@ var configStore = getConfigStore();
13213
13882
 
13214
13883
  // src/mcp/services/McpAuthService.ts
13215
13884
  import crypto2 from "crypto";
13216
- import os2 from "os";
13885
+ import os3 from "os";
13217
13886
  import open4 from "open";
13218
13887
  init_configs();
13219
13888
  var McpAuthService = class {
@@ -13257,7 +13926,7 @@ var McpAuthService = class {
13257
13926
  }
13258
13927
  logDebug(`cli login created ${loginId}`);
13259
13928
  const webLoginUrl2 = `${WEB_APP_URL}/mvs-login`;
13260
- const browserUrl = `${webLoginUrl2}/${loginId}?hostname=${os2.hostname()}`;
13929
+ const browserUrl = `${webLoginUrl2}/${loginId}?hostname=${os3.hostname()}`;
13261
13930
  await this.openBrowser(browserUrl, isBackgoundCall);
13262
13931
  logDebug(`waiting for login to complete`);
13263
13932
  let newApiToken = null;
@@ -13918,8 +14587,8 @@ async function createAuthenticatedMcpGQLClient({
13918
14587
  // src/mcp/services/McpUsageService/host.ts
13919
14588
  import { execSync } from "child_process";
13920
14589
  import fs11 from "fs";
13921
- import os3 from "os";
13922
- import path11 from "path";
14590
+ import os4 from "os";
14591
+ import path13 from "path";
13923
14592
  var IDEs = ["cursor", "windsurf", "webstorm", "vscode", "claude"];
13924
14593
  var runCommand = (cmd) => {
13925
14594
  try {
@@ -13933,8 +14602,8 @@ var gitInfo = {
13933
14602
  email: runCommand("git config user.email")
13934
14603
  };
13935
14604
  var getClaudeWorkspacePaths = () => {
13936
- const home = os3.homedir();
13937
- const claudeIdePath = path11.join(home, ".claude", "ide");
14605
+ const home = os4.homedir();
14606
+ const claudeIdePath = path13.join(home, ".claude", "ide");
13938
14607
  const workspacePaths = [];
13939
14608
  if (!fs11.existsSync(claudeIdePath)) {
13940
14609
  return workspacePaths;
@@ -13942,7 +14611,7 @@ var getClaudeWorkspacePaths = () => {
13942
14611
  try {
13943
14612
  const lockFiles = fs11.readdirSync(claudeIdePath).filter((file) => file.endsWith(".lock"));
13944
14613
  for (const lockFile of lockFiles) {
13945
- const lockFilePath = path11.join(claudeIdePath, lockFile);
14614
+ const lockFilePath = path13.join(claudeIdePath, lockFile);
13946
14615
  try {
13947
14616
  const lockContent = JSON.parse(fs11.readFileSync(lockFilePath, "utf8"));
13948
14617
  if (lockContent.workspaceFolders && Array.isArray(lockContent.workspaceFolders)) {
@@ -13962,29 +14631,29 @@ var getClaudeWorkspacePaths = () => {
13962
14631
  return workspacePaths;
13963
14632
  };
13964
14633
  var getMCPConfigPaths = (hostName) => {
13965
- const home = os3.homedir();
14634
+ const home = os4.homedir();
13966
14635
  const currentDir = process.env["WORKSPACE_FOLDER_PATHS"] || process.env["PWD"] || process.cwd();
13967
14636
  switch (hostName.toLowerCase()) {
13968
14637
  case "cursor":
13969
14638
  return [
13970
- path11.join(currentDir, ".cursor", "mcp.json"),
14639
+ path13.join(currentDir, ".cursor", "mcp.json"),
13971
14640
  // local first
13972
- path11.join(home, ".cursor", "mcp.json")
14641
+ path13.join(home, ".cursor", "mcp.json")
13973
14642
  ];
13974
14643
  case "windsurf":
13975
14644
  return [
13976
- path11.join(currentDir, ".codeium", "mcp_config.json"),
14645
+ path13.join(currentDir, ".codeium", "mcp_config.json"),
13977
14646
  // local first
13978
- path11.join(home, ".codeium", "windsurf", "mcp_config.json")
14647
+ path13.join(home, ".codeium", "windsurf", "mcp_config.json")
13979
14648
  ];
13980
14649
  case "webstorm":
13981
14650
  return [];
13982
14651
  case "visualstudiocode":
13983
14652
  case "vscode":
13984
14653
  return [
13985
- path11.join(currentDir, ".vscode", "mcp.json"),
14654
+ path13.join(currentDir, ".vscode", "mcp.json"),
13986
14655
  // local first
13987
- process.platform === "win32" ? path11.join(home, "AppData", "Roaming", "Code", "User", "mcp.json") : path11.join(
14656
+ process.platform === "win32" ? path13.join(home, "AppData", "Roaming", "Code", "User", "mcp.json") : path13.join(
13988
14657
  home,
13989
14658
  "Library",
13990
14659
  "Application Support",
@@ -13995,13 +14664,13 @@ var getMCPConfigPaths = (hostName) => {
13995
14664
  ];
13996
14665
  case "claude": {
13997
14666
  const claudePaths = [
13998
- path11.join(currentDir, ".claude.json"),
14667
+ path13.join(currentDir, ".claude.json"),
13999
14668
  // local first
14000
- path11.join(home, ".claude.json")
14669
+ path13.join(home, ".claude.json")
14001
14670
  ];
14002
14671
  const workspacePaths = getClaudeWorkspacePaths();
14003
14672
  for (const workspacePath of workspacePaths) {
14004
- claudePaths.push(path11.join(workspacePath, ".mcp.json"));
14673
+ claudePaths.push(path13.join(workspacePath, ".mcp.json"));
14005
14674
  }
14006
14675
  return claudePaths;
14007
14676
  }
@@ -14018,41 +14687,41 @@ var readConfigFile = (filePath) => {
14018
14687
  return null;
14019
14688
  }
14020
14689
  };
14021
- var mergeConfigIntoResult = (config6, mergedConfig) => {
14022
- if (config6?.projects) {
14690
+ var mergeConfigIntoResult = (config7, mergedConfig) => {
14691
+ if (config7?.projects) {
14023
14692
  const allMcpServers = {};
14024
- for (const projectPath in config6.projects) {
14025
- const project = config6.projects[projectPath];
14693
+ for (const projectPath in config7.projects) {
14694
+ const project = config7.projects[projectPath];
14026
14695
  if (project?.mcpServers) {
14027
14696
  Object.assign(allMcpServers, project.mcpServers);
14028
14697
  }
14029
14698
  }
14030
14699
  mergedConfig.mcpServers = { ...mergedConfig.mcpServers, ...allMcpServers };
14031
14700
  }
14032
- if (config6?.mcpServers) {
14701
+ if (config7?.mcpServers) {
14033
14702
  mergedConfig.mcpServers = {
14034
14703
  ...mergedConfig.mcpServers,
14035
- ...config6.mcpServers
14704
+ ...config7.mcpServers
14036
14705
  };
14037
14706
  }
14038
- if (config6?.servers) {
14039
- mergedConfig.servers = { ...mergedConfig.servers, ...config6.servers };
14707
+ if (config7?.servers) {
14708
+ mergedConfig.servers = { ...mergedConfig.servers, ...config7.servers };
14040
14709
  }
14041
14710
  };
14042
14711
  var readMCPConfig = (hostName) => {
14043
14712
  const configPaths = getMCPConfigPaths(hostName);
14044
14713
  const mergedConfig = {};
14045
14714
  for (const configPath of configPaths) {
14046
- const config6 = readConfigFile(configPath);
14047
- if (config6) {
14048
- mergeConfigIntoResult(config6, mergedConfig);
14715
+ const config7 = readConfigFile(configPath);
14716
+ if (config7) {
14717
+ mergeConfigIntoResult(config7, mergedConfig);
14049
14718
  }
14050
14719
  }
14051
14720
  return Object.keys(mergedConfig).length > 0 ? mergedConfig : null;
14052
14721
  };
14053
14722
  var getRunningProcesses = () => {
14054
14723
  try {
14055
- return os3.platform() === "win32" ? execSync("tasklist", { encoding: "utf8" }) : execSync("ps aux", { encoding: "utf8" });
14724
+ return os4.platform() === "win32" ? execSync("tasklist", { encoding: "utf8" }) : execSync("ps aux", { encoding: "utf8" });
14056
14725
  } catch {
14057
14726
  return "";
14058
14727
  }
@@ -14127,7 +14796,7 @@ var versionCommands = {
14127
14796
  }
14128
14797
  };
14129
14798
  var getProcessInfo = (pid) => {
14130
- const platform2 = os3.platform();
14799
+ const platform2 = os4.platform();
14131
14800
  try {
14132
14801
  if (platform2 === "linux" || platform2 === "darwin") {
14133
14802
  const output = execSync(`ps -o pid=,ppid=,comm= -p ${pid}`, {
@@ -14162,20 +14831,20 @@ var getHostInfo = (additionalMcpList) => {
14162
14831
  const ideConfigPaths = /* @__PURE__ */ new Set();
14163
14832
  for (const ide of IDEs) {
14164
14833
  const configPaths = getMCPConfigPaths(ide);
14165
- configPaths.forEach((path21) => ideConfigPaths.add(path21));
14834
+ configPaths.forEach((path22) => ideConfigPaths.add(path22));
14166
14835
  }
14167
14836
  const uniqueAdditionalPaths = additionalMcpList.filter(
14168
- (path21) => !ideConfigPaths.has(path21)
14837
+ (path22) => !ideConfigPaths.has(path22)
14169
14838
  );
14170
14839
  for (const ide of IDEs) {
14171
14840
  const cfg = readMCPConfig(ide);
14172
14841
  if (cfg) allConfigs[ide] = cfg;
14173
14842
  }
14174
14843
  for (const additionalPath of uniqueAdditionalPaths) {
14175
- const config6 = readConfigFile(additionalPath);
14176
- if (!config6) continue;
14844
+ const config7 = readConfigFile(additionalPath);
14845
+ if (!config7) continue;
14177
14846
  const mergedConfig = {};
14178
- mergeConfigIntoResult(config6, mergedConfig);
14847
+ mergeConfigIntoResult(config7, mergedConfig);
14179
14848
  if (Object.keys(mergedConfig).length > 0) {
14180
14849
  allConfigs["system"] = mergedConfig;
14181
14850
  }
@@ -14243,10 +14912,10 @@ var getHostInfo = (additionalMcpList) => {
14243
14912
  }
14244
14913
  }
14245
14914
  for (const { ide, name, command, isRunning } of servers) {
14246
- const config6 = allConfigs[ide] || null;
14915
+ const config7 = allConfigs[ide] || null;
14247
14916
  const ideName = ide.charAt(0).toUpperCase() + ide.slice(1) || "Unknown";
14248
14917
  let ideVersion = "Unknown";
14249
- const platform2 = os3.platform();
14918
+ const platform2 = os4.platform();
14250
14919
  const cmds = versionCommands[ideName]?.[platform2] ?? [];
14251
14920
  for (const cmd of cmds) {
14252
14921
  try {
@@ -14260,8 +14929,8 @@ var getHostInfo = (additionalMcpList) => {
14260
14929
  }
14261
14930
  }
14262
14931
  let mcpConfigObj = {};
14263
- if (config6) {
14264
- const allServers = config6.mcpServers || config6.servers || {};
14932
+ if (config7) {
14933
+ const allServers = config7.mcpServers || config7.servers || {};
14265
14934
  if (name in allServers && allServers[name]) {
14266
14935
  mcpConfigObj = allServers[name];
14267
14936
  }
@@ -14279,15 +14948,15 @@ var getHostInfo = (additionalMcpList) => {
14279
14948
 
14280
14949
  // src/mcp/services/McpUsageService/McpUsageService.ts
14281
14950
  import fetch5 from "node-fetch";
14282
- import os5 from "os";
14951
+ import os6 from "os";
14283
14952
  import { v4 as uuidv43, v5 as uuidv5 } from "uuid";
14284
14953
  init_configs();
14285
14954
 
14286
14955
  // src/mcp/services/McpUsageService/system.ts
14287
14956
  init_configs();
14288
14957
  import fs12 from "fs";
14289
- import os4 from "os";
14290
- import path12 from "path";
14958
+ import os5 from "os";
14959
+ import path14 from "path";
14291
14960
  var MAX_DEPTH = 2;
14292
14961
  var patterns = ["mcp", "claude"];
14293
14962
  var isFileMatch = (fileName) => {
@@ -14307,7 +14976,7 @@ var searchDir = async (dir, depth = 0) => {
14307
14976
  if (depth > MAX_DEPTH) return results;
14308
14977
  const entries = await fs12.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
14309
14978
  for (const entry of entries) {
14310
- const fullPath = path12.join(dir, entry.name);
14979
+ const fullPath = path14.join(dir, entry.name);
14311
14980
  if (entry.isFile() && isFileMatch(entry.name)) {
14312
14981
  results.push(fullPath);
14313
14982
  } else if (entry.isDirectory()) {
@@ -14321,17 +14990,17 @@ var searchDir = async (dir, depth = 0) => {
14321
14990
  };
14322
14991
  var findSystemMCPConfigs = async () => {
14323
14992
  try {
14324
- const home = os4.homedir();
14325
- const platform2 = os4.platform();
14993
+ const home = os5.homedir();
14994
+ const platform2 = os5.platform();
14326
14995
  const knownDirs = platform2 === "win32" ? [
14327
- path12.join(home, ".cursor"),
14328
- path12.join(home, "Documents"),
14329
- path12.join(home, "Downloads")
14996
+ path14.join(home, ".cursor"),
14997
+ path14.join(home, "Documents"),
14998
+ path14.join(home, "Downloads")
14330
14999
  ] : [
14331
- path12.join(home, ".cursor"),
14332
- process.env["XDG_CONFIG_HOME"] || path12.join(home, ".config"),
14333
- path12.join(home, "Documents"),
14334
- path12.join(home, "Downloads")
15000
+ path14.join(home, ".cursor"),
15001
+ process.env["XDG_CONFIG_HOME"] || path14.join(home, ".config"),
15002
+ path14.join(home, "Documents"),
15003
+ path14.join(home, "Downloads")
14335
15004
  ];
14336
15005
  const timeoutPromise = new Promise(
14337
15006
  (resolve) => setTimeout(() => {
@@ -14394,7 +15063,7 @@ var McpUsageService = class {
14394
15063
  generateHostId() {
14395
15064
  const stored = configStore.get(this.configKey);
14396
15065
  if (stored?.mcpHostId) return stored.mcpHostId;
14397
- const interfaces = os5.networkInterfaces();
15066
+ const interfaces = os6.networkInterfaces();
14398
15067
  const macs = [];
14399
15068
  for (const iface of Object.values(interfaces)) {
14400
15069
  if (!iface) continue;
@@ -14402,7 +15071,7 @@ var McpUsageService = class {
14402
15071
  if (net.mac && net.mac !== "00:00:00:00:00:00") macs.push(net.mac);
14403
15072
  }
14404
15073
  }
14405
- const macString = macs.length ? macs.sort().join(",") : `${os5.hostname()}-${uuidv43()}`;
15074
+ const macString = macs.length ? macs.sort().join(",") : `${os6.hostname()}-${uuidv43()}`;
14406
15075
  const hostId = uuidv5(macString, uuidv5.DNS);
14407
15076
  logDebug("[UsageService] Generated new host ID", { hostId });
14408
15077
  return hostId;
@@ -14425,7 +15094,7 @@ var McpUsageService = class {
14425
15094
  mcpHostId,
14426
15095
  organizationId,
14427
15096
  mcpVersion: packageJson.version,
14428
- mcpOsName: os5.platform(),
15097
+ mcpOsName: os6.platform(),
14429
15098
  mcps: JSON.stringify(mcps),
14430
15099
  status,
14431
15100
  userName: user.name,
@@ -14599,7 +15268,7 @@ var ToolRegistry = class {
14599
15268
 
14600
15269
  // src/mcp/core/McpServer.ts
14601
15270
  var McpServer = class {
14602
- constructor(config6, govOrgId = "") {
15271
+ constructor(config7, govOrgId = "") {
14603
15272
  __publicField(this, "server");
14604
15273
  __publicField(this, "toolRegistry");
14605
15274
  __publicField(this, "promptRegistry");
@@ -14613,8 +15282,8 @@ var McpServer = class {
14613
15282
  this.mcpUsageService = govOrgId ? new McpUsageService(govOrgId) : null;
14614
15283
  this.server = new Server(
14615
15284
  {
14616
- name: config6.name,
14617
- version: config6.version
15285
+ name: config7.name,
15286
+ version: config7.version
14618
15287
  },
14619
15288
  {
14620
15289
  capabilities: {
@@ -14630,7 +15299,7 @@ var McpServer = class {
14630
15299
  this.setupParentProcessMonitoring();
14631
15300
  logInfo("MCP server instance created");
14632
15301
  logDebug("MCP server instance config", {
14633
- config: config6,
15302
+ config: config7,
14634
15303
  parentPid: this.parentPid
14635
15304
  });
14636
15305
  }
@@ -15088,10 +15757,10 @@ var McpServer = class {
15088
15757
  };
15089
15758
 
15090
15759
  // src/mcp/prompts/CheckForNewVulnerabilitiesPrompt.ts
15091
- import { z as z33 } from "zod";
15760
+ import { z as z35 } from "zod";
15092
15761
 
15093
15762
  // src/mcp/prompts/base/BasePrompt.ts
15094
- import { z as z32 } from "zod";
15763
+ import { z as z34 } from "zod";
15095
15764
  var BasePrompt = class {
15096
15765
  getDefinition() {
15097
15766
  return {
@@ -15120,7 +15789,7 @@ var BasePrompt = class {
15120
15789
  const argsToValidate = args === void 0 ? {} : args;
15121
15790
  return this.argumentsValidationSchema.parse(argsToValidate);
15122
15791
  } catch (error) {
15123
- if (error instanceof z32.ZodError) {
15792
+ if (error instanceof z34.ZodError) {
15124
15793
  const errorDetails = error.errors.map((e) => {
15125
15794
  const fieldPath = e.path.length > 0 ? e.path.join(".") : "root";
15126
15795
  const message = e.message === "Required" ? `Missing required argument '${fieldPath}'` : `Invalid value for '${fieldPath}': ${e.message}`;
@@ -15149,8 +15818,8 @@ var BasePrompt = class {
15149
15818
  };
15150
15819
 
15151
15820
  // src/mcp/prompts/CheckForNewVulnerabilitiesPrompt.ts
15152
- var CheckForNewVulnerabilitiesArgsSchema = z33.object({
15153
- path: z33.string().optional()
15821
+ var CheckForNewVulnerabilitiesArgsSchema = z35.object({
15822
+ path: z35.string().optional()
15154
15823
  });
15155
15824
  var CheckForNewVulnerabilitiesPrompt = class extends BasePrompt {
15156
15825
  constructor() {
@@ -15395,9 +16064,9 @@ Call the \`check_for_new_available_fixes\` tool now${args?.path ? ` for ${args.p
15395
16064
  };
15396
16065
 
15397
16066
  // src/mcp/prompts/FullSecurityAuditPrompt.ts
15398
- import { z as z34 } from "zod";
15399
- var FullSecurityAuditArgsSchema = z34.object({
15400
- path: z34.string().optional()
16067
+ import { z as z36 } from "zod";
16068
+ var FullSecurityAuditArgsSchema = z36.object({
16069
+ path: z36.string().optional()
15401
16070
  });
15402
16071
  var FullSecurityAuditPrompt = class extends BasePrompt {
15403
16072
  constructor() {
@@ -15848,9 +16517,9 @@ Begin the audit now${args?.path ? ` for ${args.path}` : ""}.
15848
16517
  };
15849
16518
 
15850
16519
  // src/mcp/prompts/ReviewAndFixCriticalPrompt.ts
15851
- import { z as z35 } from "zod";
15852
- var ReviewAndFixCriticalArgsSchema = z35.object({
15853
- path: z35.string().optional()
16520
+ import { z as z37 } from "zod";
16521
+ var ReviewAndFixCriticalArgsSchema = z37.object({
16522
+ path: z37.string().optional()
15854
16523
  });
15855
16524
  var ReviewAndFixCriticalPrompt = class extends BasePrompt {
15856
16525
  constructor() {
@@ -16154,9 +16823,9 @@ Start by scanning${args?.path ? ` ${args.path}` : " the repository"} and priorit
16154
16823
  };
16155
16824
 
16156
16825
  // src/mcp/prompts/ScanRecentChangesPrompt.ts
16157
- import { z as z36 } from "zod";
16158
- var ScanRecentChangesArgsSchema = z36.object({
16159
- path: z36.string().optional()
16826
+ import { z as z38 } from "zod";
16827
+ var ScanRecentChangesArgsSchema = z38.object({
16828
+ path: z38.string().optional()
16160
16829
  });
16161
16830
  var ScanRecentChangesPrompt = class extends BasePrompt {
16162
16831
  constructor() {
@@ -16367,9 +17036,9 @@ You now have the guidance needed to perform a fast, targeted security scan of re
16367
17036
  };
16368
17037
 
16369
17038
  // src/mcp/prompts/ScanRepositoryPrompt.ts
16370
- import { z as z37 } from "zod";
16371
- var ScanRepositoryArgsSchema = z37.object({
16372
- path: z37.string().optional()
17039
+ import { z as z39 } from "zod";
17040
+ var ScanRepositoryArgsSchema = z39.object({
17041
+ path: z39.string().optional()
16373
17042
  });
16374
17043
  var ScanRepositoryPrompt = class extends BasePrompt {
16375
17044
  constructor() {
@@ -16748,30 +17417,30 @@ For a complete security audit workflow, use the \`full-security-audit\` prompt.
16748
17417
 
16749
17418
  // src/mcp/services/McpDetectionService/CursorMcpDetectionService.ts
16750
17419
  import * as fs15 from "fs";
16751
- import * as os7 from "os";
16752
- import * as path14 from "path";
17420
+ import * as os8 from "os";
17421
+ import * as path16 from "path";
16753
17422
 
16754
17423
  // src/mcp/services/McpDetectionService/BaseMcpDetectionService.ts
16755
17424
  init_configs();
16756
17425
  import * as fs14 from "fs";
16757
17426
  import fetch6 from "node-fetch";
16758
- import * as path13 from "path";
17427
+ import * as path15 from "path";
16759
17428
 
16760
17429
  // src/mcp/services/McpDetectionService/McpDetectionServiceUtils.ts
16761
17430
  import * as fs13 from "fs";
16762
- import * as os6 from "os";
17431
+ import * as os7 from "os";
16763
17432
 
16764
17433
  // src/mcp/services/McpDetectionService/VscodeMcpDetectionService.ts
16765
17434
  import * as fs16 from "fs";
16766
- import * as os8 from "os";
16767
- import * as path15 from "path";
17435
+ import * as os9 from "os";
17436
+ import * as path17 from "path";
16768
17437
 
16769
17438
  // src/mcp/tools/checkForNewAvailableFixes/CheckForNewAvailableFixesTool.ts
16770
- import { z as z40 } from "zod";
17439
+ import { z as z42 } from "zod";
16771
17440
 
16772
17441
  // src/mcp/services/PathValidation.ts
16773
17442
  import fs17 from "fs";
16774
- import path16 from "path";
17443
+ import path18 from "path";
16775
17444
  async function validatePath(inputPath) {
16776
17445
  logDebug("Validating MCP path", { inputPath });
16777
17446
  if (/^\/[a-zA-Z]:\//.test(inputPath)) {
@@ -16803,7 +17472,7 @@ async function validatePath(inputPath) {
16803
17472
  logError(error);
16804
17473
  return { isValid: false, error, path: inputPath };
16805
17474
  }
16806
- const normalizedPath = path16.normalize(inputPath);
17475
+ const normalizedPath = path18.normalize(inputPath);
16807
17476
  if (normalizedPath.includes("..")) {
16808
17477
  const error = `Normalized path contains path traversal patterns: ${inputPath}`;
16809
17478
  logError(error);
@@ -16843,7 +17512,7 @@ async function validatePath(inputPath) {
16843
17512
  }
16844
17513
 
16845
17514
  // src/mcp/tools/base/BaseTool.ts
16846
- import { z as z38 } from "zod";
17515
+ import { z as z40 } from "zod";
16847
17516
  var BaseTool = class {
16848
17517
  getDefinition() {
16849
17518
  return {
@@ -16873,7 +17542,7 @@ var BaseTool = class {
16873
17542
  try {
16874
17543
  return this.inputValidationSchema.parse(args);
16875
17544
  } catch (error) {
16876
- if (error instanceof z38.ZodError) {
17545
+ if (error instanceof z40.ZodError) {
16877
17546
  const errorDetails = error.errors.map((e) => {
16878
17547
  const fieldPath = e.path.length > 0 ? e.path.join(".") : "root";
16879
17548
  const message = e.message === "Required" ? `Missing required parameter '${fieldPath}'` : `Invalid value for '${fieldPath}': ${e.message}`;
@@ -17457,7 +18126,7 @@ init_configs();
17457
18126
  import fs18 from "fs/promises";
17458
18127
  import nodePath from "path";
17459
18128
  var getLocalFiles = async ({
17460
- path: path21,
18129
+ path: path22,
17461
18130
  maxFileSize = MCP_MAX_FILE_SIZE,
17462
18131
  maxFiles,
17463
18132
  isAllFilesScan,
@@ -17465,17 +18134,17 @@ var getLocalFiles = async ({
17465
18134
  scanRecentlyChangedFiles
17466
18135
  }) => {
17467
18136
  logDebug(`[${scanContext}] Starting getLocalFiles`, {
17468
- path: path21,
18137
+ path: path22,
17469
18138
  maxFileSize,
17470
18139
  maxFiles,
17471
18140
  isAllFilesScan,
17472
18141
  scanRecentlyChangedFiles
17473
18142
  });
17474
18143
  try {
17475
- const resolvedRepoPath = await fs18.realpath(path21);
18144
+ const resolvedRepoPath = await fs18.realpath(path22);
17476
18145
  logDebug(`[${scanContext}] Resolved repository path`, {
17477
18146
  resolvedRepoPath,
17478
- originalPath: path21
18147
+ originalPath: path22
17479
18148
  });
17480
18149
  const gitService = new GitService(resolvedRepoPath, log);
17481
18150
  const gitValidation = await gitService.validateRepository();
@@ -17488,7 +18157,7 @@ var getLocalFiles = async ({
17488
18157
  if (!gitValidation.isValid || isAllFilesScan) {
17489
18158
  try {
17490
18159
  files = await FileUtils.getLastChangedFiles({
17491
- dir: path21,
18160
+ dir: path22,
17492
18161
  maxFileSize,
17493
18162
  maxFiles,
17494
18163
  isAllFilesScan
@@ -17580,7 +18249,7 @@ var getLocalFiles = async ({
17580
18249
  logError(`${scanContext}Unexpected error in getLocalFiles`, {
17581
18250
  error: error instanceof Error ? error.message : String(error),
17582
18251
  stack: error instanceof Error ? error.stack : void 0,
17583
- path: path21
18252
+ path: path22
17584
18253
  });
17585
18254
  throw error;
17586
18255
  }
@@ -17588,15 +18257,15 @@ var getLocalFiles = async ({
17588
18257
 
17589
18258
  // src/mcp/services/LocalMobbFolderService.ts
17590
18259
  import fs19 from "fs";
17591
- import path17 from "path";
17592
- import { z as z39 } from "zod";
18260
+ import path19 from "path";
18261
+ import { z as z41 } from "zod";
17593
18262
  init_GitService();
17594
18263
  function extractPathFromPatch(patch) {
17595
18264
  const match = patch?.match(/diff --git a\/([^\s]+) b\//);
17596
18265
  return match?.[1] ?? null;
17597
18266
  }
17598
18267
  function parsedIssueTypeRes(issueType) {
17599
- return z39.nativeEnum(IssueType_Enum).safeParse(issueType);
18268
+ return z41.nativeEnum(IssueType_Enum).safeParse(issueType);
17600
18269
  }
17601
18270
  var LocalMobbFolderService = class {
17602
18271
  /**
@@ -17675,7 +18344,7 @@ var LocalMobbFolderService = class {
17675
18344
  "[LocalMobbFolderService] Non-git repository detected, skipping .gitignore operations"
17676
18345
  );
17677
18346
  }
17678
- const mobbFolderPath = path17.join(
18347
+ const mobbFolderPath = path19.join(
17679
18348
  this.repoPath,
17680
18349
  this.defaultMobbFolderName
17681
18350
  );
@@ -17847,7 +18516,7 @@ var LocalMobbFolderService = class {
17847
18516
  mobbFolderPath,
17848
18517
  baseFileName
17849
18518
  );
17850
- const filePath = path17.join(mobbFolderPath, uniqueFileName);
18519
+ const filePath = path19.join(mobbFolderPath, uniqueFileName);
17851
18520
  await fs19.promises.writeFile(filePath, patch, "utf8");
17852
18521
  logInfo("[LocalMobbFolderService] Patch saved successfully", {
17853
18522
  filePath,
@@ -17905,11 +18574,11 @@ var LocalMobbFolderService = class {
17905
18574
  * @returns Unique filename that doesn't conflict with existing files
17906
18575
  */
17907
18576
  getUniqueFileName(folderPath, baseFileName) {
17908
- const baseName = path17.parse(baseFileName).name;
17909
- const extension = path17.parse(baseFileName).ext;
18577
+ const baseName = path19.parse(baseFileName).name;
18578
+ const extension = path19.parse(baseFileName).ext;
17910
18579
  let uniqueFileName = baseFileName;
17911
18580
  let index = 1;
17912
- while (fs19.existsSync(path17.join(folderPath, uniqueFileName))) {
18581
+ while (fs19.existsSync(path19.join(folderPath, uniqueFileName))) {
17913
18582
  uniqueFileName = `${baseName}-${index}${extension}`;
17914
18583
  index++;
17915
18584
  if (index > 1e3) {
@@ -17940,7 +18609,7 @@ var LocalMobbFolderService = class {
17940
18609
  logDebug("[LocalMobbFolderService] Logging patch info", { fixId: fix.id });
17941
18610
  try {
17942
18611
  const mobbFolderPath = await this.getFolder();
17943
- const patchInfoPath = path17.join(mobbFolderPath, "patchInfo.md");
18612
+ const patchInfoPath = path19.join(mobbFolderPath, "patchInfo.md");
17944
18613
  const markdownContent = this.generateFixMarkdown(fix, savedPatchFileName);
17945
18614
  let existingContent = "";
17946
18615
  if (fs19.existsSync(patchInfoPath)) {
@@ -17982,7 +18651,7 @@ var LocalMobbFolderService = class {
17982
18651
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
17983
18652
  const patch = this.extractPatchFromFix(fix);
17984
18653
  const relativePatchedFilePath = patch ? extractPathFromPatch(patch) : null;
17985
- const patchedFilePath = relativePatchedFilePath ? path17.resolve(this.repoPath, relativePatchedFilePath) : null;
18654
+ const patchedFilePath = relativePatchedFilePath ? path19.resolve(this.repoPath, relativePatchedFilePath) : null;
17986
18655
  const fixIdentifier = savedPatchFileName ? savedPatchFileName.replace(".patch", "") : fix.id;
17987
18656
  let markdown = `# Fix ${fixIdentifier}
17988
18657
 
@@ -18326,14 +18995,14 @@ import {
18326
18995
  } from "fs";
18327
18996
  import fs20 from "fs/promises";
18328
18997
  import parseDiff2 from "parse-diff";
18329
- import path18 from "path";
18998
+ import path20 from "path";
18330
18999
  var PatchApplicationService = class {
18331
19000
  /**
18332
19001
  * Gets the appropriate comment syntax for a file based on its extension
18333
19002
  */
18334
19003
  static getCommentSyntax(filePath) {
18335
- const ext = path18.extname(filePath).toLowerCase();
18336
- const basename2 = path18.basename(filePath);
19004
+ const ext = path20.extname(filePath).toLowerCase();
19005
+ const basename2 = path20.basename(filePath);
18337
19006
  const commentMap = {
18338
19007
  // C-style languages (single line comments)
18339
19008
  ".js": "//",
@@ -18536,7 +19205,7 @@ var PatchApplicationService = class {
18536
19205
  }
18537
19206
  );
18538
19207
  }
18539
- const dirPath = path18.dirname(filePath);
19208
+ const dirPath = path20.dirname(filePath);
18540
19209
  mkdirSync(dirPath, { recursive: true });
18541
19210
  writeFileSync(filePath, finalContent, "utf8");
18542
19211
  return filePath;
@@ -18820,7 +19489,7 @@ var PatchApplicationService = class {
18820
19489
  continue;
18821
19490
  }
18822
19491
  try {
18823
- const absolutePath = path18.resolve(repositoryPath, targetFile);
19492
+ const absolutePath = path20.resolve(repositoryPath, targetFile);
18824
19493
  if (existsSync6(absolutePath)) {
18825
19494
  const stats = await fs20.stat(absolutePath);
18826
19495
  const fileModTime = stats.mtime.getTime();
@@ -19011,11 +19680,11 @@ var PatchApplicationService = class {
19011
19680
  }) {
19012
19681
  const sanitizedRepoPath = String(repositoryPath || "").replace("\0", "").replace(/^(\.\.(\/|\\))+/, "");
19013
19682
  const sanitizedTargetFile = String(targetFile || "").replace("\0", "").replace(/^(\.\.(\/|\\))+/, "");
19014
- const absoluteFilePath = path18.resolve(
19683
+ const absoluteFilePath = path20.resolve(
19015
19684
  sanitizedRepoPath,
19016
19685
  sanitizedTargetFile
19017
19686
  );
19018
- const relativePath = path18.relative(sanitizedRepoPath, absoluteFilePath);
19687
+ const relativePath = path20.relative(sanitizedRepoPath, absoluteFilePath);
19019
19688
  if (relativePath.startsWith("..")) {
19020
19689
  throw new Error(
19021
19690
  `Security violation: target file ${targetFile} resolves outside repository`
@@ -19049,7 +19718,7 @@ var PatchApplicationService = class {
19049
19718
  fix,
19050
19719
  scanContext
19051
19720
  });
19052
- appliedFiles.push(path18.relative(repositoryPath, actualPath));
19721
+ appliedFiles.push(path20.relative(repositoryPath, actualPath));
19053
19722
  logDebug(`[${scanContext}] Created new file: ${relativePath}`);
19054
19723
  }
19055
19724
  /**
@@ -19097,7 +19766,7 @@ var PatchApplicationService = class {
19097
19766
  fix,
19098
19767
  scanContext
19099
19768
  });
19100
- appliedFiles.push(path18.relative(repositoryPath, actualPath));
19769
+ appliedFiles.push(path20.relative(repositoryPath, actualPath));
19101
19770
  logDebug(`[${scanContext}] Modified file: ${relativePath}`);
19102
19771
  }
19103
19772
  }
@@ -19293,7 +19962,7 @@ init_configs();
19293
19962
  // src/mcp/services/FileOperations.ts
19294
19963
  init_FileUtils();
19295
19964
  import fs21 from "fs";
19296
- import path19 from "path";
19965
+ import path21 from "path";
19297
19966
  import AdmZip2 from "adm-zip";
19298
19967
  var FileOperations = class {
19299
19968
  /**
@@ -19313,10 +19982,10 @@ var FileOperations = class {
19313
19982
  let packedFilesCount = 0;
19314
19983
  const packedFiles = [];
19315
19984
  const excludedFiles = [];
19316
- const resolvedRepoPath = path19.resolve(repositoryPath);
19985
+ const resolvedRepoPath = path21.resolve(repositoryPath);
19317
19986
  for (const filepath of fileList) {
19318
- const absoluteFilepath = path19.join(repositoryPath, filepath);
19319
- const resolvedFilePath = path19.resolve(absoluteFilepath);
19987
+ const absoluteFilepath = path21.join(repositoryPath, filepath);
19988
+ const resolvedFilePath = path21.resolve(absoluteFilepath);
19320
19989
  if (!resolvedFilePath.startsWith(resolvedRepoPath)) {
19321
19990
  const reason = "potential path traversal security risk";
19322
19991
  logDebug(`[FileOperations] Skipping ${filepath} due to ${reason}`);
@@ -19363,11 +20032,11 @@ var FileOperations = class {
19363
20032
  fileList,
19364
20033
  repositoryPath
19365
20034
  }) {
19366
- const resolvedRepoPath = path19.resolve(repositoryPath);
20035
+ const resolvedRepoPath = path21.resolve(repositoryPath);
19367
20036
  const validatedPaths = [];
19368
20037
  for (const filepath of fileList) {
19369
- const absoluteFilepath = path19.join(repositoryPath, filepath);
19370
- const resolvedFilePath = path19.resolve(absoluteFilepath);
20038
+ const absoluteFilepath = path21.join(repositoryPath, filepath);
20039
+ const resolvedFilePath = path21.resolve(absoluteFilepath);
19371
20040
  if (!resolvedFilePath.startsWith(resolvedRepoPath)) {
19372
20041
  logDebug(
19373
20042
  `[FileOperations] Rejecting ${filepath} - path traversal attempt detected`
@@ -19395,7 +20064,7 @@ var FileOperations = class {
19395
20064
  for (const absolutePath of filePaths) {
19396
20065
  try {
19397
20066
  const content = await fs21.promises.readFile(absolutePath);
19398
- const relativePath = path19.basename(absolutePath);
20067
+ const relativePath = path21.basename(absolutePath);
19399
20068
  fileDataArray.push({
19400
20069
  relativePath,
19401
20070
  absolutePath,
@@ -19707,14 +20376,14 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
19707
20376
  * since the last scan.
19708
20377
  */
19709
20378
  async scanForSecurityVulnerabilities({
19710
- path: path21,
20379
+ path: path22,
19711
20380
  isAllDetectionRulesScan,
19712
20381
  isAllFilesScan,
19713
20382
  scanContext
19714
20383
  }) {
19715
20384
  this.hasAuthenticationFailed = false;
19716
20385
  logDebug(`[${scanContext}] Scanning for new security vulnerabilities`, {
19717
- path: path21
20386
+ path: path22
19718
20387
  });
19719
20388
  if (!this.gqlClient) {
19720
20389
  logInfo(`[${scanContext}] No GQL client found, skipping scan`);
@@ -19730,11 +20399,11 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
19730
20399
  }
19731
20400
  logDebug(
19732
20401
  `[${scanContext}] Connected to the API, assembling list of files to scan`,
19733
- { path: path21 }
20402
+ { path: path22 }
19734
20403
  );
19735
20404
  const isBackgroundScan = scanContext === ScanContext.BACKGROUND_INITIAL || scanContext === ScanContext.BACKGROUND_PERIODIC;
19736
20405
  const files = await getLocalFiles({
19737
- path: path21,
20406
+ path: path22,
19738
20407
  isAllFilesScan,
19739
20408
  scanContext,
19740
20409
  scanRecentlyChangedFiles: !isBackgroundScan
@@ -19760,13 +20429,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
19760
20429
  });
19761
20430
  const { fixReportId, projectId } = await scanFiles({
19762
20431
  fileList: filesToScan.map((file) => file.relativePath),
19763
- repositoryPath: path21,
20432
+ repositoryPath: path22,
19764
20433
  gqlClient: this.gqlClient,
19765
20434
  isAllDetectionRulesScan,
19766
20435
  scanContext
19767
20436
  });
19768
20437
  logInfo(
19769
- `[${scanContext}] Security scan completed for ${path21} reportId: ${fixReportId} projectId: ${projectId}`
20438
+ `[${scanContext}] Security scan completed for ${path22} reportId: ${fixReportId} projectId: ${projectId}`
19770
20439
  );
19771
20440
  if (isAllFilesScan) {
19772
20441
  return;
@@ -20060,13 +20729,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
20060
20729
  });
20061
20730
  return scannedFiles.some((file) => file.relativePath === fixFile);
20062
20731
  }
20063
- async getFreshFixes({ path: path21 }) {
20732
+ async getFreshFixes({ path: path22 }) {
20064
20733
  const scanContext = ScanContext.USER_REQUEST;
20065
- logDebug(`[${scanContext}] Getting fresh fixes`, { path: path21 });
20066
- if (this.path !== path21) {
20067
- this.path = path21;
20734
+ logDebug(`[${scanContext}] Getting fresh fixes`, { path: path22 });
20735
+ if (this.path !== path22) {
20736
+ this.path = path22;
20068
20737
  this.reset();
20069
- logInfo(`[${scanContext}] Reset service state for new path`, { path: path21 });
20738
+ logInfo(`[${scanContext}] Reset service state for new path`, { path: path22 });
20070
20739
  }
20071
20740
  try {
20072
20741
  this.gqlClient = await createAuthenticatedMcpGQLClient();
@@ -20084,7 +20753,7 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
20084
20753
  }
20085
20754
  throw error;
20086
20755
  }
20087
- this.triggerScan({ path: path21, gqlClient: this.gqlClient });
20756
+ this.triggerScan({ path: path22, gqlClient: this.gqlClient });
20088
20757
  let isMvsAutoFixEnabled = null;
20089
20758
  try {
20090
20759
  isMvsAutoFixEnabled = await this.gqlClient.getMvsAutoFixSettings();
@@ -20118,33 +20787,33 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
20118
20787
  return noFreshFixesPrompt;
20119
20788
  }
20120
20789
  triggerScan({
20121
- path: path21,
20790
+ path: path22,
20122
20791
  gqlClient
20123
20792
  }) {
20124
- if (this.path !== path21) {
20125
- this.path = path21;
20793
+ if (this.path !== path22) {
20794
+ this.path = path22;
20126
20795
  this.reset();
20127
- logInfo(`Reset service state for new path in triggerScan`, { path: path21 });
20796
+ logInfo(`Reset service state for new path in triggerScan`, { path: path22 });
20128
20797
  }
20129
20798
  this.gqlClient = gqlClient;
20130
20799
  if (!this.intervalId) {
20131
- this.startPeriodicScanning(path21);
20132
- this.executeInitialScan(path21);
20133
- void this.executeInitialFullScan(path21);
20800
+ this.startPeriodicScanning(path22);
20801
+ this.executeInitialScan(path22);
20802
+ void this.executeInitialFullScan(path22);
20134
20803
  }
20135
20804
  }
20136
- startPeriodicScanning(path21) {
20805
+ startPeriodicScanning(path22) {
20137
20806
  const scanContext = ScanContext.BACKGROUND_PERIODIC;
20138
20807
  logDebug(
20139
20808
  `[${scanContext}] Starting periodic scan for new security vulnerabilities`,
20140
20809
  {
20141
- path: path21
20810
+ path: path22
20142
20811
  }
20143
20812
  );
20144
20813
  this.intervalId = setInterval(() => {
20145
- logDebug(`[${scanContext}] Triggering periodic security scan`, { path: path21 });
20814
+ logDebug(`[${scanContext}] Triggering periodic security scan`, { path: path22 });
20146
20815
  this.scanForSecurityVulnerabilities({
20147
- path: path21,
20816
+ path: path22,
20148
20817
  scanContext
20149
20818
  }).catch((error) => {
20150
20819
  logError(`[${scanContext}] Error during periodic security scan`, {
@@ -20153,45 +20822,45 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
20153
20822
  });
20154
20823
  }, MCP_PERIODIC_CHECK_INTERVAL);
20155
20824
  }
20156
- async executeInitialFullScan(path21) {
20825
+ async executeInitialFullScan(path22) {
20157
20826
  const scanContext = ScanContext.FULL_SCAN;
20158
- logDebug(`[${scanContext}] Triggering initial full security scan`, { path: path21 });
20827
+ logDebug(`[${scanContext}] Triggering initial full security scan`, { path: path22 });
20159
20828
  logDebug(`[${scanContext}] Full scan paths scanned`, {
20160
20829
  fullScanPathsScanned: this.fullScanPathsScanned
20161
20830
  });
20162
- if (this.fullScanPathsScanned.includes(path21)) {
20831
+ if (this.fullScanPathsScanned.includes(path22)) {
20163
20832
  logDebug(`[${scanContext}] Full scan already executed for this path`, {
20164
- path: path21
20833
+ path: path22
20165
20834
  });
20166
20835
  return;
20167
20836
  }
20168
20837
  configStore.set("fullScanPathsScanned", [
20169
20838
  ...this.fullScanPathsScanned,
20170
- path21
20839
+ path22
20171
20840
  ]);
20172
20841
  try {
20173
20842
  await this.scanForSecurityVulnerabilities({
20174
- path: path21,
20843
+ path: path22,
20175
20844
  isAllFilesScan: true,
20176
20845
  isAllDetectionRulesScan: true,
20177
20846
  scanContext: ScanContext.FULL_SCAN
20178
20847
  });
20179
- if (!this.fullScanPathsScanned.includes(path21)) {
20180
- this.fullScanPathsScanned.push(path21);
20848
+ if (!this.fullScanPathsScanned.includes(path22)) {
20849
+ this.fullScanPathsScanned.push(path22);
20181
20850
  configStore.set("fullScanPathsScanned", this.fullScanPathsScanned);
20182
20851
  }
20183
- logInfo(`[${scanContext}] Full scan completed`, { path: path21 });
20852
+ logInfo(`[${scanContext}] Full scan completed`, { path: path22 });
20184
20853
  } catch (error) {
20185
20854
  logError(`[${scanContext}] Error during initial full security scan`, {
20186
20855
  error
20187
20856
  });
20188
20857
  }
20189
20858
  }
20190
- executeInitialScan(path21) {
20859
+ executeInitialScan(path22) {
20191
20860
  const scanContext = ScanContext.BACKGROUND_INITIAL;
20192
- logDebug(`[${scanContext}] Triggering initial security scan`, { path: path21 });
20861
+ logDebug(`[${scanContext}] Triggering initial security scan`, { path: path22 });
20193
20862
  this.scanForSecurityVulnerabilities({
20194
- path: path21,
20863
+ path: path22,
20195
20864
  scanContext: ScanContext.BACKGROUND_INITIAL
20196
20865
  }).catch((error) => {
20197
20866
  logError(`[${scanContext}] Error during initial security scan`, { error });
@@ -20270,8 +20939,8 @@ Example payload:
20270
20939
  },
20271
20940
  required: ["path"]
20272
20941
  });
20273
- __publicField(this, "inputValidationSchema", z40.object({
20274
- path: z40.string().describe(
20942
+ __publicField(this, "inputValidationSchema", z42.object({
20943
+ path: z42.string().describe(
20275
20944
  "Full local path to the cloned git repository to check for new available fixes"
20276
20945
  )
20277
20946
  }));
@@ -20288,9 +20957,9 @@ Example payload:
20288
20957
  `Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
20289
20958
  );
20290
20959
  }
20291
- const path21 = pathValidationResult.path;
20960
+ const path22 = pathValidationResult.path;
20292
20961
  const resultText = await this.newFixesService.getFreshFixes({
20293
- path: path21
20962
+ path: path22
20294
20963
  });
20295
20964
  logInfo("CheckForNewAvailableFixesTool execution completed", {
20296
20965
  resultText
@@ -20301,7 +20970,7 @@ Example payload:
20301
20970
 
20302
20971
  // src/mcp/tools/fetchAvailableFixes/FetchAvailableFixesTool.ts
20303
20972
  init_GitService();
20304
- import { z as z41 } from "zod";
20973
+ import { z as z43 } from "zod";
20305
20974
 
20306
20975
  // src/mcp/tools/fetchAvailableFixes/FetchAvailableFixesService.ts
20307
20976
  init_configs();
@@ -20443,16 +21112,16 @@ Call this tool instead of ${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES} when you only
20443
21112
  },
20444
21113
  required: ["path"]
20445
21114
  });
20446
- __publicField(this, "inputValidationSchema", z41.object({
20447
- path: z41.string().describe(
21115
+ __publicField(this, "inputValidationSchema", z43.object({
21116
+ path: z43.string().describe(
20448
21117
  "Full local path to the cloned git repository to check for available fixes"
20449
21118
  ),
20450
- offset: z41.number().optional().describe("Optional offset for pagination"),
20451
- limit: z41.number().optional().describe("Optional maximum number of fixes to return"),
20452
- fileFilter: z41.array(z41.string()).optional().describe(
21119
+ offset: z43.number().optional().describe("Optional offset for pagination"),
21120
+ limit: z43.number().optional().describe("Optional maximum number of fixes to return"),
21121
+ fileFilter: z43.array(z43.string()).optional().describe(
20453
21122
  "Optional list of file paths relative to the path parameter to filter fixes by. INCOMPATIBLE with fetchFixesFromAnyFile"
20454
21123
  ),
20455
- fetchFixesFromAnyFile: z41.boolean().optional().describe(
21124
+ fetchFixesFromAnyFile: z43.boolean().optional().describe(
20456
21125
  "Optional boolean to fetch fixes for all files. INCOMPATIBLE with fileFilter"
20457
21126
  )
20458
21127
  }));
@@ -20467,8 +21136,8 @@ Call this tool instead of ${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES} when you only
20467
21136
  `Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
20468
21137
  );
20469
21138
  }
20470
- const path21 = pathValidationResult.path;
20471
- const gitService = new GitService(path21, log);
21139
+ const path22 = pathValidationResult.path;
21140
+ const gitService = new GitService(path22, log);
20472
21141
  const gitValidation = await gitService.validateRepository();
20473
21142
  if (!gitValidation.isValid) {
20474
21143
  throw new Error(`Invalid git repository: ${gitValidation.error}`);
@@ -20521,7 +21190,7 @@ Call this tool instead of ${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES} when you only
20521
21190
  };
20522
21191
 
20523
21192
  // src/mcp/tools/mcpChecker/mcpCheckerTool.ts
20524
- import z42 from "zod";
21193
+ import z44 from "zod";
20525
21194
 
20526
21195
  // src/mcp/tools/mcpChecker/mcpCheckerService.ts
20527
21196
  var _McpCheckerService = class _McpCheckerService {
@@ -20582,7 +21251,7 @@ var McpCheckerTool = class extends BaseTool {
20582
21251
  __publicField(this, "displayName", "MCP Checker");
20583
21252
  // A detailed description to guide the LLM on when and how to invoke this tool.
20584
21253
  __publicField(this, "description", "Check the MCP servers running on this IDE against organization policies.");
20585
- __publicField(this, "inputValidationSchema", z42.object({}));
21254
+ __publicField(this, "inputValidationSchema", z44.object({}));
20586
21255
  __publicField(this, "inputSchema", {
20587
21256
  type: "object",
20588
21257
  properties: {},
@@ -20608,7 +21277,7 @@ var McpCheckerTool = class extends BaseTool {
20608
21277
  };
20609
21278
 
20610
21279
  // src/mcp/tools/scanAndFixVulnerabilities/ScanAndFixVulnerabilitiesTool.ts
20611
- import z43 from "zod";
21280
+ import z45 from "zod";
20612
21281
  init_configs();
20613
21282
 
20614
21283
  // src/mcp/tools/scanAndFixVulnerabilities/ScanAndFixVulnerabilitiesService.ts
@@ -20795,17 +21464,17 @@ Example payload:
20795
21464
  "rescan": false
20796
21465
  }`);
20797
21466
  __publicField(this, "hasAuthentication", true);
20798
- __publicField(this, "inputValidationSchema", z43.object({
20799
- path: z43.string().describe(
21467
+ __publicField(this, "inputValidationSchema", z45.object({
21468
+ path: z45.string().describe(
20800
21469
  "Full local path to repository to scan and fix vulnerabilities"
20801
21470
  ),
20802
- offset: z43.number().optional().describe("Optional offset for pagination"),
20803
- limit: z43.number().optional().describe("Optional maximum number of results to return"),
20804
- maxFiles: z43.number().optional().describe(
21471
+ offset: z45.number().optional().describe("Optional offset for pagination"),
21472
+ limit: z45.number().optional().describe("Optional maximum number of results to return"),
21473
+ maxFiles: z45.number().optional().describe(
20805
21474
  `Optional maximum number of files to scan (default: ${MCP_DEFAULT_MAX_FILES_TO_SCAN}). Increase for comprehensive scans of larger codebases or decrease for faster focused scans.`
20806
21475
  ),
20807
- rescan: z43.boolean().optional().describe("Optional whether to rescan the repository"),
20808
- scanRecentlyChangedFiles: z43.boolean().optional().describe(
21476
+ rescan: z45.boolean().optional().describe("Optional whether to rescan the repository"),
21477
+ scanRecentlyChangedFiles: z45.boolean().optional().describe(
20809
21478
  "Optional whether to automatically scan recently changed files when no changed files are found in git status. If false, the tool will prompt the user instead."
20810
21479
  )
20811
21480
  }));
@@ -20856,9 +21525,9 @@ Example payload:
20856
21525
  `Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
20857
21526
  );
20858
21527
  }
20859
- const path21 = pathValidationResult.path;
21528
+ const path22 = pathValidationResult.path;
20860
21529
  const files = await getLocalFiles({
20861
- path: path21,
21530
+ path: path22,
20862
21531
  maxFileSize: MCP_MAX_FILE_SIZE,
20863
21532
  maxFiles: args.maxFiles,
20864
21533
  scanContext: ScanContext.USER_REQUEST,
@@ -20878,7 +21547,7 @@ Example payload:
20878
21547
  try {
20879
21548
  const fixResult = await this.vulnerabilityFixService.processVulnerabilities({
20880
21549
  fileList: files.map((file) => file.relativePath),
20881
- repositoryPath: path21,
21550
+ repositoryPath: path22,
20882
21551
  offset: args.offset,
20883
21552
  limit: args.limit,
20884
21553
  isRescan: args.rescan || !!args.maxFiles
@@ -20983,32 +21652,32 @@ var mcpHandler = async (_args) => {
20983
21652
 
20984
21653
  // src/args/commands/review.ts
20985
21654
  import fs22 from "fs";
20986
- import chalk9 from "chalk";
21655
+ import chalk11 from "chalk";
20987
21656
  function reviewBuilder(yargs2) {
20988
21657
  return yargs2.option("f", {
20989
21658
  alias: "scan-file",
20990
21659
  demandOption: true,
20991
21660
  type: "string",
20992
- describe: chalk9.bold(
21661
+ describe: chalk11.bold(
20993
21662
  "Select the vulnerability report to analyze (Checkmarx, Snyk, Fortify, CodeQL, Sonarqube, Semgrep)"
20994
21663
  )
20995
21664
  }).option("repo", { ...repoOption, demandOption: true }).option("scanner", { ...scannerOptions, demandOption: true }).option("ref", { ...refOption, demandOption: true }).option("ch", {
20996
21665
  alias: "commit-hash",
20997
- describe: chalk9.bold("Hash of the commit"),
21666
+ describe: chalk11.bold("Hash of the commit"),
20998
21667
  type: "string",
20999
21668
  demandOption: true
21000
21669
  }).option("mobb-project-name", mobbProjectNameOption).option("api-key", { ...apiKeyOption, demandOption: true }).option("commit-hash", { ...commitHashOption, demandOption: true }).option("github-token", {
21001
- describe: chalk9.bold("Github action token"),
21670
+ describe: chalk11.bold("Github action token"),
21002
21671
  type: "string",
21003
21672
  demandOption: true
21004
21673
  }).option("pull-request", {
21005
21674
  alias: ["pr", "pr-number", "pr-id"],
21006
- describe: chalk9.bold("Number of the pull request"),
21675
+ describe: chalk11.bold("Number of the pull request"),
21007
21676
  type: "number",
21008
21677
  demandOption: true
21009
21678
  }).option("p", {
21010
21679
  alias: "src-path",
21011
- describe: chalk9.bold(
21680
+ describe: chalk11.bold(
21012
21681
  "Path to the repository folder with the source code"
21013
21682
  ),
21014
21683
  type: "string",
@@ -21021,7 +21690,7 @@ function reviewBuilder(yargs2) {
21021
21690
  function validateReviewOptions(argv) {
21022
21691
  if (!fs22.existsSync(argv.f)) {
21023
21692
  throw new CliError(`
21024
- Can't access ${chalk9.bold(argv.f)}`);
21693
+ Can't access ${chalk11.bold(argv.f)}`);
21025
21694
  }
21026
21695
  validateRepoUrl(argv);
21027
21696
  validateReportFileFormat(argv.f);
@@ -21091,248 +21760,77 @@ async function addScmTokenHandler(args) {
21091
21760
  await addScmToken(args);
21092
21761
  }
21093
21762
 
21094
- // src/args/commands/upload_ai_blame.ts
21095
- import fsPromises3 from "fs/promises";
21096
- import path20 from "path";
21097
- import chalk10 from "chalk";
21098
- import Configstore6 from "configstore";
21099
- import { withFile } from "tmp-promise";
21100
- import z44 from "zod";
21101
- var PromptItemZ = z44.object({
21102
- type: z44.enum(["USER_PROMPT", "AI_RESPONSE", "TOOL_EXECUTION", "AI_THINKING"]),
21103
- attachedFiles: z44.array(
21104
- z44.object({
21105
- relativePath: z44.string(),
21106
- startLine: z44.number().optional()
21107
- })
21108
- ).optional(),
21109
- tokens: z44.object({
21110
- inputCount: z44.number(),
21111
- outputCount: z44.number()
21112
- }).optional(),
21113
- text: z44.string().optional(),
21114
- date: z44.date().optional(),
21115
- tool: z44.object({
21116
- name: z44.string(),
21117
- parameters: z44.string(),
21118
- result: z44.string(),
21119
- rawArguments: z44.string().optional(),
21120
- accepted: z44.boolean().optional()
21121
- }).optional()
21122
- });
21123
- var PromptItemArrayZ = z44.array(PromptItemZ);
21124
- function uploadAiBlameBuilder(args) {
21125
- return args.option("prompt", {
21126
- type: "string",
21127
- array: true,
21128
- demandOption: true,
21129
- describe: chalk10.bold("Path(s) to prompt artifact(s) (one per session)")
21130
- }).option("inference", {
21131
- type: "string",
21132
- array: true,
21133
- demandOption: true,
21134
- describe: chalk10.bold(
21135
- "Path(s) to inference artifact(s) (one per session)"
21136
- )
21137
- }).option("ai-response-at", {
21138
- type: "string",
21139
- array: true,
21140
- describe: chalk10.bold(
21141
- "ISO timestamp(s) for AI response (one per session, defaults to now)"
21142
- )
21143
- }).option("model", {
21144
- type: "string",
21145
- array: true,
21146
- describe: chalk10.bold("AI model name(s) (optional, one per session)")
21147
- }).option("tool-name", {
21148
- type: "string",
21149
- array: true,
21150
- describe: chalk10.bold("Tool/IDE name(s) (optional, one per session)")
21151
- }).option("blame-type", {
21152
- type: "string",
21153
- array: true,
21154
- choices: Object.values(AiBlameInferenceType),
21155
- describe: chalk10.bold(
21156
- "Blame type(s) (optional, one per session, defaults to CHAT)"
21157
- )
21158
- }).strict();
21159
- }
21160
- var config5 = new Configstore6(packageJson.name, { apiToken: "" });
21161
- async function getAuthenticatedGQLClientForIdeExtension() {
21162
- let gqlClient = new GQLClient({
21163
- apiKey: config5.get("apiToken") ?? "",
21164
- type: "apiKey"
21165
- });
21166
- gqlClient = await handleMobbLogin({
21167
- inGqlClient: gqlClient,
21168
- skipPrompts: true
21169
- });
21170
- return gqlClient;
21171
- }
21172
- async function uploadAiBlameHandler(args, exitOnError = true) {
21173
- const prompts = args.prompt || [];
21174
- const inferences = args.inference || [];
21175
- const models = args.model || [];
21176
- const tools = args.toolName || args["tool-name"] || [];
21177
- const responseTimes = args.aiResponseAt || args["ai-response-at"] || [];
21178
- const blameTypes = args.blameType || args["blame-type"] || [];
21179
- if (prompts.length !== inferences.length) {
21180
- const errorMsg = "prompt and inference must have the same number of entries";
21181
- console.error(chalk10.red(errorMsg));
21182
- if (exitOnError) {
21183
- process.exit(1);
21184
- }
21185
- throw new Error(errorMsg);
21186
- }
21187
- const nowIso = (/* @__PURE__ */ new Date()).toISOString();
21188
- const sessions = [];
21189
- for (let i = 0; i < prompts.length; i++) {
21190
- const promptPath = String(prompts[i]);
21191
- const inferencePath = String(inferences[i]);
21192
- try {
21193
- await Promise.all([
21194
- fsPromises3.access(promptPath),
21195
- fsPromises3.access(inferencePath)
21196
- ]);
21197
- } catch {
21198
- const errorMsg = `File not found for session ${i + 1}`;
21199
- console.error(chalk10.red(errorMsg));
21200
- if (exitOnError) {
21201
- process.exit(1);
21202
- }
21203
- throw new Error(errorMsg);
21204
- }
21205
- sessions.push({
21206
- promptFileName: path20.basename(promptPath),
21207
- inferenceFileName: path20.basename(inferencePath),
21208
- aiResponseAt: responseTimes[i] || nowIso,
21209
- model: models[i],
21210
- toolName: tools[i],
21211
- blameType: blameTypes[i] || "CHAT" /* Chat */
21212
- });
21213
- }
21214
- const authenticatedClient = await getAuthenticatedGQLClientForIdeExtension();
21215
- const initRes = await authenticatedClient.uploadAIBlameInferencesInitRaw({
21216
- sessions
21217
- });
21218
- const uploadSessions = initRes.uploadAIBlameInferencesInit?.uploadSessions ?? [];
21219
- if (uploadSessions.length !== sessions.length) {
21220
- const errorMsg = "Init failed to return expected number of sessions";
21221
- console.error(chalk10.red(errorMsg));
21222
- if (exitOnError) {
21223
- process.exit(1);
21224
- }
21225
- throw new Error(errorMsg);
21226
- }
21227
- for (let i = 0; i < uploadSessions.length; i++) {
21228
- const us = uploadSessions[i];
21229
- const promptPath = String(prompts[i]);
21230
- const inferencePath = String(inferences[i]);
21231
- await Promise.all([
21232
- // Prompt
21233
- uploadFile({
21234
- file: promptPath,
21235
- url: us.prompt.url,
21236
- uploadFields: JSON.parse(us.prompt.uploadFieldsJSON),
21237
- uploadKey: us.prompt.uploadKey
21238
- }),
21239
- // Inference
21240
- uploadFile({
21241
- file: inferencePath,
21242
- url: us.inference.url,
21243
- uploadFields: JSON.parse(us.inference.uploadFieldsJSON),
21244
- uploadKey: us.inference.uploadKey
21245
- })
21246
- ]);
21247
- }
21248
- const finalizeSessions = uploadSessions.map((us, i) => {
21249
- const s = sessions[i];
21250
- return {
21251
- aiBlameInferenceId: us.aiBlameInferenceId,
21252
- promptKey: us.prompt.uploadKey,
21253
- inferenceKey: us.inference.uploadKey,
21254
- aiResponseAt: s.aiResponseAt,
21255
- model: s.model,
21256
- toolName: s.toolName,
21257
- blameType: s.blameType
21258
- };
21259
- });
21260
- const finRes = await authenticatedClient.finalizeAIBlameInferencesUploadRaw({
21261
- sessions: finalizeSessions
21262
- });
21263
- const status = finRes?.finalizeAIBlameInferencesUpload?.status;
21264
- if (status !== "OK") {
21265
- const errorMsg = finRes?.finalizeAIBlameInferencesUpload?.error || "unknown error";
21266
- console.error(chalk10.red(errorMsg));
21267
- if (exitOnError) {
21268
- process.exit(1);
21269
- }
21270
- throw new Error(errorMsg);
21271
- }
21272
- console.log(chalk10.green("AI Blame uploads finalized successfully"));
21273
- }
21274
-
21275
21763
  // src/args/yargs.ts
21276
21764
  var parseArgs = async (args) => {
21277
21765
  const yargsInstance = yargs(args);
21278
21766
  return yargsInstance.updateStrings({
21279
- "Commands:": chalk11.yellow.underline.bold("Commands:"),
21280
- "Options:": chalk11.yellow.underline.bold("Options:"),
21281
- "Examples:": chalk11.yellow.underline.bold("Examples:"),
21282
- "Show help": chalk11.bold("Show help")
21767
+ "Commands:": chalk12.yellow.underline.bold("Commands:"),
21768
+ "Options:": chalk12.yellow.underline.bold("Options:"),
21769
+ "Examples:": chalk12.yellow.underline.bold("Examples:"),
21770
+ "Show help": chalk12.bold("Show help")
21283
21771
  }).usage(
21284
- `${chalk11.bold(
21772
+ `${chalk12.bold(
21285
21773
  "\n Bugsy - Trusted, Automatic Vulnerability Fixer \u{1F575}\uFE0F\u200D\u2642\uFE0F\n\n"
21286
- )} ${chalk11.yellow.underline.bold("Usage:")}
21287
- $0 ${chalk11.green(
21774
+ )} ${chalk12.yellow.underline.bold("Usage:")}
21775
+ $0 ${chalk12.green(
21288
21776
  "<command>"
21289
- )} ${chalk11.dim("[options]")}
21777
+ )} ${chalk12.dim("[options]")}
21290
21778
  `
21291
21779
  ).version(false).command(
21292
21780
  mobbCliCommand.scan,
21293
- chalk11.bold(
21781
+ chalk12.bold(
21294
21782
  "Scan your code for vulnerabilities, get automated fixes right away."
21295
21783
  ),
21296
21784
  scanBuilder,
21297
21785
  scanHandler
21298
21786
  ).command(
21299
21787
  mobbCliCommand.analyze,
21300
- chalk11.bold(
21788
+ chalk12.bold(
21301
21789
  "Provide a code repository, get automated fixes right away. You can also provide a vulnerability report to analyze or have Mobb scan the code for you."
21302
21790
  ),
21303
21791
  analyzeBuilder,
21304
21792
  analyzeHandler
21305
21793
  ).command(
21306
21794
  mobbCliCommand.review,
21307
- chalk11.bold(
21795
+ chalk12.bold(
21308
21796
  "Mobb will review your github pull requests and provide comments with fixes "
21309
21797
  ),
21310
21798
  reviewBuilder,
21311
21799
  reviewHandler
21312
21800
  ).command(
21313
21801
  mobbCliCommand.addScmToken,
21314
- chalk11.bold(
21802
+ chalk12.bold(
21315
21803
  "Add your SCM (Github, Gitlab, Azure DevOps) token to Mobb to enable automated fixes."
21316
21804
  ),
21317
21805
  addScmTokenBuilder,
21318
21806
  addScmTokenHandler
21319
21807
  ).command(
21320
21808
  mobbCliCommand.convertToSarif,
21321
- chalk11.bold("Convert an existing SAST report to SARIF format."),
21809
+ chalk12.bold("Convert an existing SAST report to SARIF format."),
21322
21810
  convertToSarifBuilder,
21323
21811
  convertToSarifHandler
21324
21812
  ).command(
21325
21813
  mobbCliCommand.mcp,
21326
- chalk11.bold("Launch the MCP (Model Context Protocol) server."),
21814
+ chalk12.bold("Launch the MCP (Model Context Protocol) server."),
21327
21815
  mcpBuilder,
21328
21816
  mcpHandler
21329
21817
  ).command(
21330
21818
  mobbCliCommand.uploadAiBlame,
21331
- chalk11.bold(
21819
+ chalk12.bold(
21332
21820
  "Upload AI Blame inference artifacts (prompt + inference) and finalize them."
21333
21821
  ),
21334
21822
  uploadAiBlameBuilder,
21335
21823
  uploadAiBlameHandler
21824
+ ).command(
21825
+ mobbCliCommand.claudeCodeInstallHook,
21826
+ chalk12.bold("Install Claude Code hooks for data collection."),
21827
+ claudeCodeInstallHookBuilder,
21828
+ claudeCodeInstallHookHandler
21829
+ ).command(
21830
+ mobbCliCommand.claudeCodeProcessHook,
21831
+ chalk12.bold("Process Claude Code hook data and upload to backend."),
21832
+ claudeCodeProcessHookBuilder,
21833
+ claudeCodeProcessHookHandler
21336
21834
  ).example(
21337
21835
  "npx mobbdev@latest scan -r https://github.com/WebGoat/WebGoat",
21338
21836
  "Scan an existing repository"
@@ -21341,7 +21839,7 @@ var parseArgs = async (args) => {
21341
21839
  handler() {
21342
21840
  yargsInstance.showHelp();
21343
21841
  }
21344
- }).strictOptions().help("h").alias("h", "help").epilog(chalk11.bgBlue("Made with \u2764\uFE0F by Mobb")).showHelpOnFail(true).wrap(Math.min(120, yargsInstance.terminalWidth())).parse();
21842
+ }).strictOptions().help("h").alias("h", "help").epilog(chalk12.bgBlue("Made with \u2764\uFE0F by Mobb")).showHelpOnFail(true).wrap(Math.min(120, yargsInstance.terminalWidth())).parse();
21345
21843
  };
21346
21844
 
21347
21845
  // src/index.ts