mobbdev 1.0.180 → 1.0.182
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +175 -19
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -10604,7 +10604,9 @@ var GQLClient = class {
|
|
|
10604
10604
|
`The user with email:${email} is not associated with any organization`
|
|
10605
10605
|
);
|
|
10606
10606
|
}
|
|
10607
|
-
const organization = orgAndProjectRes.user?.at(0)?.userOrganizationsAndUserOrganizationRoles.map(
|
|
10607
|
+
const organization = orgAndProjectRes.user?.at(0)?.userOrganizationsAndUserOrganizationRoles.map(
|
|
10608
|
+
(org) => org.organization
|
|
10609
|
+
).filter(
|
|
10608
10610
|
(org) => userDefinedOrganizationId ? org.id === userDefinedOrganizationId : true
|
|
10609
10611
|
)?.at(0);
|
|
10610
10612
|
if (!organization) {
|
|
@@ -12354,15 +12356,111 @@ import {
|
|
|
12354
12356
|
|
|
12355
12357
|
// src/mcp/Logger.ts
|
|
12356
12358
|
import Configstore3 from "configstore";
|
|
12359
|
+
|
|
12360
|
+
// src/mcp/services/WorkspaceService.ts
|
|
12361
|
+
var WorkspaceService = class {
|
|
12362
|
+
/**
|
|
12363
|
+
* Sets a known workspace path that was discovered through successful validation
|
|
12364
|
+
* @param path The validated workspace path to store
|
|
12365
|
+
*/
|
|
12366
|
+
static setKnownWorkspacePath(path17) {
|
|
12367
|
+
this.knownWorkspacePath = path17;
|
|
12368
|
+
}
|
|
12369
|
+
/**
|
|
12370
|
+
* Gets the known workspace path that was previously validated
|
|
12371
|
+
* @returns The known workspace path or undefined if none stored
|
|
12372
|
+
*/
|
|
12373
|
+
static getKnownWorkspacePath() {
|
|
12374
|
+
return this.knownWorkspacePath;
|
|
12375
|
+
}
|
|
12376
|
+
/**
|
|
12377
|
+
* Gets the workspace folder path from known path or environment variables
|
|
12378
|
+
* @returns The workspace folder path or undefined if none found
|
|
12379
|
+
*/
|
|
12380
|
+
static getWorkspaceFolderPath() {
|
|
12381
|
+
if (this.knownWorkspacePath) {
|
|
12382
|
+
return this.knownWorkspacePath;
|
|
12383
|
+
}
|
|
12384
|
+
const workspaceEnvVars = [
|
|
12385
|
+
"WORKSPACE_FOLDER_PATHS",
|
|
12386
|
+
// Cursor IDE
|
|
12387
|
+
"PWD",
|
|
12388
|
+
// Claude Code and general shell
|
|
12389
|
+
"WORKSPACE_ROOT",
|
|
12390
|
+
// Generic workspace root
|
|
12391
|
+
"PROJECT_ROOT"
|
|
12392
|
+
// Generic project root
|
|
12393
|
+
];
|
|
12394
|
+
for (const envVar of workspaceEnvVars) {
|
|
12395
|
+
const value = process.env[envVar];
|
|
12396
|
+
if (value?.trim()) {
|
|
12397
|
+
return value.trim();
|
|
12398
|
+
}
|
|
12399
|
+
}
|
|
12400
|
+
return void 0;
|
|
12401
|
+
}
|
|
12402
|
+
///this should be deleted, use instead the host detection from the McpUsageService
|
|
12403
|
+
/**
|
|
12404
|
+
* Detects the IDE/editor host based on environment variables
|
|
12405
|
+
* @returns The detected IDE host
|
|
12406
|
+
*/
|
|
12407
|
+
static getHost() {
|
|
12408
|
+
if (process.env["WORKSPACE_FOLDER_PATHS"]) {
|
|
12409
|
+
return "CURSOR";
|
|
12410
|
+
}
|
|
12411
|
+
if (process.env["VSCODE_IPC_HOOK"] || process.env["VSCODE_PID"] || process.env["TERM_PROGRAM"] === "vscode") {
|
|
12412
|
+
return "VSCODE";
|
|
12413
|
+
}
|
|
12414
|
+
if (process.env["WINDSURF_IPC_HOOK"] || process.env["WINDSURF_PID"] || process.env["TERM_PROGRAM"] === "windsurf") {
|
|
12415
|
+
return "WINDSURF";
|
|
12416
|
+
}
|
|
12417
|
+
if (process.env["CLAUDE_DESKTOP"] || process.env["ANTHROPIC_CLAUDE"]) {
|
|
12418
|
+
return "CLAUDE";
|
|
12419
|
+
}
|
|
12420
|
+
if (process.env["WEBSTORM_VM_OPTIONS"] || process.env["IDEA_VM_OPTIONS"] || process.env["JETBRAINS_IDE"]) {
|
|
12421
|
+
return "WEBSTORM";
|
|
12422
|
+
}
|
|
12423
|
+
return "UNKNOWN";
|
|
12424
|
+
}
|
|
12425
|
+
};
|
|
12426
|
+
__publicField(WorkspaceService, "knownWorkspacePath");
|
|
12427
|
+
|
|
12428
|
+
// src/mcp/Logger.ts
|
|
12357
12429
|
var MAX_LOGS_SIZE = 1e3;
|
|
12358
12430
|
var Logger = class {
|
|
12359
12431
|
constructor() {
|
|
12360
12432
|
__publicField(this, "mobbConfigStore");
|
|
12361
|
-
__publicField(this, "
|
|
12362
|
-
this
|
|
12433
|
+
__publicField(this, "host");
|
|
12434
|
+
__publicField(this, "unknownPathSuffix");
|
|
12435
|
+
__publicField(this, "lastKnownPath", null);
|
|
12436
|
+
this.host = WorkspaceService.getHost();
|
|
12437
|
+
this.unknownPathSuffix = Math.floor(1e3 + Math.random() * 9e3).toString();
|
|
12363
12438
|
this.mobbConfigStore = new Configstore3("mobb-logs", {});
|
|
12364
12439
|
this.mobbConfigStore.set("version", packageJson.version);
|
|
12365
12440
|
}
|
|
12441
|
+
/**
|
|
12442
|
+
* Gets the current log path, fetching workspace path dynamically
|
|
12443
|
+
*/
|
|
12444
|
+
getCurrentLogPath() {
|
|
12445
|
+
const workspacePath = WorkspaceService.getWorkspaceFolderPath();
|
|
12446
|
+
if (workspacePath) {
|
|
12447
|
+
return `${this.host}:${workspacePath}`;
|
|
12448
|
+
}
|
|
12449
|
+
return `${this.host}:unknown-${this.unknownPathSuffix}`;
|
|
12450
|
+
}
|
|
12451
|
+
/**
|
|
12452
|
+
* Migrates logs from unknown path to known workspace path
|
|
12453
|
+
*/
|
|
12454
|
+
migrateLogs(fromPath, toPath) {
|
|
12455
|
+
const existingLogs = this.mobbConfigStore.get(fromPath) || [];
|
|
12456
|
+
const targetLogs = this.mobbConfigStore.get(toPath) || [];
|
|
12457
|
+
if (existingLogs.length > 0) {
|
|
12458
|
+
const combinedLogs = [...targetLogs, ...existingLogs];
|
|
12459
|
+
const finalLogs = combinedLogs.slice(-MAX_LOGS_SIZE);
|
|
12460
|
+
this.mobbConfigStore.set(toPath, finalLogs);
|
|
12461
|
+
this.mobbConfigStore.delete(fromPath);
|
|
12462
|
+
}
|
|
12463
|
+
}
|
|
12366
12464
|
/**
|
|
12367
12465
|
* Log a message to the console.
|
|
12368
12466
|
* @param message - The message to log.
|
|
@@ -12370,17 +12468,27 @@ var Logger = class {
|
|
|
12370
12468
|
* @param data - The data to log.
|
|
12371
12469
|
*/
|
|
12372
12470
|
log(message, level = "info", data) {
|
|
12471
|
+
const currentPath = this.getCurrentLogPath();
|
|
12472
|
+
const workspacePath = WorkspaceService.getWorkspaceFolderPath();
|
|
12473
|
+
if (workspacePath && this.lastKnownPath !== workspacePath) {
|
|
12474
|
+
const unknownPath = `${this.host}:unknown-${this.unknownPathSuffix}`;
|
|
12475
|
+
const knownPath = `${this.host}:${workspacePath}`;
|
|
12476
|
+
if (this.lastKnownPath === null || this.lastKnownPath.includes("unknown-")) {
|
|
12477
|
+
this.migrateLogs(unknownPath, knownPath);
|
|
12478
|
+
}
|
|
12479
|
+
this.lastKnownPath = workspacePath;
|
|
12480
|
+
}
|
|
12373
12481
|
const logMessage = {
|
|
12374
12482
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12375
12483
|
level,
|
|
12376
12484
|
message,
|
|
12377
12485
|
data
|
|
12378
12486
|
};
|
|
12379
|
-
const logs = this.mobbConfigStore.get(
|
|
12487
|
+
const logs = this.mobbConfigStore.get(currentPath) || [];
|
|
12380
12488
|
if (logs.length >= MAX_LOGS_SIZE) {
|
|
12381
12489
|
logs.shift();
|
|
12382
12490
|
}
|
|
12383
|
-
this.mobbConfigStore.set(
|
|
12491
|
+
this.mobbConfigStore.set(currentPath, [...logs, logMessage]);
|
|
12384
12492
|
}
|
|
12385
12493
|
};
|
|
12386
12494
|
var logger = new Logger();
|
|
@@ -13475,6 +13583,12 @@ var McpUsageService = class {
|
|
|
13475
13583
|
}
|
|
13476
13584
|
}
|
|
13477
13585
|
startPeriodicTracking() {
|
|
13586
|
+
if (!this.hasOrganizationId()) {
|
|
13587
|
+
logDebug(
|
|
13588
|
+
`[UsageService] Not starting periodic tracking - organization ID not available`
|
|
13589
|
+
);
|
|
13590
|
+
return;
|
|
13591
|
+
}
|
|
13478
13592
|
logDebug(`[UsageService] Starting periodic tracking for mcps`, {});
|
|
13479
13593
|
this.intervalId = setInterval(async () => {
|
|
13480
13594
|
logDebug(`[UsageService] Triggering periodic usage service`, {
|
|
@@ -13509,6 +13623,10 @@ var McpUsageService = class {
|
|
|
13509
13623
|
}
|
|
13510
13624
|
return "";
|
|
13511
13625
|
}
|
|
13626
|
+
hasOrganizationId() {
|
|
13627
|
+
const organizationId = configStore.get("GOV-ORG-ID") || "";
|
|
13628
|
+
return !!organizationId;
|
|
13629
|
+
}
|
|
13512
13630
|
createUsageData(mcpHostId, organizationId, status) {
|
|
13513
13631
|
const { user, mcps } = getHostInfo();
|
|
13514
13632
|
return {
|
|
@@ -13670,6 +13788,12 @@ var McpServer = class {
|
|
|
13670
13788
|
}
|
|
13671
13789
|
async trackServerUsage(action, signalOrError) {
|
|
13672
13790
|
try {
|
|
13791
|
+
if (!mcpUsageService.hasOrganizationId()) {
|
|
13792
|
+
logDebug(
|
|
13793
|
+
`[McpServer] Skipping ${action} usage tracking - organization ID not available`
|
|
13794
|
+
);
|
|
13795
|
+
return;
|
|
13796
|
+
}
|
|
13673
13797
|
if (action === "start") {
|
|
13674
13798
|
await mcpUsageService.trackServerStart();
|
|
13675
13799
|
}
|
|
@@ -13849,17 +13973,15 @@ var McpServer = class {
|
|
|
13849
13973
|
logError("Failed to connect to the API, skipping background scan");
|
|
13850
13974
|
return;
|
|
13851
13975
|
}
|
|
13852
|
-
|
|
13853
|
-
|
|
13854
|
-
WORKSPACE_FOLDER_PATHS: process.env["WORKSPACE_FOLDER_PATHS"]
|
|
13855
|
-
});
|
|
13976
|
+
const workspacePath = WorkspaceService.getWorkspaceFolderPath();
|
|
13977
|
+
if (workspacePath) {
|
|
13856
13978
|
try {
|
|
13857
13979
|
const checkForNewAvailableFixesTool = this.toolRegistry.getTool(
|
|
13858
13980
|
MCP_TOOL_CHECK_FOR_NEW_AVAILABLE_FIXES
|
|
13859
13981
|
);
|
|
13860
13982
|
logInfo("Triggering periodic scan for new available fixes");
|
|
13861
13983
|
checkForNewAvailableFixesTool.triggerScan({
|
|
13862
|
-
path:
|
|
13984
|
+
path: workspacePath,
|
|
13863
13985
|
gqlClient
|
|
13864
13986
|
});
|
|
13865
13987
|
} catch (error) {
|
|
@@ -14017,14 +14139,19 @@ async function validatePath(inputPath) {
|
|
|
14017
14139
|
inputPath = inputPath.slice(1);
|
|
14018
14140
|
}
|
|
14019
14141
|
if (inputPath === "." || inputPath === "./") {
|
|
14020
|
-
|
|
14142
|
+
const workspaceFolderPath = WorkspaceService.getWorkspaceFolderPath();
|
|
14143
|
+
if (workspaceFolderPath) {
|
|
14021
14144
|
logDebug("Fallback to workspace folder path", {
|
|
14022
14145
|
inputPath,
|
|
14023
|
-
workspaceFolderPaths:
|
|
14146
|
+
workspaceFolderPaths: [workspaceFolderPath]
|
|
14147
|
+
});
|
|
14148
|
+
WorkspaceService.setKnownWorkspacePath(workspaceFolderPath);
|
|
14149
|
+
logDebug("Stored workspace folder path as known path", {
|
|
14150
|
+
workspaceFolderPath
|
|
14024
14151
|
});
|
|
14025
14152
|
return {
|
|
14026
14153
|
isValid: true,
|
|
14027
|
-
path:
|
|
14154
|
+
path: workspaceFolderPath
|
|
14028
14155
|
};
|
|
14029
14156
|
} else {
|
|
14030
14157
|
const error = `"." is not a valid path, please provide a full localpath to the repository`;
|
|
@@ -14066,6 +14193,8 @@ async function validatePath(inputPath) {
|
|
|
14066
14193
|
try {
|
|
14067
14194
|
await fs11.promises.access(inputPath);
|
|
14068
14195
|
logDebug("Path exists and is accessible", { inputPath });
|
|
14196
|
+
WorkspaceService.setKnownWorkspacePath(inputPath);
|
|
14197
|
+
logDebug("Stored validated path in WorkspaceService", { inputPath });
|
|
14069
14198
|
return { isValid: true, path: inputPath };
|
|
14070
14199
|
} catch (error) {
|
|
14071
14200
|
const errorMessage = `Path does not exist or is not accessible: ${inputPath}`;
|
|
@@ -14178,7 +14307,15 @@ To retrieve the available fixes, use one of these approaches:
|
|
|
14178
14307
|
|
|
14179
14308
|
**\u{1F4CB} Valid offset range:** 0 to ${Math.max(0, totalCount - 1)}
|
|
14180
14309
|
|
|
14181
|
-
|
|
14310
|
+
### \u26A0\uFE0F CRITICAL INSTRUCTION FOR AI AGENTS \u26A0\uFE0F
|
|
14311
|
+
|
|
14312
|
+
**DO NOT AUTOMATICALLY FETCH FIXES WITHOUT EXPLICIT USER REQUEST**
|
|
14313
|
+
|
|
14314
|
+
- **DO NOT** run the \`${currentTool}\` tool again on your own
|
|
14315
|
+
- **ONLY** fetch fixes if the user explicitly asks for them
|
|
14316
|
+
- **WAIT** for the user to specifically request fixes before proceeding
|
|
14317
|
+
|
|
14318
|
+
If the user wants to fetch the fixes, they should explicitly ask you to run the \`${currentTool}\` tool again with the corrected parameters.
|
|
14182
14319
|
`;
|
|
14183
14320
|
var applyFixesPrompt = ({
|
|
14184
14321
|
fixes,
|
|
@@ -14300,12 +14437,23 @@ ${hasMore ? `---
|
|
|
14300
14437
|
|
|
14301
14438
|
You have viewed ${shownCount} out of ${totalCount} available fixes.
|
|
14302
14439
|
|
|
14303
|
-
|
|
14440
|
+
### \u26A0\uFE0F CRITICAL INSTRUCTION FOR AI AGENTS \u26A0\uFE0F
|
|
14441
|
+
|
|
14442
|
+
**DO NOT AUTOMATICALLY FETCH ADDITIONAL FIXES WITHOUT EXPLICIT USER REQUEST**
|
|
14443
|
+
|
|
14444
|
+
- **DO NOT** run the \`${currentTool}\` tool again on your own
|
|
14445
|
+
- **DO NOT** automatically retrieve more fixes
|
|
14446
|
+
- **ONLY** fetch additional fixes if the user explicitly asks for them
|
|
14447
|
+
- **WAIT** for the user to specifically request more fixes before proceeding
|
|
14448
|
+
|
|
14449
|
+
### How Users Can Request Additional Fixes
|
|
14450
|
+
|
|
14451
|
+
If the user wants to see more fixes, they should explicitly ask you to run the \`${currentTool}\` tool again with the following parameters:
|
|
14304
14452
|
|
|
14305
14453
|
- **offset**: ${nextOffset} _(start index for the next batch)_
|
|
14306
14454
|
- **limit**: <number_of_fixes_to_return> _(optional \u2013 default is ${MCP_DEFAULT_LIMIT})_
|
|
14307
14455
|
|
|
14308
|
-
If
|
|
14456
|
+
If they omit both **offset** and **limit**, the command will automatically return the next ${MCP_DEFAULT_LIMIT} fixes.
|
|
14309
14457
|
` : ""}
|
|
14310
14458
|
`;
|
|
14311
14459
|
};
|
|
@@ -14346,7 +14494,7 @@ var expiredReportPrompt = ({
|
|
|
14346
14494
|
Your most recent vulnerability report for this repository **expired on ${lastReportDate}** and is no longer available for fetching automated fixes.
|
|
14347
14495
|
|
|
14348
14496
|
### \u{1F4CB} Why Did This Happen?
|
|
14349
|
-
- Reports are automatically purged after a retention period for security and storage
|
|
14497
|
+
- Reports are automatically purged after a retention period for security and storage optimization.
|
|
14350
14498
|
- No new scans have been run since the last report expired.
|
|
14351
14499
|
|
|
14352
14500
|
### \u{1F3AF} Recommended Actions
|
|
@@ -14427,13 +14575,21 @@ This will scan up to the specified number of recently changed files.
|
|
|
14427
14575
|
|
|
14428
14576
|
### \u{1F504} Running a Fresh Scan
|
|
14429
14577
|
|
|
14430
|
-
|
|
14578
|
+
### \u26A0\uFE0F CRITICAL INSTRUCTION FOR AI AGENTS \u26A0\uFE0F
|
|
14579
|
+
|
|
14580
|
+
**DO NOT AUTOMATICALLY RUN RESCANS WITHOUT EXPLICIT USER REQUEST**
|
|
14581
|
+
|
|
14582
|
+
- **DO NOT** run rescans on your own
|
|
14583
|
+
- **ONLY** perform rescans if the user explicitly asks for them
|
|
14584
|
+
- **WAIT** for the user to specifically request a rescan before proceeding
|
|
14585
|
+
|
|
14586
|
+
If the user wants to perform a **rescan** of their repository (fetching a brand-new vulnerability report and updated fixes), they should explicitly ask you to include the additional parameter:
|
|
14431
14587
|
|
|
14432
14588
|
- **rescan**: true
|
|
14433
14589
|
|
|
14434
14590
|
This will start a new analysis, discard any cached results.
|
|
14435
14591
|
|
|
14436
|
-
\u26A0\uFE0F *Note:* A full rescan may take longer to complete than simply fetching additional fixes because
|
|
14592
|
+
\u26A0\uFE0F *Note:* A full rescan may take longer to complete than simply fetching additional fixes because the repository is re-uploaded and re-analyzed from scratch.
|
|
14437
14593
|
`;
|
|
14438
14594
|
var noFixesFoundPrompt = ({
|
|
14439
14595
|
scannedFiles
|