mobbdev 1.0.217 → 1.1.0

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 +956 -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,645 @@ 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() {
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
+ const mobbHookConfig = {
13431
+ matcher: "Edit|Write",
13432
+ hooks: [
13433
+ {
13434
+ type: "command",
13435
+ command: "npx --yes mobbdev@latest claude-code-process-hook"
13436
+ }
13437
+ ]
13438
+ };
13439
+ const existingHookIndex = settings.hooks.PostToolUse.findIndex(
13440
+ (hook) => hook.matcher === "Edit|Write" && hook.hooks.some(
13441
+ (h) => h.command?.includes("mobbdev@latest claude-code-process-hook")
13442
+ )
13443
+ );
13444
+ if (existingHookIndex >= 0) {
13445
+ console.log(chalk10.yellow("Mobb hook already exists, updating..."));
13446
+ settings.hooks.PostToolUse[existingHookIndex] = mobbHookConfig;
13447
+ } else {
13448
+ console.log(chalk10.green("Adding new Mobb hook..."));
13449
+ settings.hooks.PostToolUse.push(mobbHookConfig);
13450
+ }
13451
+ await writeClaudeSettings(settings);
13452
+ console.log(
13453
+ chalk10.green(
13454
+ `\u2705 Mobb hooks installed successfully in ${CLAUDE_SETTINGS_PATH}`
13455
+ )
13456
+ );
13457
+ }
13458
+
13459
+ // src/args/commands/claude_code.ts
13460
+ var config6 = new Configstore5(packageJson.name, { apiToken: "" });
13461
+ var claudeCodeInstallHookBuilder = (yargs2) => {
13462
+ return yargs2.example(
13463
+ "$0 claude-code-install-hook",
13464
+ "Install Claude Code hooks for data collection"
13465
+ ).strict();
13466
+ };
13467
+ var claudeCodeProcessHookBuilder = (yargs2) => {
13468
+ return yargs2.example(
13469
+ "$0 claude-code-process-hook",
13470
+ "Process Claude Code hook data and upload to backend"
13471
+ ).strict();
13472
+ };
13473
+ var claudeCodeInstallHookHandler = async () => {
13474
+ try {
13475
+ const gqlClient = new GQLClient({
13476
+ apiKey: config6.get("apiToken") ?? "",
13477
+ type: "apiKey"
13478
+ });
13479
+ await handleMobbLogin({
13480
+ inGqlClient: gqlClient,
13481
+ skipPrompts: false
13482
+ });
13483
+ await installMobbHooks();
13484
+ process.exit(0);
13485
+ } catch (error) {
13486
+ console.error("Failed to install Claude Code hooks:", error);
13487
+ process.exit(1);
13488
+ }
13489
+ };
13490
+ var claudeCodeProcessHookHandler = async () => {
13491
+ try {
13492
+ const { hookData, inference, tracePayload, uploadSuccess } = await processAndUploadHookData();
13493
+ console.log("Successfully processed Claude Code hook:");
13494
+ console.log("Session ID:", hookData.session_id);
13495
+ console.log("Tool:", hookData.tool_name);
13496
+ console.log("Transcript path:", hookData.transcript_path);
13497
+ console.log("Inference length:", inference.length);
13498
+ const userPrompts = tracePayload.prompts.filter(
13499
+ (p) => p.type === "USER_PROMPT"
13500
+ );
13501
+ const assistantResponses = tracePayload.prompts.filter(
13502
+ (p) => p.type === "AI_RESPONSE"
13503
+ );
13504
+ const aiThinking = tracePayload.prompts.filter(
13505
+ (p) => p.type === "AI_THINKING"
13506
+ );
13507
+ console.log("Conversation context extracted:");
13508
+ console.log("- User prompts:", userPrompts.length);
13509
+ console.log("- Assistant responses:", assistantResponses.length);
13510
+ console.log("- AI thinking entries:", aiThinking.length);
13511
+ console.log("- Model:", tracePayload.model);
13512
+ const totalInputTokens = tracePayload.prompts.reduce(
13513
+ (sum, p) => sum + (p.tokens?.inputCount || 0),
13514
+ 0
13515
+ );
13516
+ const totalOutputTokens = tracePayload.prompts.reduce(
13517
+ (sum, p) => sum + (p.tokens?.outputCount || 0),
13518
+ 0
13519
+ );
13520
+ console.log("- Input tokens:", totalInputTokens);
13521
+ console.log("- Output tokens:", totalOutputTokens);
13522
+ console.log("Trace data formatted:");
13523
+ console.log("- Prompt items:", tracePayload.prompts.length);
13524
+ console.log("- Model:", tracePayload.model);
13525
+ console.log("- Tool:", tracePayload.tool);
13526
+ console.log("- Response time:", tracePayload.responseTime);
13527
+ console.log("- Upload success:", uploadSuccess ? "\u2705" : "\u274C");
13528
+ if (uploadSuccess) {
13529
+ console.log("\u2705 Claude Code trace uploaded successfully to Mobb backend");
13530
+ }
13531
+ process.exit(0);
13532
+ } catch (error) {
13533
+ console.error("Failed to process Claude Code hook data:", error);
13534
+ process.exit(1);
13535
+ }
13536
+ };
13537
+
12897
13538
  // src/mcp/core/McpServer.ts
12898
13539
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
12899
13540
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
@@ -12905,7 +13546,7 @@ import {
12905
13546
  } from "@modelcontextprotocol/sdk/types.js";
12906
13547
 
12907
13548
  // src/mcp/Logger.ts
12908
- import Configstore4 from "configstore";
13549
+ import Configstore6 from "configstore";
12909
13550
 
12910
13551
  // src/mcp/services/WorkspaceService.ts
12911
13552
  var WorkspaceService = class {
@@ -12913,8 +13554,8 @@ var WorkspaceService = class {
12913
13554
  * Sets a known workspace path that was discovered through successful validation
12914
13555
  * @param path The validated workspace path to store
12915
13556
  */
12916
- static setKnownWorkspacePath(path21) {
12917
- this.knownWorkspacePath = path21;
13557
+ static setKnownWorkspacePath(path22) {
13558
+ this.knownWorkspacePath = path22;
12918
13559
  }
12919
13560
  /**
12920
13561
  * Gets the known workspace path that was previously validated
@@ -12991,7 +13632,7 @@ var Logger = class {
12991
13632
  __publicField(this, "lastKnownPath", null);
12992
13633
  this.host = WorkspaceService.getHost();
12993
13634
  this.unknownPathSuffix = Math.floor(1e3 + Math.random() * 9e3).toString();
12994
- this.mobbConfigStore = new Configstore4("mobb-logs", {});
13635
+ this.mobbConfigStore = new Configstore6("mobb-logs", {});
12995
13636
  this.mobbConfigStore.set("version", packageJson.version);
12996
13637
  }
12997
13638
  /**
@@ -13061,135 +13702,135 @@ import { v4 as uuidv42 } from "uuid";
13061
13702
  init_configs();
13062
13703
 
13063
13704
  // src/mcp/types.ts
13064
- import { z as z31 } from "zod";
13065
- var ScanAndFixVulnerabilitiesToolSchema = z31.object({
13066
- path: z31.string()
13705
+ import { z as z33 } from "zod";
13706
+ var ScanAndFixVulnerabilitiesToolSchema = z33.object({
13707
+ path: z33.string()
13067
13708
  });
13068
- var VulnerabilityReportIssueTagSchema = z31.object({
13069
- vulnerability_report_issue_tag_value: z31.nativeEnum(
13709
+ var VulnerabilityReportIssueTagSchema = z33.object({
13710
+ vulnerability_report_issue_tag_value: z33.nativeEnum(
13070
13711
  Vulnerability_Report_Issue_Tag_Enum
13071
13712
  )
13072
13713
  });
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)
13714
+ var VulnerabilityReportIssueSchema = z33.object({
13715
+ category: z33.any().optional().nullable(),
13716
+ parsedIssueType: z33.nativeEnum(IssueType_Enum).nullable().optional(),
13717
+ parsedSeverity: z33.nativeEnum(Vulnerability_Severity_Enum).nullable().optional(),
13718
+ vulnerabilityReportIssueTags: z33.array(VulnerabilityReportIssueTagSchema)
13078
13719
  });
13079
- var SharedStateSchema = z31.object({
13080
- __typename: z31.literal("fix_shared_state").optional(),
13081
- id: z31.any(),
13720
+ var SharedStateSchema = z33.object({
13721
+ __typename: z33.literal("fix_shared_state").optional(),
13722
+ id: z33.any(),
13082
13723
  // GraphQL uses `any` type for UUID
13083
- downloadedBy: z31.array(z31.any().nullable()).optional().nullable()
13724
+ downloadedBy: z33.array(z33.any().nullable()).optional().nullable()
13084
13725
  });
13085
- var UnstructuredFixExtraContextSchema = z31.object({
13086
- __typename: z31.literal("UnstructuredFixExtraContext").optional(),
13087
- key: z31.string(),
13088
- value: z31.any()
13726
+ var UnstructuredFixExtraContextSchema = z33.object({
13727
+ __typename: z33.literal("UnstructuredFixExtraContext").optional(),
13728
+ key: z33.string(),
13729
+ value: z33.any()
13089
13730
  // GraphQL JSON type
13090
13731
  });
13091
- var FixExtraContextResponseSchema = z31.object({
13092
- __typename: z31.literal("FixExtraContextResponse").optional(),
13093
- extraContext: z31.array(UnstructuredFixExtraContextSchema),
13094
- fixDescription: z31.string()
13732
+ var FixExtraContextResponseSchema = z33.object({
13733
+ __typename: z33.literal("FixExtraContextResponse").optional(),
13734
+ extraContext: z33.array(UnstructuredFixExtraContextSchema),
13735
+ fixDescription: z33.string()
13095
13736
  });
13096
- var FixDataSchema = z31.object({
13097
- __typename: z31.literal("FixData"),
13098
- patch: z31.string(),
13099
- patchOriginalEncodingBase64: z31.string(),
13737
+ var FixDataSchema = z33.object({
13738
+ __typename: z33.literal("FixData"),
13739
+ patch: z33.string(),
13740
+ patchOriginalEncodingBase64: z33.string(),
13100
13741
  extraContext: FixExtraContextResponseSchema
13101
13742
  });
13102
- var GetFixNoFixErrorSchema = z31.object({
13103
- __typename: z31.literal("GetFixNoFixError")
13743
+ var GetFixNoFixErrorSchema = z33.object({
13744
+ __typename: z33.literal("GetFixNoFixError")
13104
13745
  });
13105
- var PatchAndQuestionsSchema = z31.union([FixDataSchema, GetFixNoFixErrorSchema]);
13106
- var McpFixSchema = z31.object({
13107
- __typename: z31.literal("fix").optional(),
13108
- id: z31.any(),
13746
+ var PatchAndQuestionsSchema = z33.union([FixDataSchema, GetFixNoFixErrorSchema]);
13747
+ var McpFixSchema = z33.object({
13748
+ __typename: z33.literal("fix").optional(),
13749
+ id: z33.any(),
13109
13750
  // 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(),
13751
+ confidence: z33.number(),
13752
+ safeIssueType: z33.string().nullable(),
13753
+ severityText: z33.string().nullable(),
13754
+ gitBlameLogin: z33.string().nullable().optional(),
13114
13755
  // Optional in GraphQL
13115
- severityValue: z31.number().nullable(),
13116
- vulnerabilityReportIssues: z31.array(VulnerabilityReportIssueSchema),
13756
+ severityValue: z33.number().nullable(),
13757
+ vulnerabilityReportIssues: z33.array(VulnerabilityReportIssueSchema),
13117
13758
  sharedState: SharedStateSchema.nullable().optional(),
13118
13759
  // Optional in GraphQL
13119
13760
  patchAndQuestions: PatchAndQuestionsSchema,
13120
13761
  // Additional field added by the client
13121
- fixUrl: z31.string().optional()
13762
+ fixUrl: z33.string().optional()
13122
13763
  });
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()
13764
+ var FixAggregateSchema = z33.object({
13765
+ __typename: z33.literal("fix_aggregate").optional(),
13766
+ aggregate: z33.object({
13767
+ __typename: z33.literal("fix_aggregate_fields").optional(),
13768
+ count: z33.number()
13128
13769
  }).nullable()
13129
13770
  });
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()
13771
+ var VulnerabilityReportIssueAggregateSchema = z33.object({
13772
+ __typename: z33.literal("vulnerability_report_issue_aggregate").optional(),
13773
+ aggregate: z33.object({
13774
+ __typename: z33.literal("vulnerability_report_issue_aggregate_fields").optional(),
13775
+ count: z33.number()
13135
13776
  }).nullable()
13136
13777
  });
13137
- var RepoSchema = z31.object({
13138
- __typename: z31.literal("repo").optional(),
13139
- originalUrl: z31.string()
13778
+ var RepoSchema = z33.object({
13779
+ __typename: z33.literal("repo").optional(),
13780
+ originalUrl: z33.string()
13140
13781
  });
13141
- var ProjectSchema = z31.object({
13142
- id: z31.any(),
13782
+ var ProjectSchema = z33.object({
13783
+ id: z33.any(),
13143
13784
  // GraphQL uses `any` type for UUID
13144
- organizationId: z31.any()
13785
+ organizationId: z33.any()
13145
13786
  // GraphQL uses `any` type for UUID
13146
13787
  });
13147
- var VulnerabilityReportSchema = z31.object({
13148
- scanDate: z31.any().nullable(),
13788
+ var VulnerabilityReportSchema = z33.object({
13789
+ scanDate: z33.any().nullable(),
13149
13790
  // GraphQL uses `any` type for timestamp
13150
- vendor: z31.string(),
13791
+ vendor: z33.string(),
13151
13792
  // GraphQL generates as string, not enum
13152
- projectId: z31.any().optional(),
13793
+ projectId: z33.any().optional(),
13153
13794
  // GraphQL uses `any` type for UUID
13154
13795
  project: ProjectSchema,
13155
13796
  totalVulnerabilityReportIssuesCount: VulnerabilityReportIssueAggregateSchema,
13156
13797
  notFixableVulnerabilityReportIssuesCount: VulnerabilityReportIssueAggregateSchema
13157
13798
  });
13158
- var FixReportSummarySchema = z31.object({
13159
- __typename: z31.literal("fixReport").optional(),
13160
- id: z31.any(),
13799
+ var FixReportSummarySchema = z33.object({
13800
+ __typename: z33.literal("fixReport").optional(),
13801
+ id: z33.any(),
13161
13802
  // GraphQL uses `any` type for UUID
13162
- createdOn: z31.any(),
13803
+ createdOn: z33.any(),
13163
13804
  // GraphQL uses `any` type for timestamp
13164
13805
  repo: RepoSchema.nullable(),
13165
- issueTypes: z31.any().nullable(),
13806
+ issueTypes: z33.any().nullable(),
13166
13807
  // GraphQL uses `any` type for JSON
13167
13808
  CRITICAL: FixAggregateSchema,
13168
13809
  HIGH: FixAggregateSchema,
13169
13810
  MEDIUM: FixAggregateSchema,
13170
13811
  LOW: FixAggregateSchema,
13171
- fixes: z31.array(McpFixSchema),
13172
- userFixes: z31.array(McpFixSchema).optional(),
13812
+ fixes: z33.array(McpFixSchema),
13813
+ userFixes: z33.array(McpFixSchema).optional(),
13173
13814
  // Present in some responses but can be omitted
13174
13815
  filteredFixesCount: FixAggregateSchema,
13175
13816
  totalFixesCount: FixAggregateSchema,
13176
13817
  vulnerabilityReport: VulnerabilityReportSchema
13177
13818
  });
13178
- var ExpiredReportSchema = z31.object({
13179
- __typename: z31.literal("fixReport").optional(),
13180
- id: z31.any(),
13819
+ var ExpiredReportSchema = z33.object({
13820
+ __typename: z33.literal("fixReport").optional(),
13821
+ id: z33.any(),
13181
13822
  // GraphQL uses `any` type for UUID
13182
- expirationOn: z31.any().nullable()
13823
+ expirationOn: z33.any().nullable()
13183
13824
  // GraphQL uses `any` type for timestamp
13184
13825
  });
13185
- var GetLatestReportByRepoUrlResponseSchema = z31.object({
13186
- __typename: z31.literal("query_root").optional(),
13187
- fixReport: z31.array(FixReportSummarySchema),
13188
- expiredReport: z31.array(ExpiredReportSchema)
13826
+ var GetLatestReportByRepoUrlResponseSchema = z33.object({
13827
+ __typename: z33.literal("query_root").optional(),
13828
+ fixReport: z33.array(FixReportSummarySchema),
13829
+ expiredReport: z33.array(ExpiredReportSchema)
13189
13830
  });
13190
13831
 
13191
13832
  // src/mcp/services/ConfigStoreService.ts
13192
- import Configstore5 from "configstore";
13833
+ import Configstore7 from "configstore";
13193
13834
  init_configs();
13194
13835
  function createConfigStore(defaultValues = { apiToken: "" }) {
13195
13836
  const API_URL2 = process.env["API_URL"] || MCP_DEFAULT_API_URL;
@@ -13201,7 +13842,7 @@ function createConfigStore(defaultValues = { apiToken: "" }) {
13201
13842
  domain = API_URL2.replace(/^https?:\/\//, "").replace(/\/.*$/, "").replace(/:\d+$/, "");
13202
13843
  }
13203
13844
  const sanitizedDomain = domain.replace(/\./g, "_");
13204
- return new Configstore5(
13845
+ return new Configstore7(
13205
13846
  `${packageJson.name}-${sanitizedDomain}`,
13206
13847
  defaultValues
13207
13848
  );
@@ -13213,7 +13854,7 @@ var configStore = getConfigStore();
13213
13854
 
13214
13855
  // src/mcp/services/McpAuthService.ts
13215
13856
  import crypto2 from "crypto";
13216
- import os2 from "os";
13857
+ import os3 from "os";
13217
13858
  import open4 from "open";
13218
13859
  init_configs();
13219
13860
  var McpAuthService = class {
@@ -13257,7 +13898,7 @@ var McpAuthService = class {
13257
13898
  }
13258
13899
  logDebug(`cli login created ${loginId}`);
13259
13900
  const webLoginUrl2 = `${WEB_APP_URL}/mvs-login`;
13260
- const browserUrl = `${webLoginUrl2}/${loginId}?hostname=${os2.hostname()}`;
13901
+ const browserUrl = `${webLoginUrl2}/${loginId}?hostname=${os3.hostname()}`;
13261
13902
  await this.openBrowser(browserUrl, isBackgoundCall);
13262
13903
  logDebug(`waiting for login to complete`);
13263
13904
  let newApiToken = null;
@@ -13918,8 +14559,8 @@ async function createAuthenticatedMcpGQLClient({
13918
14559
  // src/mcp/services/McpUsageService/host.ts
13919
14560
  import { execSync } from "child_process";
13920
14561
  import fs11 from "fs";
13921
- import os3 from "os";
13922
- import path11 from "path";
14562
+ import os4 from "os";
14563
+ import path13 from "path";
13923
14564
  var IDEs = ["cursor", "windsurf", "webstorm", "vscode", "claude"];
13924
14565
  var runCommand = (cmd) => {
13925
14566
  try {
@@ -13933,8 +14574,8 @@ var gitInfo = {
13933
14574
  email: runCommand("git config user.email")
13934
14575
  };
13935
14576
  var getClaudeWorkspacePaths = () => {
13936
- const home = os3.homedir();
13937
- const claudeIdePath = path11.join(home, ".claude", "ide");
14577
+ const home = os4.homedir();
14578
+ const claudeIdePath = path13.join(home, ".claude", "ide");
13938
14579
  const workspacePaths = [];
13939
14580
  if (!fs11.existsSync(claudeIdePath)) {
13940
14581
  return workspacePaths;
@@ -13942,7 +14583,7 @@ var getClaudeWorkspacePaths = () => {
13942
14583
  try {
13943
14584
  const lockFiles = fs11.readdirSync(claudeIdePath).filter((file) => file.endsWith(".lock"));
13944
14585
  for (const lockFile of lockFiles) {
13945
- const lockFilePath = path11.join(claudeIdePath, lockFile);
14586
+ const lockFilePath = path13.join(claudeIdePath, lockFile);
13946
14587
  try {
13947
14588
  const lockContent = JSON.parse(fs11.readFileSync(lockFilePath, "utf8"));
13948
14589
  if (lockContent.workspaceFolders && Array.isArray(lockContent.workspaceFolders)) {
@@ -13962,29 +14603,29 @@ var getClaudeWorkspacePaths = () => {
13962
14603
  return workspacePaths;
13963
14604
  };
13964
14605
  var getMCPConfigPaths = (hostName) => {
13965
- const home = os3.homedir();
14606
+ const home = os4.homedir();
13966
14607
  const currentDir = process.env["WORKSPACE_FOLDER_PATHS"] || process.env["PWD"] || process.cwd();
13967
14608
  switch (hostName.toLowerCase()) {
13968
14609
  case "cursor":
13969
14610
  return [
13970
- path11.join(currentDir, ".cursor", "mcp.json"),
14611
+ path13.join(currentDir, ".cursor", "mcp.json"),
13971
14612
  // local first
13972
- path11.join(home, ".cursor", "mcp.json")
14613
+ path13.join(home, ".cursor", "mcp.json")
13973
14614
  ];
13974
14615
  case "windsurf":
13975
14616
  return [
13976
- path11.join(currentDir, ".codeium", "mcp_config.json"),
14617
+ path13.join(currentDir, ".codeium", "mcp_config.json"),
13977
14618
  // local first
13978
- path11.join(home, ".codeium", "windsurf", "mcp_config.json")
14619
+ path13.join(home, ".codeium", "windsurf", "mcp_config.json")
13979
14620
  ];
13980
14621
  case "webstorm":
13981
14622
  return [];
13982
14623
  case "visualstudiocode":
13983
14624
  case "vscode":
13984
14625
  return [
13985
- path11.join(currentDir, ".vscode", "mcp.json"),
14626
+ path13.join(currentDir, ".vscode", "mcp.json"),
13986
14627
  // local first
13987
- process.platform === "win32" ? path11.join(home, "AppData", "Roaming", "Code", "User", "mcp.json") : path11.join(
14628
+ process.platform === "win32" ? path13.join(home, "AppData", "Roaming", "Code", "User", "mcp.json") : path13.join(
13988
14629
  home,
13989
14630
  "Library",
13990
14631
  "Application Support",
@@ -13995,13 +14636,13 @@ var getMCPConfigPaths = (hostName) => {
13995
14636
  ];
13996
14637
  case "claude": {
13997
14638
  const claudePaths = [
13998
- path11.join(currentDir, ".claude.json"),
14639
+ path13.join(currentDir, ".claude.json"),
13999
14640
  // local first
14000
- path11.join(home, ".claude.json")
14641
+ path13.join(home, ".claude.json")
14001
14642
  ];
14002
14643
  const workspacePaths = getClaudeWorkspacePaths();
14003
14644
  for (const workspacePath of workspacePaths) {
14004
- claudePaths.push(path11.join(workspacePath, ".mcp.json"));
14645
+ claudePaths.push(path13.join(workspacePath, ".mcp.json"));
14005
14646
  }
14006
14647
  return claudePaths;
14007
14648
  }
@@ -14018,41 +14659,41 @@ var readConfigFile = (filePath) => {
14018
14659
  return null;
14019
14660
  }
14020
14661
  };
14021
- var mergeConfigIntoResult = (config6, mergedConfig) => {
14022
- if (config6?.projects) {
14662
+ var mergeConfigIntoResult = (config7, mergedConfig) => {
14663
+ if (config7?.projects) {
14023
14664
  const allMcpServers = {};
14024
- for (const projectPath in config6.projects) {
14025
- const project = config6.projects[projectPath];
14665
+ for (const projectPath in config7.projects) {
14666
+ const project = config7.projects[projectPath];
14026
14667
  if (project?.mcpServers) {
14027
14668
  Object.assign(allMcpServers, project.mcpServers);
14028
14669
  }
14029
14670
  }
14030
14671
  mergedConfig.mcpServers = { ...mergedConfig.mcpServers, ...allMcpServers };
14031
14672
  }
14032
- if (config6?.mcpServers) {
14673
+ if (config7?.mcpServers) {
14033
14674
  mergedConfig.mcpServers = {
14034
14675
  ...mergedConfig.mcpServers,
14035
- ...config6.mcpServers
14676
+ ...config7.mcpServers
14036
14677
  };
14037
14678
  }
14038
- if (config6?.servers) {
14039
- mergedConfig.servers = { ...mergedConfig.servers, ...config6.servers };
14679
+ if (config7?.servers) {
14680
+ mergedConfig.servers = { ...mergedConfig.servers, ...config7.servers };
14040
14681
  }
14041
14682
  };
14042
14683
  var readMCPConfig = (hostName) => {
14043
14684
  const configPaths = getMCPConfigPaths(hostName);
14044
14685
  const mergedConfig = {};
14045
14686
  for (const configPath of configPaths) {
14046
- const config6 = readConfigFile(configPath);
14047
- if (config6) {
14048
- mergeConfigIntoResult(config6, mergedConfig);
14687
+ const config7 = readConfigFile(configPath);
14688
+ if (config7) {
14689
+ mergeConfigIntoResult(config7, mergedConfig);
14049
14690
  }
14050
14691
  }
14051
14692
  return Object.keys(mergedConfig).length > 0 ? mergedConfig : null;
14052
14693
  };
14053
14694
  var getRunningProcesses = () => {
14054
14695
  try {
14055
- return os3.platform() === "win32" ? execSync("tasklist", { encoding: "utf8" }) : execSync("ps aux", { encoding: "utf8" });
14696
+ return os4.platform() === "win32" ? execSync("tasklist", { encoding: "utf8" }) : execSync("ps aux", { encoding: "utf8" });
14056
14697
  } catch {
14057
14698
  return "";
14058
14699
  }
@@ -14127,7 +14768,7 @@ var versionCommands = {
14127
14768
  }
14128
14769
  };
14129
14770
  var getProcessInfo = (pid) => {
14130
- const platform2 = os3.platform();
14771
+ const platform2 = os4.platform();
14131
14772
  try {
14132
14773
  if (platform2 === "linux" || platform2 === "darwin") {
14133
14774
  const output = execSync(`ps -o pid=,ppid=,comm= -p ${pid}`, {
@@ -14162,20 +14803,20 @@ var getHostInfo = (additionalMcpList) => {
14162
14803
  const ideConfigPaths = /* @__PURE__ */ new Set();
14163
14804
  for (const ide of IDEs) {
14164
14805
  const configPaths = getMCPConfigPaths(ide);
14165
- configPaths.forEach((path21) => ideConfigPaths.add(path21));
14806
+ configPaths.forEach((path22) => ideConfigPaths.add(path22));
14166
14807
  }
14167
14808
  const uniqueAdditionalPaths = additionalMcpList.filter(
14168
- (path21) => !ideConfigPaths.has(path21)
14809
+ (path22) => !ideConfigPaths.has(path22)
14169
14810
  );
14170
14811
  for (const ide of IDEs) {
14171
14812
  const cfg = readMCPConfig(ide);
14172
14813
  if (cfg) allConfigs[ide] = cfg;
14173
14814
  }
14174
14815
  for (const additionalPath of uniqueAdditionalPaths) {
14175
- const config6 = readConfigFile(additionalPath);
14176
- if (!config6) continue;
14816
+ const config7 = readConfigFile(additionalPath);
14817
+ if (!config7) continue;
14177
14818
  const mergedConfig = {};
14178
- mergeConfigIntoResult(config6, mergedConfig);
14819
+ mergeConfigIntoResult(config7, mergedConfig);
14179
14820
  if (Object.keys(mergedConfig).length > 0) {
14180
14821
  allConfigs["system"] = mergedConfig;
14181
14822
  }
@@ -14243,10 +14884,10 @@ var getHostInfo = (additionalMcpList) => {
14243
14884
  }
14244
14885
  }
14245
14886
  for (const { ide, name, command, isRunning } of servers) {
14246
- const config6 = allConfigs[ide] || null;
14887
+ const config7 = allConfigs[ide] || null;
14247
14888
  const ideName = ide.charAt(0).toUpperCase() + ide.slice(1) || "Unknown";
14248
14889
  let ideVersion = "Unknown";
14249
- const platform2 = os3.platform();
14890
+ const platform2 = os4.platform();
14250
14891
  const cmds = versionCommands[ideName]?.[platform2] ?? [];
14251
14892
  for (const cmd of cmds) {
14252
14893
  try {
@@ -14260,8 +14901,8 @@ var getHostInfo = (additionalMcpList) => {
14260
14901
  }
14261
14902
  }
14262
14903
  let mcpConfigObj = {};
14263
- if (config6) {
14264
- const allServers = config6.mcpServers || config6.servers || {};
14904
+ if (config7) {
14905
+ const allServers = config7.mcpServers || config7.servers || {};
14265
14906
  if (name in allServers && allServers[name]) {
14266
14907
  mcpConfigObj = allServers[name];
14267
14908
  }
@@ -14279,15 +14920,15 @@ var getHostInfo = (additionalMcpList) => {
14279
14920
 
14280
14921
  // src/mcp/services/McpUsageService/McpUsageService.ts
14281
14922
  import fetch5 from "node-fetch";
14282
- import os5 from "os";
14923
+ import os6 from "os";
14283
14924
  import { v4 as uuidv43, v5 as uuidv5 } from "uuid";
14284
14925
  init_configs();
14285
14926
 
14286
14927
  // src/mcp/services/McpUsageService/system.ts
14287
14928
  init_configs();
14288
14929
  import fs12 from "fs";
14289
- import os4 from "os";
14290
- import path12 from "path";
14930
+ import os5 from "os";
14931
+ import path14 from "path";
14291
14932
  var MAX_DEPTH = 2;
14292
14933
  var patterns = ["mcp", "claude"];
14293
14934
  var isFileMatch = (fileName) => {
@@ -14307,7 +14948,7 @@ var searchDir = async (dir, depth = 0) => {
14307
14948
  if (depth > MAX_DEPTH) return results;
14308
14949
  const entries = await fs12.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
14309
14950
  for (const entry of entries) {
14310
- const fullPath = path12.join(dir, entry.name);
14951
+ const fullPath = path14.join(dir, entry.name);
14311
14952
  if (entry.isFile() && isFileMatch(entry.name)) {
14312
14953
  results.push(fullPath);
14313
14954
  } else if (entry.isDirectory()) {
@@ -14321,17 +14962,17 @@ var searchDir = async (dir, depth = 0) => {
14321
14962
  };
14322
14963
  var findSystemMCPConfigs = async () => {
14323
14964
  try {
14324
- const home = os4.homedir();
14325
- const platform2 = os4.platform();
14965
+ const home = os5.homedir();
14966
+ const platform2 = os5.platform();
14326
14967
  const knownDirs = platform2 === "win32" ? [
14327
- path12.join(home, ".cursor"),
14328
- path12.join(home, "Documents"),
14329
- path12.join(home, "Downloads")
14968
+ path14.join(home, ".cursor"),
14969
+ path14.join(home, "Documents"),
14970
+ path14.join(home, "Downloads")
14330
14971
  ] : [
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")
14972
+ path14.join(home, ".cursor"),
14973
+ process.env["XDG_CONFIG_HOME"] || path14.join(home, ".config"),
14974
+ path14.join(home, "Documents"),
14975
+ path14.join(home, "Downloads")
14335
14976
  ];
14336
14977
  const timeoutPromise = new Promise(
14337
14978
  (resolve) => setTimeout(() => {
@@ -14394,7 +15035,7 @@ var McpUsageService = class {
14394
15035
  generateHostId() {
14395
15036
  const stored = configStore.get(this.configKey);
14396
15037
  if (stored?.mcpHostId) return stored.mcpHostId;
14397
- const interfaces = os5.networkInterfaces();
15038
+ const interfaces = os6.networkInterfaces();
14398
15039
  const macs = [];
14399
15040
  for (const iface of Object.values(interfaces)) {
14400
15041
  if (!iface) continue;
@@ -14402,7 +15043,7 @@ var McpUsageService = class {
14402
15043
  if (net.mac && net.mac !== "00:00:00:00:00:00") macs.push(net.mac);
14403
15044
  }
14404
15045
  }
14405
- const macString = macs.length ? macs.sort().join(",") : `${os5.hostname()}-${uuidv43()}`;
15046
+ const macString = macs.length ? macs.sort().join(",") : `${os6.hostname()}-${uuidv43()}`;
14406
15047
  const hostId = uuidv5(macString, uuidv5.DNS);
14407
15048
  logDebug("[UsageService] Generated new host ID", { hostId });
14408
15049
  return hostId;
@@ -14425,7 +15066,7 @@ var McpUsageService = class {
14425
15066
  mcpHostId,
14426
15067
  organizationId,
14427
15068
  mcpVersion: packageJson.version,
14428
- mcpOsName: os5.platform(),
15069
+ mcpOsName: os6.platform(),
14429
15070
  mcps: JSON.stringify(mcps),
14430
15071
  status,
14431
15072
  userName: user.name,
@@ -14599,7 +15240,7 @@ var ToolRegistry = class {
14599
15240
 
14600
15241
  // src/mcp/core/McpServer.ts
14601
15242
  var McpServer = class {
14602
- constructor(config6, govOrgId = "") {
15243
+ constructor(config7, govOrgId = "") {
14603
15244
  __publicField(this, "server");
14604
15245
  __publicField(this, "toolRegistry");
14605
15246
  __publicField(this, "promptRegistry");
@@ -14613,8 +15254,8 @@ var McpServer = class {
14613
15254
  this.mcpUsageService = govOrgId ? new McpUsageService(govOrgId) : null;
14614
15255
  this.server = new Server(
14615
15256
  {
14616
- name: config6.name,
14617
- version: config6.version
15257
+ name: config7.name,
15258
+ version: config7.version
14618
15259
  },
14619
15260
  {
14620
15261
  capabilities: {
@@ -14630,7 +15271,7 @@ var McpServer = class {
14630
15271
  this.setupParentProcessMonitoring();
14631
15272
  logInfo("MCP server instance created");
14632
15273
  logDebug("MCP server instance config", {
14633
- config: config6,
15274
+ config: config7,
14634
15275
  parentPid: this.parentPid
14635
15276
  });
14636
15277
  }
@@ -15088,10 +15729,10 @@ var McpServer = class {
15088
15729
  };
15089
15730
 
15090
15731
  // src/mcp/prompts/CheckForNewVulnerabilitiesPrompt.ts
15091
- import { z as z33 } from "zod";
15732
+ import { z as z35 } from "zod";
15092
15733
 
15093
15734
  // src/mcp/prompts/base/BasePrompt.ts
15094
- import { z as z32 } from "zod";
15735
+ import { z as z34 } from "zod";
15095
15736
  var BasePrompt = class {
15096
15737
  getDefinition() {
15097
15738
  return {
@@ -15120,7 +15761,7 @@ var BasePrompt = class {
15120
15761
  const argsToValidate = args === void 0 ? {} : args;
15121
15762
  return this.argumentsValidationSchema.parse(argsToValidate);
15122
15763
  } catch (error) {
15123
- if (error instanceof z32.ZodError) {
15764
+ if (error instanceof z34.ZodError) {
15124
15765
  const errorDetails = error.errors.map((e) => {
15125
15766
  const fieldPath = e.path.length > 0 ? e.path.join(".") : "root";
15126
15767
  const message = e.message === "Required" ? `Missing required argument '${fieldPath}'` : `Invalid value for '${fieldPath}': ${e.message}`;
@@ -15149,8 +15790,8 @@ var BasePrompt = class {
15149
15790
  };
15150
15791
 
15151
15792
  // src/mcp/prompts/CheckForNewVulnerabilitiesPrompt.ts
15152
- var CheckForNewVulnerabilitiesArgsSchema = z33.object({
15153
- path: z33.string().optional()
15793
+ var CheckForNewVulnerabilitiesArgsSchema = z35.object({
15794
+ path: z35.string().optional()
15154
15795
  });
15155
15796
  var CheckForNewVulnerabilitiesPrompt = class extends BasePrompt {
15156
15797
  constructor() {
@@ -15395,9 +16036,9 @@ Call the \`check_for_new_available_fixes\` tool now${args?.path ? ` for ${args.p
15395
16036
  };
15396
16037
 
15397
16038
  // src/mcp/prompts/FullSecurityAuditPrompt.ts
15398
- import { z as z34 } from "zod";
15399
- var FullSecurityAuditArgsSchema = z34.object({
15400
- path: z34.string().optional()
16039
+ import { z as z36 } from "zod";
16040
+ var FullSecurityAuditArgsSchema = z36.object({
16041
+ path: z36.string().optional()
15401
16042
  });
15402
16043
  var FullSecurityAuditPrompt = class extends BasePrompt {
15403
16044
  constructor() {
@@ -15848,9 +16489,9 @@ Begin the audit now${args?.path ? ` for ${args.path}` : ""}.
15848
16489
  };
15849
16490
 
15850
16491
  // src/mcp/prompts/ReviewAndFixCriticalPrompt.ts
15851
- import { z as z35 } from "zod";
15852
- var ReviewAndFixCriticalArgsSchema = z35.object({
15853
- path: z35.string().optional()
16492
+ import { z as z37 } from "zod";
16493
+ var ReviewAndFixCriticalArgsSchema = z37.object({
16494
+ path: z37.string().optional()
15854
16495
  });
15855
16496
  var ReviewAndFixCriticalPrompt = class extends BasePrompt {
15856
16497
  constructor() {
@@ -16154,9 +16795,9 @@ Start by scanning${args?.path ? ` ${args.path}` : " the repository"} and priorit
16154
16795
  };
16155
16796
 
16156
16797
  // src/mcp/prompts/ScanRecentChangesPrompt.ts
16157
- import { z as z36 } from "zod";
16158
- var ScanRecentChangesArgsSchema = z36.object({
16159
- path: z36.string().optional()
16798
+ import { z as z38 } from "zod";
16799
+ var ScanRecentChangesArgsSchema = z38.object({
16800
+ path: z38.string().optional()
16160
16801
  });
16161
16802
  var ScanRecentChangesPrompt = class extends BasePrompt {
16162
16803
  constructor() {
@@ -16367,9 +17008,9 @@ You now have the guidance needed to perform a fast, targeted security scan of re
16367
17008
  };
16368
17009
 
16369
17010
  // src/mcp/prompts/ScanRepositoryPrompt.ts
16370
- import { z as z37 } from "zod";
16371
- var ScanRepositoryArgsSchema = z37.object({
16372
- path: z37.string().optional()
17011
+ import { z as z39 } from "zod";
17012
+ var ScanRepositoryArgsSchema = z39.object({
17013
+ path: z39.string().optional()
16373
17014
  });
16374
17015
  var ScanRepositoryPrompt = class extends BasePrompt {
16375
17016
  constructor() {
@@ -16748,30 +17389,30 @@ For a complete security audit workflow, use the \`full-security-audit\` prompt.
16748
17389
 
16749
17390
  // src/mcp/services/McpDetectionService/CursorMcpDetectionService.ts
16750
17391
  import * as fs15 from "fs";
16751
- import * as os7 from "os";
16752
- import * as path14 from "path";
17392
+ import * as os8 from "os";
17393
+ import * as path16 from "path";
16753
17394
 
16754
17395
  // src/mcp/services/McpDetectionService/BaseMcpDetectionService.ts
16755
17396
  init_configs();
16756
17397
  import * as fs14 from "fs";
16757
17398
  import fetch6 from "node-fetch";
16758
- import * as path13 from "path";
17399
+ import * as path15 from "path";
16759
17400
 
16760
17401
  // src/mcp/services/McpDetectionService/McpDetectionServiceUtils.ts
16761
17402
  import * as fs13 from "fs";
16762
- import * as os6 from "os";
17403
+ import * as os7 from "os";
16763
17404
 
16764
17405
  // src/mcp/services/McpDetectionService/VscodeMcpDetectionService.ts
16765
17406
  import * as fs16 from "fs";
16766
- import * as os8 from "os";
16767
- import * as path15 from "path";
17407
+ import * as os9 from "os";
17408
+ import * as path17 from "path";
16768
17409
 
16769
17410
  // src/mcp/tools/checkForNewAvailableFixes/CheckForNewAvailableFixesTool.ts
16770
- import { z as z40 } from "zod";
17411
+ import { z as z42 } from "zod";
16771
17412
 
16772
17413
  // src/mcp/services/PathValidation.ts
16773
17414
  import fs17 from "fs";
16774
- import path16 from "path";
17415
+ import path18 from "path";
16775
17416
  async function validatePath(inputPath) {
16776
17417
  logDebug("Validating MCP path", { inputPath });
16777
17418
  if (/^\/[a-zA-Z]:\//.test(inputPath)) {
@@ -16803,7 +17444,7 @@ async function validatePath(inputPath) {
16803
17444
  logError(error);
16804
17445
  return { isValid: false, error, path: inputPath };
16805
17446
  }
16806
- const normalizedPath = path16.normalize(inputPath);
17447
+ const normalizedPath = path18.normalize(inputPath);
16807
17448
  if (normalizedPath.includes("..")) {
16808
17449
  const error = `Normalized path contains path traversal patterns: ${inputPath}`;
16809
17450
  logError(error);
@@ -16843,7 +17484,7 @@ async function validatePath(inputPath) {
16843
17484
  }
16844
17485
 
16845
17486
  // src/mcp/tools/base/BaseTool.ts
16846
- import { z as z38 } from "zod";
17487
+ import { z as z40 } from "zod";
16847
17488
  var BaseTool = class {
16848
17489
  getDefinition() {
16849
17490
  return {
@@ -16873,7 +17514,7 @@ var BaseTool = class {
16873
17514
  try {
16874
17515
  return this.inputValidationSchema.parse(args);
16875
17516
  } catch (error) {
16876
- if (error instanceof z38.ZodError) {
17517
+ if (error instanceof z40.ZodError) {
16877
17518
  const errorDetails = error.errors.map((e) => {
16878
17519
  const fieldPath = e.path.length > 0 ? e.path.join(".") : "root";
16879
17520
  const message = e.message === "Required" ? `Missing required parameter '${fieldPath}'` : `Invalid value for '${fieldPath}': ${e.message}`;
@@ -17457,7 +18098,7 @@ init_configs();
17457
18098
  import fs18 from "fs/promises";
17458
18099
  import nodePath from "path";
17459
18100
  var getLocalFiles = async ({
17460
- path: path21,
18101
+ path: path22,
17461
18102
  maxFileSize = MCP_MAX_FILE_SIZE,
17462
18103
  maxFiles,
17463
18104
  isAllFilesScan,
@@ -17465,17 +18106,17 @@ var getLocalFiles = async ({
17465
18106
  scanRecentlyChangedFiles
17466
18107
  }) => {
17467
18108
  logDebug(`[${scanContext}] Starting getLocalFiles`, {
17468
- path: path21,
18109
+ path: path22,
17469
18110
  maxFileSize,
17470
18111
  maxFiles,
17471
18112
  isAllFilesScan,
17472
18113
  scanRecentlyChangedFiles
17473
18114
  });
17474
18115
  try {
17475
- const resolvedRepoPath = await fs18.realpath(path21);
18116
+ const resolvedRepoPath = await fs18.realpath(path22);
17476
18117
  logDebug(`[${scanContext}] Resolved repository path`, {
17477
18118
  resolvedRepoPath,
17478
- originalPath: path21
18119
+ originalPath: path22
17479
18120
  });
17480
18121
  const gitService = new GitService(resolvedRepoPath, log);
17481
18122
  const gitValidation = await gitService.validateRepository();
@@ -17488,7 +18129,7 @@ var getLocalFiles = async ({
17488
18129
  if (!gitValidation.isValid || isAllFilesScan) {
17489
18130
  try {
17490
18131
  files = await FileUtils.getLastChangedFiles({
17491
- dir: path21,
18132
+ dir: path22,
17492
18133
  maxFileSize,
17493
18134
  maxFiles,
17494
18135
  isAllFilesScan
@@ -17580,7 +18221,7 @@ var getLocalFiles = async ({
17580
18221
  logError(`${scanContext}Unexpected error in getLocalFiles`, {
17581
18222
  error: error instanceof Error ? error.message : String(error),
17582
18223
  stack: error instanceof Error ? error.stack : void 0,
17583
- path: path21
18224
+ path: path22
17584
18225
  });
17585
18226
  throw error;
17586
18227
  }
@@ -17588,15 +18229,15 @@ var getLocalFiles = async ({
17588
18229
 
17589
18230
  // src/mcp/services/LocalMobbFolderService.ts
17590
18231
  import fs19 from "fs";
17591
- import path17 from "path";
17592
- import { z as z39 } from "zod";
18232
+ import path19 from "path";
18233
+ import { z as z41 } from "zod";
17593
18234
  init_GitService();
17594
18235
  function extractPathFromPatch(patch) {
17595
18236
  const match = patch?.match(/diff --git a\/([^\s]+) b\//);
17596
18237
  return match?.[1] ?? null;
17597
18238
  }
17598
18239
  function parsedIssueTypeRes(issueType) {
17599
- return z39.nativeEnum(IssueType_Enum).safeParse(issueType);
18240
+ return z41.nativeEnum(IssueType_Enum).safeParse(issueType);
17600
18241
  }
17601
18242
  var LocalMobbFolderService = class {
17602
18243
  /**
@@ -17675,7 +18316,7 @@ var LocalMobbFolderService = class {
17675
18316
  "[LocalMobbFolderService] Non-git repository detected, skipping .gitignore operations"
17676
18317
  );
17677
18318
  }
17678
- const mobbFolderPath = path17.join(
18319
+ const mobbFolderPath = path19.join(
17679
18320
  this.repoPath,
17680
18321
  this.defaultMobbFolderName
17681
18322
  );
@@ -17847,7 +18488,7 @@ var LocalMobbFolderService = class {
17847
18488
  mobbFolderPath,
17848
18489
  baseFileName
17849
18490
  );
17850
- const filePath = path17.join(mobbFolderPath, uniqueFileName);
18491
+ const filePath = path19.join(mobbFolderPath, uniqueFileName);
17851
18492
  await fs19.promises.writeFile(filePath, patch, "utf8");
17852
18493
  logInfo("[LocalMobbFolderService] Patch saved successfully", {
17853
18494
  filePath,
@@ -17905,11 +18546,11 @@ var LocalMobbFolderService = class {
17905
18546
  * @returns Unique filename that doesn't conflict with existing files
17906
18547
  */
17907
18548
  getUniqueFileName(folderPath, baseFileName) {
17908
- const baseName = path17.parse(baseFileName).name;
17909
- const extension = path17.parse(baseFileName).ext;
18549
+ const baseName = path19.parse(baseFileName).name;
18550
+ const extension = path19.parse(baseFileName).ext;
17910
18551
  let uniqueFileName = baseFileName;
17911
18552
  let index = 1;
17912
- while (fs19.existsSync(path17.join(folderPath, uniqueFileName))) {
18553
+ while (fs19.existsSync(path19.join(folderPath, uniqueFileName))) {
17913
18554
  uniqueFileName = `${baseName}-${index}${extension}`;
17914
18555
  index++;
17915
18556
  if (index > 1e3) {
@@ -17940,7 +18581,7 @@ var LocalMobbFolderService = class {
17940
18581
  logDebug("[LocalMobbFolderService] Logging patch info", { fixId: fix.id });
17941
18582
  try {
17942
18583
  const mobbFolderPath = await this.getFolder();
17943
- const patchInfoPath = path17.join(mobbFolderPath, "patchInfo.md");
18584
+ const patchInfoPath = path19.join(mobbFolderPath, "patchInfo.md");
17944
18585
  const markdownContent = this.generateFixMarkdown(fix, savedPatchFileName);
17945
18586
  let existingContent = "";
17946
18587
  if (fs19.existsSync(patchInfoPath)) {
@@ -17982,7 +18623,7 @@ var LocalMobbFolderService = class {
17982
18623
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
17983
18624
  const patch = this.extractPatchFromFix(fix);
17984
18625
  const relativePatchedFilePath = patch ? extractPathFromPatch(patch) : null;
17985
- const patchedFilePath = relativePatchedFilePath ? path17.resolve(this.repoPath, relativePatchedFilePath) : null;
18626
+ const patchedFilePath = relativePatchedFilePath ? path19.resolve(this.repoPath, relativePatchedFilePath) : null;
17986
18627
  const fixIdentifier = savedPatchFileName ? savedPatchFileName.replace(".patch", "") : fix.id;
17987
18628
  let markdown = `# Fix ${fixIdentifier}
17988
18629
 
@@ -18326,14 +18967,14 @@ import {
18326
18967
  } from "fs";
18327
18968
  import fs20 from "fs/promises";
18328
18969
  import parseDiff2 from "parse-diff";
18329
- import path18 from "path";
18970
+ import path20 from "path";
18330
18971
  var PatchApplicationService = class {
18331
18972
  /**
18332
18973
  * Gets the appropriate comment syntax for a file based on its extension
18333
18974
  */
18334
18975
  static getCommentSyntax(filePath) {
18335
- const ext = path18.extname(filePath).toLowerCase();
18336
- const basename2 = path18.basename(filePath);
18976
+ const ext = path20.extname(filePath).toLowerCase();
18977
+ const basename2 = path20.basename(filePath);
18337
18978
  const commentMap = {
18338
18979
  // C-style languages (single line comments)
18339
18980
  ".js": "//",
@@ -18536,7 +19177,7 @@ var PatchApplicationService = class {
18536
19177
  }
18537
19178
  );
18538
19179
  }
18539
- const dirPath = path18.dirname(filePath);
19180
+ const dirPath = path20.dirname(filePath);
18540
19181
  mkdirSync(dirPath, { recursive: true });
18541
19182
  writeFileSync(filePath, finalContent, "utf8");
18542
19183
  return filePath;
@@ -18820,7 +19461,7 @@ var PatchApplicationService = class {
18820
19461
  continue;
18821
19462
  }
18822
19463
  try {
18823
- const absolutePath = path18.resolve(repositoryPath, targetFile);
19464
+ const absolutePath = path20.resolve(repositoryPath, targetFile);
18824
19465
  if (existsSync6(absolutePath)) {
18825
19466
  const stats = await fs20.stat(absolutePath);
18826
19467
  const fileModTime = stats.mtime.getTime();
@@ -19011,11 +19652,11 @@ var PatchApplicationService = class {
19011
19652
  }) {
19012
19653
  const sanitizedRepoPath = String(repositoryPath || "").replace("\0", "").replace(/^(\.\.(\/|\\))+/, "");
19013
19654
  const sanitizedTargetFile = String(targetFile || "").replace("\0", "").replace(/^(\.\.(\/|\\))+/, "");
19014
- const absoluteFilePath = path18.resolve(
19655
+ const absoluteFilePath = path20.resolve(
19015
19656
  sanitizedRepoPath,
19016
19657
  sanitizedTargetFile
19017
19658
  );
19018
- const relativePath = path18.relative(sanitizedRepoPath, absoluteFilePath);
19659
+ const relativePath = path20.relative(sanitizedRepoPath, absoluteFilePath);
19019
19660
  if (relativePath.startsWith("..")) {
19020
19661
  throw new Error(
19021
19662
  `Security violation: target file ${targetFile} resolves outside repository`
@@ -19049,7 +19690,7 @@ var PatchApplicationService = class {
19049
19690
  fix,
19050
19691
  scanContext
19051
19692
  });
19052
- appliedFiles.push(path18.relative(repositoryPath, actualPath));
19693
+ appliedFiles.push(path20.relative(repositoryPath, actualPath));
19053
19694
  logDebug(`[${scanContext}] Created new file: ${relativePath}`);
19054
19695
  }
19055
19696
  /**
@@ -19097,7 +19738,7 @@ var PatchApplicationService = class {
19097
19738
  fix,
19098
19739
  scanContext
19099
19740
  });
19100
- appliedFiles.push(path18.relative(repositoryPath, actualPath));
19741
+ appliedFiles.push(path20.relative(repositoryPath, actualPath));
19101
19742
  logDebug(`[${scanContext}] Modified file: ${relativePath}`);
19102
19743
  }
19103
19744
  }
@@ -19293,7 +19934,7 @@ init_configs();
19293
19934
  // src/mcp/services/FileOperations.ts
19294
19935
  init_FileUtils();
19295
19936
  import fs21 from "fs";
19296
- import path19 from "path";
19937
+ import path21 from "path";
19297
19938
  import AdmZip2 from "adm-zip";
19298
19939
  var FileOperations = class {
19299
19940
  /**
@@ -19313,10 +19954,10 @@ var FileOperations = class {
19313
19954
  let packedFilesCount = 0;
19314
19955
  const packedFiles = [];
19315
19956
  const excludedFiles = [];
19316
- const resolvedRepoPath = path19.resolve(repositoryPath);
19957
+ const resolvedRepoPath = path21.resolve(repositoryPath);
19317
19958
  for (const filepath of fileList) {
19318
- const absoluteFilepath = path19.join(repositoryPath, filepath);
19319
- const resolvedFilePath = path19.resolve(absoluteFilepath);
19959
+ const absoluteFilepath = path21.join(repositoryPath, filepath);
19960
+ const resolvedFilePath = path21.resolve(absoluteFilepath);
19320
19961
  if (!resolvedFilePath.startsWith(resolvedRepoPath)) {
19321
19962
  const reason = "potential path traversal security risk";
19322
19963
  logDebug(`[FileOperations] Skipping ${filepath} due to ${reason}`);
@@ -19363,11 +20004,11 @@ var FileOperations = class {
19363
20004
  fileList,
19364
20005
  repositoryPath
19365
20006
  }) {
19366
- const resolvedRepoPath = path19.resolve(repositoryPath);
20007
+ const resolvedRepoPath = path21.resolve(repositoryPath);
19367
20008
  const validatedPaths = [];
19368
20009
  for (const filepath of fileList) {
19369
- const absoluteFilepath = path19.join(repositoryPath, filepath);
19370
- const resolvedFilePath = path19.resolve(absoluteFilepath);
20010
+ const absoluteFilepath = path21.join(repositoryPath, filepath);
20011
+ const resolvedFilePath = path21.resolve(absoluteFilepath);
19371
20012
  if (!resolvedFilePath.startsWith(resolvedRepoPath)) {
19372
20013
  logDebug(
19373
20014
  `[FileOperations] Rejecting ${filepath} - path traversal attempt detected`
@@ -19395,7 +20036,7 @@ var FileOperations = class {
19395
20036
  for (const absolutePath of filePaths) {
19396
20037
  try {
19397
20038
  const content = await fs21.promises.readFile(absolutePath);
19398
- const relativePath = path19.basename(absolutePath);
20039
+ const relativePath = path21.basename(absolutePath);
19399
20040
  fileDataArray.push({
19400
20041
  relativePath,
19401
20042
  absolutePath,
@@ -19707,14 +20348,14 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
19707
20348
  * since the last scan.
19708
20349
  */
19709
20350
  async scanForSecurityVulnerabilities({
19710
- path: path21,
20351
+ path: path22,
19711
20352
  isAllDetectionRulesScan,
19712
20353
  isAllFilesScan,
19713
20354
  scanContext
19714
20355
  }) {
19715
20356
  this.hasAuthenticationFailed = false;
19716
20357
  logDebug(`[${scanContext}] Scanning for new security vulnerabilities`, {
19717
- path: path21
20358
+ path: path22
19718
20359
  });
19719
20360
  if (!this.gqlClient) {
19720
20361
  logInfo(`[${scanContext}] No GQL client found, skipping scan`);
@@ -19730,11 +20371,11 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
19730
20371
  }
19731
20372
  logDebug(
19732
20373
  `[${scanContext}] Connected to the API, assembling list of files to scan`,
19733
- { path: path21 }
20374
+ { path: path22 }
19734
20375
  );
19735
20376
  const isBackgroundScan = scanContext === ScanContext.BACKGROUND_INITIAL || scanContext === ScanContext.BACKGROUND_PERIODIC;
19736
20377
  const files = await getLocalFiles({
19737
- path: path21,
20378
+ path: path22,
19738
20379
  isAllFilesScan,
19739
20380
  scanContext,
19740
20381
  scanRecentlyChangedFiles: !isBackgroundScan
@@ -19760,13 +20401,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
19760
20401
  });
19761
20402
  const { fixReportId, projectId } = await scanFiles({
19762
20403
  fileList: filesToScan.map((file) => file.relativePath),
19763
- repositoryPath: path21,
20404
+ repositoryPath: path22,
19764
20405
  gqlClient: this.gqlClient,
19765
20406
  isAllDetectionRulesScan,
19766
20407
  scanContext
19767
20408
  });
19768
20409
  logInfo(
19769
- `[${scanContext}] Security scan completed for ${path21} reportId: ${fixReportId} projectId: ${projectId}`
20410
+ `[${scanContext}] Security scan completed for ${path22} reportId: ${fixReportId} projectId: ${projectId}`
19770
20411
  );
19771
20412
  if (isAllFilesScan) {
19772
20413
  return;
@@ -20060,13 +20701,13 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
20060
20701
  });
20061
20702
  return scannedFiles.some((file) => file.relativePath === fixFile);
20062
20703
  }
20063
- async getFreshFixes({ path: path21 }) {
20704
+ async getFreshFixes({ path: path22 }) {
20064
20705
  const scanContext = ScanContext.USER_REQUEST;
20065
- logDebug(`[${scanContext}] Getting fresh fixes`, { path: path21 });
20066
- if (this.path !== path21) {
20067
- this.path = path21;
20706
+ logDebug(`[${scanContext}] Getting fresh fixes`, { path: path22 });
20707
+ if (this.path !== path22) {
20708
+ this.path = path22;
20068
20709
  this.reset();
20069
- logInfo(`[${scanContext}] Reset service state for new path`, { path: path21 });
20710
+ logInfo(`[${scanContext}] Reset service state for new path`, { path: path22 });
20070
20711
  }
20071
20712
  try {
20072
20713
  this.gqlClient = await createAuthenticatedMcpGQLClient();
@@ -20084,7 +20725,7 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
20084
20725
  }
20085
20726
  throw error;
20086
20727
  }
20087
- this.triggerScan({ path: path21, gqlClient: this.gqlClient });
20728
+ this.triggerScan({ path: path22, gqlClient: this.gqlClient });
20088
20729
  let isMvsAutoFixEnabled = null;
20089
20730
  try {
20090
20731
  isMvsAutoFixEnabled = await this.gqlClient.getMvsAutoFixSettings();
@@ -20118,33 +20759,33 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
20118
20759
  return noFreshFixesPrompt;
20119
20760
  }
20120
20761
  triggerScan({
20121
- path: path21,
20762
+ path: path22,
20122
20763
  gqlClient
20123
20764
  }) {
20124
- if (this.path !== path21) {
20125
- this.path = path21;
20765
+ if (this.path !== path22) {
20766
+ this.path = path22;
20126
20767
  this.reset();
20127
- logInfo(`Reset service state for new path in triggerScan`, { path: path21 });
20768
+ logInfo(`Reset service state for new path in triggerScan`, { path: path22 });
20128
20769
  }
20129
20770
  this.gqlClient = gqlClient;
20130
20771
  if (!this.intervalId) {
20131
- this.startPeriodicScanning(path21);
20132
- this.executeInitialScan(path21);
20133
- void this.executeInitialFullScan(path21);
20772
+ this.startPeriodicScanning(path22);
20773
+ this.executeInitialScan(path22);
20774
+ void this.executeInitialFullScan(path22);
20134
20775
  }
20135
20776
  }
20136
- startPeriodicScanning(path21) {
20777
+ startPeriodicScanning(path22) {
20137
20778
  const scanContext = ScanContext.BACKGROUND_PERIODIC;
20138
20779
  logDebug(
20139
20780
  `[${scanContext}] Starting periodic scan for new security vulnerabilities`,
20140
20781
  {
20141
- path: path21
20782
+ path: path22
20142
20783
  }
20143
20784
  );
20144
20785
  this.intervalId = setInterval(() => {
20145
- logDebug(`[${scanContext}] Triggering periodic security scan`, { path: path21 });
20786
+ logDebug(`[${scanContext}] Triggering periodic security scan`, { path: path22 });
20146
20787
  this.scanForSecurityVulnerabilities({
20147
- path: path21,
20788
+ path: path22,
20148
20789
  scanContext
20149
20790
  }).catch((error) => {
20150
20791
  logError(`[${scanContext}] Error during periodic security scan`, {
@@ -20153,45 +20794,45 @@ var _CheckForNewAvailableFixesService = class _CheckForNewAvailableFixesService
20153
20794
  });
20154
20795
  }, MCP_PERIODIC_CHECK_INTERVAL);
20155
20796
  }
20156
- async executeInitialFullScan(path21) {
20797
+ async executeInitialFullScan(path22) {
20157
20798
  const scanContext = ScanContext.FULL_SCAN;
20158
- logDebug(`[${scanContext}] Triggering initial full security scan`, { path: path21 });
20799
+ logDebug(`[${scanContext}] Triggering initial full security scan`, { path: path22 });
20159
20800
  logDebug(`[${scanContext}] Full scan paths scanned`, {
20160
20801
  fullScanPathsScanned: this.fullScanPathsScanned
20161
20802
  });
20162
- if (this.fullScanPathsScanned.includes(path21)) {
20803
+ if (this.fullScanPathsScanned.includes(path22)) {
20163
20804
  logDebug(`[${scanContext}] Full scan already executed for this path`, {
20164
- path: path21
20805
+ path: path22
20165
20806
  });
20166
20807
  return;
20167
20808
  }
20168
20809
  configStore.set("fullScanPathsScanned", [
20169
20810
  ...this.fullScanPathsScanned,
20170
- path21
20811
+ path22
20171
20812
  ]);
20172
20813
  try {
20173
20814
  await this.scanForSecurityVulnerabilities({
20174
- path: path21,
20815
+ path: path22,
20175
20816
  isAllFilesScan: true,
20176
20817
  isAllDetectionRulesScan: true,
20177
20818
  scanContext: ScanContext.FULL_SCAN
20178
20819
  });
20179
- if (!this.fullScanPathsScanned.includes(path21)) {
20180
- this.fullScanPathsScanned.push(path21);
20820
+ if (!this.fullScanPathsScanned.includes(path22)) {
20821
+ this.fullScanPathsScanned.push(path22);
20181
20822
  configStore.set("fullScanPathsScanned", this.fullScanPathsScanned);
20182
20823
  }
20183
- logInfo(`[${scanContext}] Full scan completed`, { path: path21 });
20824
+ logInfo(`[${scanContext}] Full scan completed`, { path: path22 });
20184
20825
  } catch (error) {
20185
20826
  logError(`[${scanContext}] Error during initial full security scan`, {
20186
20827
  error
20187
20828
  });
20188
20829
  }
20189
20830
  }
20190
- executeInitialScan(path21) {
20831
+ executeInitialScan(path22) {
20191
20832
  const scanContext = ScanContext.BACKGROUND_INITIAL;
20192
- logDebug(`[${scanContext}] Triggering initial security scan`, { path: path21 });
20833
+ logDebug(`[${scanContext}] Triggering initial security scan`, { path: path22 });
20193
20834
  this.scanForSecurityVulnerabilities({
20194
- path: path21,
20835
+ path: path22,
20195
20836
  scanContext: ScanContext.BACKGROUND_INITIAL
20196
20837
  }).catch((error) => {
20197
20838
  logError(`[${scanContext}] Error during initial security scan`, { error });
@@ -20270,8 +20911,8 @@ Example payload:
20270
20911
  },
20271
20912
  required: ["path"]
20272
20913
  });
20273
- __publicField(this, "inputValidationSchema", z40.object({
20274
- path: z40.string().describe(
20914
+ __publicField(this, "inputValidationSchema", z42.object({
20915
+ path: z42.string().describe(
20275
20916
  "Full local path to the cloned git repository to check for new available fixes"
20276
20917
  )
20277
20918
  }));
@@ -20288,9 +20929,9 @@ Example payload:
20288
20929
  `Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
20289
20930
  );
20290
20931
  }
20291
- const path21 = pathValidationResult.path;
20932
+ const path22 = pathValidationResult.path;
20292
20933
  const resultText = await this.newFixesService.getFreshFixes({
20293
- path: path21
20934
+ path: path22
20294
20935
  });
20295
20936
  logInfo("CheckForNewAvailableFixesTool execution completed", {
20296
20937
  resultText
@@ -20301,7 +20942,7 @@ Example payload:
20301
20942
 
20302
20943
  // src/mcp/tools/fetchAvailableFixes/FetchAvailableFixesTool.ts
20303
20944
  init_GitService();
20304
- import { z as z41 } from "zod";
20945
+ import { z as z43 } from "zod";
20305
20946
 
20306
20947
  // src/mcp/tools/fetchAvailableFixes/FetchAvailableFixesService.ts
20307
20948
  init_configs();
@@ -20443,16 +21084,16 @@ Call this tool instead of ${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES} when you only
20443
21084
  },
20444
21085
  required: ["path"]
20445
21086
  });
20446
- __publicField(this, "inputValidationSchema", z41.object({
20447
- path: z41.string().describe(
21087
+ __publicField(this, "inputValidationSchema", z43.object({
21088
+ path: z43.string().describe(
20448
21089
  "Full local path to the cloned git repository to check for available fixes"
20449
21090
  ),
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(
21091
+ offset: z43.number().optional().describe("Optional offset for pagination"),
21092
+ limit: z43.number().optional().describe("Optional maximum number of fixes to return"),
21093
+ fileFilter: z43.array(z43.string()).optional().describe(
20453
21094
  "Optional list of file paths relative to the path parameter to filter fixes by. INCOMPATIBLE with fetchFixesFromAnyFile"
20454
21095
  ),
20455
- fetchFixesFromAnyFile: z41.boolean().optional().describe(
21096
+ fetchFixesFromAnyFile: z43.boolean().optional().describe(
20456
21097
  "Optional boolean to fetch fixes for all files. INCOMPATIBLE with fileFilter"
20457
21098
  )
20458
21099
  }));
@@ -20467,8 +21108,8 @@ Call this tool instead of ${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES} when you only
20467
21108
  `Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
20468
21109
  );
20469
21110
  }
20470
- const path21 = pathValidationResult.path;
20471
- const gitService = new GitService(path21, log);
21111
+ const path22 = pathValidationResult.path;
21112
+ const gitService = new GitService(path22, log);
20472
21113
  const gitValidation = await gitService.validateRepository();
20473
21114
  if (!gitValidation.isValid) {
20474
21115
  throw new Error(`Invalid git repository: ${gitValidation.error}`);
@@ -20521,7 +21162,7 @@ Call this tool instead of ${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES} when you only
20521
21162
  };
20522
21163
 
20523
21164
  // src/mcp/tools/mcpChecker/mcpCheckerTool.ts
20524
- import z42 from "zod";
21165
+ import z44 from "zod";
20525
21166
 
20526
21167
  // src/mcp/tools/mcpChecker/mcpCheckerService.ts
20527
21168
  var _McpCheckerService = class _McpCheckerService {
@@ -20582,7 +21223,7 @@ var McpCheckerTool = class extends BaseTool {
20582
21223
  __publicField(this, "displayName", "MCP Checker");
20583
21224
  // A detailed description to guide the LLM on when and how to invoke this tool.
20584
21225
  __publicField(this, "description", "Check the MCP servers running on this IDE against organization policies.");
20585
- __publicField(this, "inputValidationSchema", z42.object({}));
21226
+ __publicField(this, "inputValidationSchema", z44.object({}));
20586
21227
  __publicField(this, "inputSchema", {
20587
21228
  type: "object",
20588
21229
  properties: {},
@@ -20608,7 +21249,7 @@ var McpCheckerTool = class extends BaseTool {
20608
21249
  };
20609
21250
 
20610
21251
  // src/mcp/tools/scanAndFixVulnerabilities/ScanAndFixVulnerabilitiesTool.ts
20611
- import z43 from "zod";
21252
+ import z45 from "zod";
20612
21253
  init_configs();
20613
21254
 
20614
21255
  // src/mcp/tools/scanAndFixVulnerabilities/ScanAndFixVulnerabilitiesService.ts
@@ -20795,17 +21436,17 @@ Example payload:
20795
21436
  "rescan": false
20796
21437
  }`);
20797
21438
  __publicField(this, "hasAuthentication", true);
20798
- __publicField(this, "inputValidationSchema", z43.object({
20799
- path: z43.string().describe(
21439
+ __publicField(this, "inputValidationSchema", z45.object({
21440
+ path: z45.string().describe(
20800
21441
  "Full local path to repository to scan and fix vulnerabilities"
20801
21442
  ),
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(
21443
+ offset: z45.number().optional().describe("Optional offset for pagination"),
21444
+ limit: z45.number().optional().describe("Optional maximum number of results to return"),
21445
+ maxFiles: z45.number().optional().describe(
20805
21446
  `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
21447
  ),
20807
- rescan: z43.boolean().optional().describe("Optional whether to rescan the repository"),
20808
- scanRecentlyChangedFiles: z43.boolean().optional().describe(
21448
+ rescan: z45.boolean().optional().describe("Optional whether to rescan the repository"),
21449
+ scanRecentlyChangedFiles: z45.boolean().optional().describe(
20809
21450
  "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
21451
  )
20811
21452
  }));
@@ -20856,9 +21497,9 @@ Example payload:
20856
21497
  `Invalid path: potential security risk detected in path: ${pathValidationResult.error}`
20857
21498
  );
20858
21499
  }
20859
- const path21 = pathValidationResult.path;
21500
+ const path22 = pathValidationResult.path;
20860
21501
  const files = await getLocalFiles({
20861
- path: path21,
21502
+ path: path22,
20862
21503
  maxFileSize: MCP_MAX_FILE_SIZE,
20863
21504
  maxFiles: args.maxFiles,
20864
21505
  scanContext: ScanContext.USER_REQUEST,
@@ -20878,7 +21519,7 @@ Example payload:
20878
21519
  try {
20879
21520
  const fixResult = await this.vulnerabilityFixService.processVulnerabilities({
20880
21521
  fileList: files.map((file) => file.relativePath),
20881
- repositoryPath: path21,
21522
+ repositoryPath: path22,
20882
21523
  offset: args.offset,
20883
21524
  limit: args.limit,
20884
21525
  isRescan: args.rescan || !!args.maxFiles
@@ -20983,32 +21624,32 @@ var mcpHandler = async (_args) => {
20983
21624
 
20984
21625
  // src/args/commands/review.ts
20985
21626
  import fs22 from "fs";
20986
- import chalk9 from "chalk";
21627
+ import chalk11 from "chalk";
20987
21628
  function reviewBuilder(yargs2) {
20988
21629
  return yargs2.option("f", {
20989
21630
  alias: "scan-file",
20990
21631
  demandOption: true,
20991
21632
  type: "string",
20992
- describe: chalk9.bold(
21633
+ describe: chalk11.bold(
20993
21634
  "Select the vulnerability report to analyze (Checkmarx, Snyk, Fortify, CodeQL, Sonarqube, Semgrep)"
20994
21635
  )
20995
21636
  }).option("repo", { ...repoOption, demandOption: true }).option("scanner", { ...scannerOptions, demandOption: true }).option("ref", { ...refOption, demandOption: true }).option("ch", {
20996
21637
  alias: "commit-hash",
20997
- describe: chalk9.bold("Hash of the commit"),
21638
+ describe: chalk11.bold("Hash of the commit"),
20998
21639
  type: "string",
20999
21640
  demandOption: true
21000
21641
  }).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"),
21642
+ describe: chalk11.bold("Github action token"),
21002
21643
  type: "string",
21003
21644
  demandOption: true
21004
21645
  }).option("pull-request", {
21005
21646
  alias: ["pr", "pr-number", "pr-id"],
21006
- describe: chalk9.bold("Number of the pull request"),
21647
+ describe: chalk11.bold("Number of the pull request"),
21007
21648
  type: "number",
21008
21649
  demandOption: true
21009
21650
  }).option("p", {
21010
21651
  alias: "src-path",
21011
- describe: chalk9.bold(
21652
+ describe: chalk11.bold(
21012
21653
  "Path to the repository folder with the source code"
21013
21654
  ),
21014
21655
  type: "string",
@@ -21021,7 +21662,7 @@ function reviewBuilder(yargs2) {
21021
21662
  function validateReviewOptions(argv) {
21022
21663
  if (!fs22.existsSync(argv.f)) {
21023
21664
  throw new CliError(`
21024
- Can't access ${chalk9.bold(argv.f)}`);
21665
+ Can't access ${chalk11.bold(argv.f)}`);
21025
21666
  }
21026
21667
  validateRepoUrl(argv);
21027
21668
  validateReportFileFormat(argv.f);
@@ -21091,248 +21732,77 @@ async function addScmTokenHandler(args) {
21091
21732
  await addScmToken(args);
21092
21733
  }
21093
21734
 
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
21735
  // src/args/yargs.ts
21276
21736
  var parseArgs = async (args) => {
21277
21737
  const yargsInstance = yargs(args);
21278
21738
  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")
21739
+ "Commands:": chalk12.yellow.underline.bold("Commands:"),
21740
+ "Options:": chalk12.yellow.underline.bold("Options:"),
21741
+ "Examples:": chalk12.yellow.underline.bold("Examples:"),
21742
+ "Show help": chalk12.bold("Show help")
21283
21743
  }).usage(
21284
- `${chalk11.bold(
21744
+ `${chalk12.bold(
21285
21745
  "\n Bugsy - Trusted, Automatic Vulnerability Fixer \u{1F575}\uFE0F\u200D\u2642\uFE0F\n\n"
21286
- )} ${chalk11.yellow.underline.bold("Usage:")}
21287
- $0 ${chalk11.green(
21746
+ )} ${chalk12.yellow.underline.bold("Usage:")}
21747
+ $0 ${chalk12.green(
21288
21748
  "<command>"
21289
- )} ${chalk11.dim("[options]")}
21749
+ )} ${chalk12.dim("[options]")}
21290
21750
  `
21291
21751
  ).version(false).command(
21292
21752
  mobbCliCommand.scan,
21293
- chalk11.bold(
21753
+ chalk12.bold(
21294
21754
  "Scan your code for vulnerabilities, get automated fixes right away."
21295
21755
  ),
21296
21756
  scanBuilder,
21297
21757
  scanHandler
21298
21758
  ).command(
21299
21759
  mobbCliCommand.analyze,
21300
- chalk11.bold(
21760
+ chalk12.bold(
21301
21761
  "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
21762
  ),
21303
21763
  analyzeBuilder,
21304
21764
  analyzeHandler
21305
21765
  ).command(
21306
21766
  mobbCliCommand.review,
21307
- chalk11.bold(
21767
+ chalk12.bold(
21308
21768
  "Mobb will review your github pull requests and provide comments with fixes "
21309
21769
  ),
21310
21770
  reviewBuilder,
21311
21771
  reviewHandler
21312
21772
  ).command(
21313
21773
  mobbCliCommand.addScmToken,
21314
- chalk11.bold(
21774
+ chalk12.bold(
21315
21775
  "Add your SCM (Github, Gitlab, Azure DevOps) token to Mobb to enable automated fixes."
21316
21776
  ),
21317
21777
  addScmTokenBuilder,
21318
21778
  addScmTokenHandler
21319
21779
  ).command(
21320
21780
  mobbCliCommand.convertToSarif,
21321
- chalk11.bold("Convert an existing SAST report to SARIF format."),
21781
+ chalk12.bold("Convert an existing SAST report to SARIF format."),
21322
21782
  convertToSarifBuilder,
21323
21783
  convertToSarifHandler
21324
21784
  ).command(
21325
21785
  mobbCliCommand.mcp,
21326
- chalk11.bold("Launch the MCP (Model Context Protocol) server."),
21786
+ chalk12.bold("Launch the MCP (Model Context Protocol) server."),
21327
21787
  mcpBuilder,
21328
21788
  mcpHandler
21329
21789
  ).command(
21330
21790
  mobbCliCommand.uploadAiBlame,
21331
- chalk11.bold(
21791
+ chalk12.bold(
21332
21792
  "Upload AI Blame inference artifacts (prompt + inference) and finalize them."
21333
21793
  ),
21334
21794
  uploadAiBlameBuilder,
21335
21795
  uploadAiBlameHandler
21796
+ ).command(
21797
+ mobbCliCommand.claudeCodeInstallHook,
21798
+ chalk12.bold("Install Claude Code hooks for data collection."),
21799
+ claudeCodeInstallHookBuilder,
21800
+ claudeCodeInstallHookHandler
21801
+ ).command(
21802
+ mobbCliCommand.claudeCodeProcessHook,
21803
+ chalk12.bold("Process Claude Code hook data and upload to backend."),
21804
+ claudeCodeProcessHookBuilder,
21805
+ claudeCodeProcessHookHandler
21336
21806
  ).example(
21337
21807
  "npx mobbdev@latest scan -r https://github.com/WebGoat/WebGoat",
21338
21808
  "Scan an existing repository"
@@ -21341,7 +21811,7 @@ var parseArgs = async (args) => {
21341
21811
  handler() {
21342
21812
  yargsInstance.showHelp();
21343
21813
  }
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();
21814
+ }).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
21815
  };
21346
21816
 
21347
21817
  // src/index.ts