mobbdev 1.2.1 → 1.2.3
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/README.md +18 -0
- package/dist/args/commands/upload_ai_blame.d.mts +52 -32
- package/dist/args/commands/upload_ai_blame.mjs +69 -2
- package/dist/index.mjs +259 -90
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -175,6 +175,24 @@ Here is a simple example of a command line that will run Bugsy in your pipeline:
|
|
|
175
175
|
npx mobbdev analyze --ci --scan-file $SAST_RESULTS_FILENAME --repo $CI_PROJECT_URL --ref $CI_COMMIT_REF_NAME --api-key $MOBB_API_KEY
|
|
176
176
|
```
|
|
177
177
|
|
|
178
|
+
### Polling Mode
|
|
179
|
+
|
|
180
|
+
By default, Bugsy uses WebSocket connections for real-time status updates during analysis. However, some proxy environments or firewalls may block WebSocket connections. In these cases, you can use the `--polling` flag to use HTTP polling instead:
|
|
181
|
+
|
|
182
|
+
```shell
|
|
183
|
+
npx mobbdev analyze --scan-file report.json --repo https://github.com/org/repo --polling
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
**When to use `--polling`:**
|
|
187
|
+
- Your network blocks WebSocket connections (ws:// or wss://)
|
|
188
|
+
- You're behind a corporate proxy that doesn't support WebSocket
|
|
189
|
+
- You experience connection timeouts with the default WebSocket mode
|
|
190
|
+
|
|
191
|
+
**Polling characteristics:**
|
|
192
|
+
- Polling interval: 5 seconds
|
|
193
|
+
- Timeout: 30 minutes
|
|
194
|
+
- Slightly higher latency compared to WebSocket mode, but works in restricted environments
|
|
195
|
+
|
|
178
196
|
## Contribution
|
|
179
197
|
|
|
180
198
|
Install the dependencies and run the tests:
|
|
@@ -21,7 +21,7 @@ type Logger = {
|
|
|
21
21
|
error: (msg: string, data?: unknown) => void;
|
|
22
22
|
};
|
|
23
23
|
declare const PromptItemZ: z.ZodObject<{
|
|
24
|
-
type: z.ZodEnum<["USER_PROMPT", "AI_RESPONSE", "TOOL_EXECUTION", "AI_THINKING"]>;
|
|
24
|
+
type: z.ZodEnum<["USER_PROMPT", "AI_RESPONSE", "TOOL_EXECUTION", "AI_THINKING", "MCP_TOOL_CALL"]>;
|
|
25
25
|
attachedFiles: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
26
26
|
relativePath: z.ZodString;
|
|
27
27
|
startLine: z.ZodOptional<z.ZodNumber>;
|
|
@@ -50,30 +50,28 @@ declare const PromptItemZ: z.ZodObject<{
|
|
|
50
50
|
result: z.ZodString;
|
|
51
51
|
rawArguments: z.ZodOptional<z.ZodString>;
|
|
52
52
|
accepted: z.ZodOptional<z.ZodBoolean>;
|
|
53
|
+
mcpServer: z.ZodOptional<z.ZodString>;
|
|
54
|
+
mcpToolName: z.ZodOptional<z.ZodString>;
|
|
53
55
|
}, "strip", z.ZodTypeAny, {
|
|
54
56
|
name: string;
|
|
55
57
|
parameters: string;
|
|
56
58
|
result: string;
|
|
57
|
-
accepted?: boolean | undefined;
|
|
58
59
|
rawArguments?: string | undefined;
|
|
60
|
+
accepted?: boolean | undefined;
|
|
61
|
+
mcpServer?: string | undefined;
|
|
62
|
+
mcpToolName?: string | undefined;
|
|
59
63
|
}, {
|
|
60
64
|
name: string;
|
|
61
65
|
parameters: string;
|
|
62
66
|
result: string;
|
|
63
|
-
accepted?: boolean | undefined;
|
|
64
67
|
rawArguments?: string | undefined;
|
|
68
|
+
accepted?: boolean | undefined;
|
|
69
|
+
mcpServer?: string | undefined;
|
|
70
|
+
mcpToolName?: string | undefined;
|
|
65
71
|
}>>;
|
|
66
72
|
}, "strip", z.ZodTypeAny, {
|
|
67
|
-
type: "USER_PROMPT" | "AI_RESPONSE" | "TOOL_EXECUTION" | "AI_THINKING";
|
|
68
|
-
tool?: {
|
|
69
|
-
name: string;
|
|
70
|
-
parameters: string;
|
|
71
|
-
result: string;
|
|
72
|
-
accepted?: boolean | undefined;
|
|
73
|
-
rawArguments?: string | undefined;
|
|
74
|
-
} | undefined;
|
|
73
|
+
type: "USER_PROMPT" | "AI_RESPONSE" | "TOOL_EXECUTION" | "AI_THINKING" | "MCP_TOOL_CALL";
|
|
75
74
|
date?: Date | undefined;
|
|
76
|
-
text?: string | undefined;
|
|
77
75
|
attachedFiles?: {
|
|
78
76
|
relativePath: string;
|
|
79
77
|
startLine?: number | undefined;
|
|
@@ -82,17 +80,19 @@ declare const PromptItemZ: z.ZodObject<{
|
|
|
82
80
|
inputCount: number;
|
|
83
81
|
outputCount: number;
|
|
84
82
|
} | undefined;
|
|
85
|
-
|
|
86
|
-
type: "USER_PROMPT" | "AI_RESPONSE" | "TOOL_EXECUTION" | "AI_THINKING";
|
|
83
|
+
text?: string | undefined;
|
|
87
84
|
tool?: {
|
|
88
85
|
name: string;
|
|
89
86
|
parameters: string;
|
|
90
87
|
result: string;
|
|
91
|
-
accepted?: boolean | undefined;
|
|
92
88
|
rawArguments?: string | undefined;
|
|
89
|
+
accepted?: boolean | undefined;
|
|
90
|
+
mcpServer?: string | undefined;
|
|
91
|
+
mcpToolName?: string | undefined;
|
|
93
92
|
} | undefined;
|
|
93
|
+
}, {
|
|
94
|
+
type: "USER_PROMPT" | "AI_RESPONSE" | "TOOL_EXECUTION" | "AI_THINKING" | "MCP_TOOL_CALL";
|
|
94
95
|
date?: Date | undefined;
|
|
95
|
-
text?: string | undefined;
|
|
96
96
|
attachedFiles?: {
|
|
97
97
|
relativePath: string;
|
|
98
98
|
startLine?: number | undefined;
|
|
@@ -101,10 +101,20 @@ declare const PromptItemZ: z.ZodObject<{
|
|
|
101
101
|
inputCount: number;
|
|
102
102
|
outputCount: number;
|
|
103
103
|
} | undefined;
|
|
104
|
+
text?: string | undefined;
|
|
105
|
+
tool?: {
|
|
106
|
+
name: string;
|
|
107
|
+
parameters: string;
|
|
108
|
+
result: string;
|
|
109
|
+
rawArguments?: string | undefined;
|
|
110
|
+
accepted?: boolean | undefined;
|
|
111
|
+
mcpServer?: string | undefined;
|
|
112
|
+
mcpToolName?: string | undefined;
|
|
113
|
+
} | undefined;
|
|
104
114
|
}>;
|
|
105
115
|
type PromptItem = z.infer<typeof PromptItemZ>;
|
|
106
116
|
declare const PromptItemArrayZ: z.ZodArray<z.ZodObject<{
|
|
107
|
-
type: z.ZodEnum<["USER_PROMPT", "AI_RESPONSE", "TOOL_EXECUTION", "AI_THINKING"]>;
|
|
117
|
+
type: z.ZodEnum<["USER_PROMPT", "AI_RESPONSE", "TOOL_EXECUTION", "AI_THINKING", "MCP_TOOL_CALL"]>;
|
|
108
118
|
attachedFiles: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
109
119
|
relativePath: z.ZodString;
|
|
110
120
|
startLine: z.ZodOptional<z.ZodNumber>;
|
|
@@ -133,30 +143,28 @@ declare const PromptItemArrayZ: z.ZodArray<z.ZodObject<{
|
|
|
133
143
|
result: z.ZodString;
|
|
134
144
|
rawArguments: z.ZodOptional<z.ZodString>;
|
|
135
145
|
accepted: z.ZodOptional<z.ZodBoolean>;
|
|
146
|
+
mcpServer: z.ZodOptional<z.ZodString>;
|
|
147
|
+
mcpToolName: z.ZodOptional<z.ZodString>;
|
|
136
148
|
}, "strip", z.ZodTypeAny, {
|
|
137
149
|
name: string;
|
|
138
150
|
parameters: string;
|
|
139
151
|
result: string;
|
|
140
|
-
accepted?: boolean | undefined;
|
|
141
152
|
rawArguments?: string | undefined;
|
|
153
|
+
accepted?: boolean | undefined;
|
|
154
|
+
mcpServer?: string | undefined;
|
|
155
|
+
mcpToolName?: string | undefined;
|
|
142
156
|
}, {
|
|
143
157
|
name: string;
|
|
144
158
|
parameters: string;
|
|
145
159
|
result: string;
|
|
146
|
-
accepted?: boolean | undefined;
|
|
147
160
|
rawArguments?: string | undefined;
|
|
161
|
+
accepted?: boolean | undefined;
|
|
162
|
+
mcpServer?: string | undefined;
|
|
163
|
+
mcpToolName?: string | undefined;
|
|
148
164
|
}>>;
|
|
149
165
|
}, "strip", z.ZodTypeAny, {
|
|
150
|
-
type: "USER_PROMPT" | "AI_RESPONSE" | "TOOL_EXECUTION" | "AI_THINKING";
|
|
151
|
-
tool?: {
|
|
152
|
-
name: string;
|
|
153
|
-
parameters: string;
|
|
154
|
-
result: string;
|
|
155
|
-
accepted?: boolean | undefined;
|
|
156
|
-
rawArguments?: string | undefined;
|
|
157
|
-
} | undefined;
|
|
166
|
+
type: "USER_PROMPT" | "AI_RESPONSE" | "TOOL_EXECUTION" | "AI_THINKING" | "MCP_TOOL_CALL";
|
|
158
167
|
date?: Date | undefined;
|
|
159
|
-
text?: string | undefined;
|
|
160
168
|
attachedFiles?: {
|
|
161
169
|
relativePath: string;
|
|
162
170
|
startLine?: number | undefined;
|
|
@@ -165,17 +173,19 @@ declare const PromptItemArrayZ: z.ZodArray<z.ZodObject<{
|
|
|
165
173
|
inputCount: number;
|
|
166
174
|
outputCount: number;
|
|
167
175
|
} | undefined;
|
|
168
|
-
|
|
169
|
-
type: "USER_PROMPT" | "AI_RESPONSE" | "TOOL_EXECUTION" | "AI_THINKING";
|
|
176
|
+
text?: string | undefined;
|
|
170
177
|
tool?: {
|
|
171
178
|
name: string;
|
|
172
179
|
parameters: string;
|
|
173
180
|
result: string;
|
|
174
|
-
accepted?: boolean | undefined;
|
|
175
181
|
rawArguments?: string | undefined;
|
|
182
|
+
accepted?: boolean | undefined;
|
|
183
|
+
mcpServer?: string | undefined;
|
|
184
|
+
mcpToolName?: string | undefined;
|
|
176
185
|
} | undefined;
|
|
186
|
+
}, {
|
|
187
|
+
type: "USER_PROMPT" | "AI_RESPONSE" | "TOOL_EXECUTION" | "AI_THINKING" | "MCP_TOOL_CALL";
|
|
177
188
|
date?: Date | undefined;
|
|
178
|
-
text?: string | undefined;
|
|
179
189
|
attachedFiles?: {
|
|
180
190
|
relativePath: string;
|
|
181
191
|
startLine?: number | undefined;
|
|
@@ -184,6 +194,16 @@ declare const PromptItemArrayZ: z.ZodArray<z.ZodObject<{
|
|
|
184
194
|
inputCount: number;
|
|
185
195
|
outputCount: number;
|
|
186
196
|
} | undefined;
|
|
197
|
+
text?: string | undefined;
|
|
198
|
+
tool?: {
|
|
199
|
+
name: string;
|
|
200
|
+
parameters: string;
|
|
201
|
+
result: string;
|
|
202
|
+
rawArguments?: string | undefined;
|
|
203
|
+
accepted?: boolean | undefined;
|
|
204
|
+
mcpServer?: string | undefined;
|
|
205
|
+
mcpToolName?: string | undefined;
|
|
206
|
+
} | undefined;
|
|
187
207
|
}>, "many">;
|
|
188
208
|
type PromptItemArray = z.infer<typeof PromptItemArrayZ>;
|
|
189
209
|
type UploadAiBlameOptions = {
|
|
@@ -6401,6 +6401,61 @@ var GQLClient = class {
|
|
|
6401
6401
|
}
|
|
6402
6402
|
);
|
|
6403
6403
|
}
|
|
6404
|
+
async pollForAnalysisState(params) {
|
|
6405
|
+
const { analysisId, callbackStates, callback, timeoutInMs } = params;
|
|
6406
|
+
const startTime = Date.now();
|
|
6407
|
+
const maxDuration = timeoutInMs ?? 30 * 60 * 1e3;
|
|
6408
|
+
const pollingIntervalSec = REPORT_STATE_CHECK_DELAY / 1e3;
|
|
6409
|
+
debug6(
|
|
6410
|
+
`[pollForAnalysisState] Starting polling for analysis ${analysisId}, target states: ${callbackStates.join(", ")}, interval: ${pollingIntervalSec}s`
|
|
6411
|
+
);
|
|
6412
|
+
let isPolling = true;
|
|
6413
|
+
let pollCount = 0;
|
|
6414
|
+
while (isPolling) {
|
|
6415
|
+
pollCount++;
|
|
6416
|
+
const elapsedSec = Math.round((Date.now() - startTime) / 1e3);
|
|
6417
|
+
if (Date.now() - startTime > maxDuration) {
|
|
6418
|
+
debug6(
|
|
6419
|
+
`[pollForAnalysisState] Timeout expired after ${pollCount} polls (${elapsedSec}s)`
|
|
6420
|
+
);
|
|
6421
|
+
throw new ReportDigestError(
|
|
6422
|
+
`Polling timeout expired for analysis: ${analysisId} with timeout: ${maxDuration}ms`,
|
|
6423
|
+
`Analysis timed out after ${Math.round(maxDuration / 6e4)} minutes. Please try again or check the Mobb platform for status.`
|
|
6424
|
+
);
|
|
6425
|
+
}
|
|
6426
|
+
debug6(
|
|
6427
|
+
`[pollForAnalysisState] Poll #${pollCount} (elapsed: ${elapsedSec}s) - fetching analysis state...`
|
|
6428
|
+
);
|
|
6429
|
+
const analysis = await this.getAnalysis(analysisId);
|
|
6430
|
+
debug6(
|
|
6431
|
+
`[pollForAnalysisState] Poll #${pollCount} - current state: ${analysis.state}`
|
|
6432
|
+
);
|
|
6433
|
+
if (!analysis.state || analysis.state === "Failed" /* Failed */) {
|
|
6434
|
+
const errorMessage = analysis.failReason || `Analysis failed with id: ${analysis.id}`;
|
|
6435
|
+
debug6(`[pollForAnalysisState] Analysis failed: ${errorMessage}`);
|
|
6436
|
+
throw new ReportDigestError(errorMessage, analysis.failReason ?? "");
|
|
6437
|
+
}
|
|
6438
|
+
if (callbackStates.includes(analysis.state)) {
|
|
6439
|
+
debug6(
|
|
6440
|
+
`[pollForAnalysisState] Target state reached: ${analysis.state} after ${pollCount} polls (${elapsedSec}s)`
|
|
6441
|
+
);
|
|
6442
|
+
await callback(analysis.id);
|
|
6443
|
+
isPolling = false;
|
|
6444
|
+
return {
|
|
6445
|
+
analysis: {
|
|
6446
|
+
id: analysis.id,
|
|
6447
|
+
state: analysis.state,
|
|
6448
|
+
failReason: analysis.failReason
|
|
6449
|
+
}
|
|
6450
|
+
};
|
|
6451
|
+
}
|
|
6452
|
+
debug6(
|
|
6453
|
+
`[pollForAnalysisState] State ${analysis.state} not in target states, waiting ${pollingIntervalSec}s before next poll...`
|
|
6454
|
+
);
|
|
6455
|
+
await sleep(REPORT_STATE_CHECK_DELAY);
|
|
6456
|
+
}
|
|
6457
|
+
throw new Error(`Unexpected end of polling for analysis: ${analysisId}`);
|
|
6458
|
+
}
|
|
6404
6459
|
async getFixReportsByRepoUrl({ repoUrl }) {
|
|
6405
6460
|
const res = await this._clientSdk.GetFixReportsByRepoUrl({
|
|
6406
6461
|
repoUrl
|
|
@@ -7061,7 +7116,14 @@ var defaultLogger = {
|
|
|
7061
7116
|
}
|
|
7062
7117
|
};
|
|
7063
7118
|
var PromptItemZ = z26.object({
|
|
7064
|
-
type: z26.enum([
|
|
7119
|
+
type: z26.enum([
|
|
7120
|
+
"USER_PROMPT",
|
|
7121
|
+
"AI_RESPONSE",
|
|
7122
|
+
"TOOL_EXECUTION",
|
|
7123
|
+
"AI_THINKING",
|
|
7124
|
+
"MCP_TOOL_CALL"
|
|
7125
|
+
// MCP (Model Context Protocol) tool invocation
|
|
7126
|
+
]),
|
|
7065
7127
|
attachedFiles: z26.array(
|
|
7066
7128
|
z26.object({
|
|
7067
7129
|
relativePath: z26.string(),
|
|
@@ -7079,7 +7141,12 @@ var PromptItemZ = z26.object({
|
|
|
7079
7141
|
parameters: z26.string(),
|
|
7080
7142
|
result: z26.string(),
|
|
7081
7143
|
rawArguments: z26.string().optional(),
|
|
7082
|
-
accepted: z26.boolean().optional()
|
|
7144
|
+
accepted: z26.boolean().optional(),
|
|
7145
|
+
// MCP-specific fields (only populated for MCP_TOOL_CALL type)
|
|
7146
|
+
mcpServer: z26.string().optional(),
|
|
7147
|
+
// MCP server name (e.g., "datadog", "mobb-mcp")
|
|
7148
|
+
mcpToolName: z26.string().optional()
|
|
7149
|
+
// MCP tool name without prefix (e.g., "scan_and_fix_vulnerabilities")
|
|
7083
7150
|
}).optional()
|
|
7084
7151
|
});
|
|
7085
7152
|
var PromptItemArrayZ = z26.array(PromptItemZ);
|
package/dist/index.mjs
CHANGED
|
@@ -11524,6 +11524,13 @@ var convertToSarifCodePathPatternsOption = {
|
|
|
11524
11524
|
type: "string",
|
|
11525
11525
|
array: true
|
|
11526
11526
|
};
|
|
11527
|
+
var pollingOption = {
|
|
11528
|
+
describe: chalk2.bold(
|
|
11529
|
+
"Use HTTP polling instead of WebSocket for status updates. Useful for proxy environments or firewalls that block WebSocket connections. Polling interval: 5 seconds, timeout: 30 minutes."
|
|
11530
|
+
),
|
|
11531
|
+
type: "boolean",
|
|
11532
|
+
default: false
|
|
11533
|
+
};
|
|
11527
11534
|
|
|
11528
11535
|
// src/args/commands/convert_to_sarif.ts
|
|
11529
11536
|
function convertToSarifBuilder(args) {
|
|
@@ -12236,6 +12243,61 @@ var GQLClient = class {
|
|
|
12236
12243
|
}
|
|
12237
12244
|
);
|
|
12238
12245
|
}
|
|
12246
|
+
async pollForAnalysisState(params) {
|
|
12247
|
+
const { analysisId, callbackStates, callback, timeoutInMs } = params;
|
|
12248
|
+
const startTime = Date.now();
|
|
12249
|
+
const maxDuration = timeoutInMs ?? 30 * 60 * 1e3;
|
|
12250
|
+
const pollingIntervalSec = REPORT_STATE_CHECK_DELAY / 1e3;
|
|
12251
|
+
debug6(
|
|
12252
|
+
`[pollForAnalysisState] Starting polling for analysis ${analysisId}, target states: ${callbackStates.join(", ")}, interval: ${pollingIntervalSec}s`
|
|
12253
|
+
);
|
|
12254
|
+
let isPolling = true;
|
|
12255
|
+
let pollCount = 0;
|
|
12256
|
+
while (isPolling) {
|
|
12257
|
+
pollCount++;
|
|
12258
|
+
const elapsedSec = Math.round((Date.now() - startTime) / 1e3);
|
|
12259
|
+
if (Date.now() - startTime > maxDuration) {
|
|
12260
|
+
debug6(
|
|
12261
|
+
`[pollForAnalysisState] Timeout expired after ${pollCount} polls (${elapsedSec}s)`
|
|
12262
|
+
);
|
|
12263
|
+
throw new ReportDigestError(
|
|
12264
|
+
`Polling timeout expired for analysis: ${analysisId} with timeout: ${maxDuration}ms`,
|
|
12265
|
+
`Analysis timed out after ${Math.round(maxDuration / 6e4)} minutes. Please try again or check the Mobb platform for status.`
|
|
12266
|
+
);
|
|
12267
|
+
}
|
|
12268
|
+
debug6(
|
|
12269
|
+
`[pollForAnalysisState] Poll #${pollCount} (elapsed: ${elapsedSec}s) - fetching analysis state...`
|
|
12270
|
+
);
|
|
12271
|
+
const analysis = await this.getAnalysis(analysisId);
|
|
12272
|
+
debug6(
|
|
12273
|
+
`[pollForAnalysisState] Poll #${pollCount} - current state: ${analysis.state}`
|
|
12274
|
+
);
|
|
12275
|
+
if (!analysis.state || analysis.state === "Failed" /* Failed */) {
|
|
12276
|
+
const errorMessage = analysis.failReason || `Analysis failed with id: ${analysis.id}`;
|
|
12277
|
+
debug6(`[pollForAnalysisState] Analysis failed: ${errorMessage}`);
|
|
12278
|
+
throw new ReportDigestError(errorMessage, analysis.failReason ?? "");
|
|
12279
|
+
}
|
|
12280
|
+
if (callbackStates.includes(analysis.state)) {
|
|
12281
|
+
debug6(
|
|
12282
|
+
`[pollForAnalysisState] Target state reached: ${analysis.state} after ${pollCount} polls (${elapsedSec}s)`
|
|
12283
|
+
);
|
|
12284
|
+
await callback(analysis.id);
|
|
12285
|
+
isPolling = false;
|
|
12286
|
+
return {
|
|
12287
|
+
analysis: {
|
|
12288
|
+
id: analysis.id,
|
|
12289
|
+
state: analysis.state,
|
|
12290
|
+
failReason: analysis.failReason
|
|
12291
|
+
}
|
|
12292
|
+
};
|
|
12293
|
+
}
|
|
12294
|
+
debug6(
|
|
12295
|
+
`[pollForAnalysisState] State ${analysis.state} not in target states, waiting ${pollingIntervalSec}s before next poll...`
|
|
12296
|
+
);
|
|
12297
|
+
await sleep(REPORT_STATE_CHECK_DELAY);
|
|
12298
|
+
}
|
|
12299
|
+
throw new Error(`Unexpected end of polling for analysis: ${analysisId}`);
|
|
12300
|
+
}
|
|
12239
12301
|
async getFixReportsByRepoUrl({ repoUrl }) {
|
|
12240
12302
|
const res = await this._clientSdk.GetFixReportsByRepoUrl({
|
|
12241
12303
|
repoUrl
|
|
@@ -12636,7 +12698,8 @@ var debug8 = Debug7("mobbdev:index");
|
|
|
12636
12698
|
async function sendReport({
|
|
12637
12699
|
spinner,
|
|
12638
12700
|
submitVulnerabilityReportVariables,
|
|
12639
|
-
gqlClient
|
|
12701
|
+
gqlClient,
|
|
12702
|
+
polling
|
|
12640
12703
|
}) {
|
|
12641
12704
|
try {
|
|
12642
12705
|
const submitRes = await gqlClient.submitVulnerabilityReport(
|
|
@@ -12647,19 +12710,32 @@ async function sendReport({
|
|
|
12647
12710
|
throw new Error("\u{1F575}\uFE0F\u200D\u2642\uFE0F Mobb analysis failed");
|
|
12648
12711
|
}
|
|
12649
12712
|
spinner.update({ text: progressMassages.processingVulnerabilityReport });
|
|
12650
|
-
|
|
12651
|
-
|
|
12652
|
-
analysisId: submitRes.submitVulnerabilityReport.fixReportId
|
|
12653
|
-
},
|
|
12654
|
-
callback: () => spinner.update({
|
|
12655
|
-
text: "\u2699\uFE0F Vulnerability report processed successfully"
|
|
12656
|
-
}),
|
|
12657
|
-
callbackStates: [
|
|
12658
|
-
"Digested" /* Digested */,
|
|
12659
|
-
"Finished" /* Finished */
|
|
12660
|
-
],
|
|
12661
|
-
timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
|
|
12713
|
+
const callback = (_analysisId) => spinner.update({
|
|
12714
|
+
text: "\u2699\uFE0F Vulnerability report processed successfully"
|
|
12662
12715
|
});
|
|
12716
|
+
const callbackStates = [
|
|
12717
|
+
"Digested" /* Digested */,
|
|
12718
|
+
"Finished" /* Finished */
|
|
12719
|
+
];
|
|
12720
|
+
if (polling) {
|
|
12721
|
+
debug8("[sendReport] Using POLLING mode for analysis state updates");
|
|
12722
|
+
await gqlClient.pollForAnalysisState({
|
|
12723
|
+
analysisId: submitRes.submitVulnerabilityReport.fixReportId,
|
|
12724
|
+
callback,
|
|
12725
|
+
callbackStates,
|
|
12726
|
+
timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
|
|
12727
|
+
});
|
|
12728
|
+
} else {
|
|
12729
|
+
debug8("[sendReport] Using WEBSOCKET mode for analysis state updates");
|
|
12730
|
+
await gqlClient.subscribeToAnalysis({
|
|
12731
|
+
subscribeToAnalysisParams: {
|
|
12732
|
+
analysisId: submitRes.submitVulnerabilityReport.fixReportId
|
|
12733
|
+
},
|
|
12734
|
+
callback,
|
|
12735
|
+
callbackStates,
|
|
12736
|
+
timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
|
|
12737
|
+
});
|
|
12738
|
+
}
|
|
12663
12739
|
return submitRes;
|
|
12664
12740
|
} catch (e) {
|
|
12665
12741
|
spinner.error({ text: "\u{1F575}\uFE0F\u200D\u2642\uFE0F Mobb analysis failed" });
|
|
@@ -13197,44 +13273,57 @@ async function handleAutoPr(params) {
|
|
|
13197
13273
|
commitDirectly,
|
|
13198
13274
|
prId,
|
|
13199
13275
|
createSpinner: createSpinner5,
|
|
13200
|
-
createOnePr
|
|
13276
|
+
createOnePr,
|
|
13277
|
+
polling
|
|
13201
13278
|
} = params;
|
|
13202
13279
|
const createAutoPrSpinner = createSpinner5(
|
|
13203
13280
|
"\u{1F504} Waiting for the analysis to finish before initiating automatic pull request creation"
|
|
13204
13281
|
).start();
|
|
13205
|
-
|
|
13206
|
-
|
|
13207
|
-
analysisId
|
|
13208
|
-
|
|
13209
|
-
|
|
13210
|
-
|
|
13211
|
-
|
|
13212
|
-
|
|
13213
|
-
|
|
13214
|
-
|
|
13282
|
+
const callback = async (analysisId2) => {
|
|
13283
|
+
const autoPrAnalysisRes = await gqlClient.autoPrAnalysis({
|
|
13284
|
+
analysisId: analysisId2,
|
|
13285
|
+
commitDirectly,
|
|
13286
|
+
prId,
|
|
13287
|
+
prStrategy: createOnePr ? "CONDENSE" /* Condense */ : "SPREAD" /* Spread */
|
|
13288
|
+
});
|
|
13289
|
+
debug12("auto pr analysis res %o", autoPrAnalysisRes);
|
|
13290
|
+
if (autoPrAnalysisRes.autoPrAnalysis?.__typename === "AutoPrError") {
|
|
13291
|
+
createAutoPrSpinner.error({
|
|
13292
|
+
text: `\u{1F504} Automatic pull request failed - ${autoPrAnalysisRes.autoPrAnalysis.error}`
|
|
13215
13293
|
});
|
|
13216
|
-
|
|
13217
|
-
|
|
13218
|
-
|
|
13219
|
-
|
|
13220
|
-
|
|
13221
|
-
return;
|
|
13222
|
-
}
|
|
13223
|
-
if (autoPrAnalysisRes.autoPrAnalysis?.__typename === "AutoPrSuccess") {
|
|
13224
|
-
const { appliedAutoPrIssueTypes } = autoPrAnalysisRes.autoPrAnalysis;
|
|
13225
|
-
if (appliedAutoPrIssueTypes.length === 0) {
|
|
13226
|
-
createAutoPrSpinner.success({
|
|
13227
|
-
text: "\u{1F504} Automatic pull request did not find any new fixes to open a pull request for"
|
|
13228
|
-
});
|
|
13229
|
-
return;
|
|
13230
|
-
}
|
|
13294
|
+
return;
|
|
13295
|
+
}
|
|
13296
|
+
if (autoPrAnalysisRes.autoPrAnalysis?.__typename === "AutoPrSuccess") {
|
|
13297
|
+
const { appliedAutoPrIssueTypes } = autoPrAnalysisRes.autoPrAnalysis;
|
|
13298
|
+
if (appliedAutoPrIssueTypes.length === 0) {
|
|
13231
13299
|
createAutoPrSpinner.success({
|
|
13232
|
-
text:
|
|
13300
|
+
text: "\u{1F504} Automatic pull request did not find any new fixes to open a pull request for"
|
|
13233
13301
|
});
|
|
13302
|
+
return;
|
|
13234
13303
|
}
|
|
13235
|
-
|
|
13236
|
-
|
|
13237
|
-
|
|
13304
|
+
createAutoPrSpinner.success({
|
|
13305
|
+
text: `\u{1F504} Automatic pull request creation initiated successfully for the following issue types: ${appliedAutoPrIssueTypes}`
|
|
13306
|
+
});
|
|
13307
|
+
}
|
|
13308
|
+
};
|
|
13309
|
+
const callbackStates = ["Finished" /* Finished */];
|
|
13310
|
+
if (polling) {
|
|
13311
|
+
debug12("[handleAutoPr] Using POLLING mode for analysis state updates");
|
|
13312
|
+
return await gqlClient.pollForAnalysisState({
|
|
13313
|
+
analysisId,
|
|
13314
|
+
callback,
|
|
13315
|
+
callbackStates
|
|
13316
|
+
});
|
|
13317
|
+
} else {
|
|
13318
|
+
debug12("[handleAutoPr] Using WEBSOCKET mode for analysis state updates");
|
|
13319
|
+
return await gqlClient.subscribeToAnalysis({
|
|
13320
|
+
subscribeToAnalysisParams: {
|
|
13321
|
+
analysisId
|
|
13322
|
+
},
|
|
13323
|
+
callback,
|
|
13324
|
+
callbackStates
|
|
13325
|
+
});
|
|
13326
|
+
}
|
|
13238
13327
|
}
|
|
13239
13328
|
|
|
13240
13329
|
// src/features/analysis/git.ts
|
|
@@ -13987,7 +14076,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
13987
14076
|
autoPr,
|
|
13988
14077
|
createOnePr,
|
|
13989
14078
|
commitDirectly,
|
|
13990
|
-
pullRequest
|
|
14079
|
+
pullRequest,
|
|
14080
|
+
polling
|
|
13991
14081
|
} = params;
|
|
13992
14082
|
debug18("start %s %s", dirname, repo);
|
|
13993
14083
|
const { createSpinner: createSpinner5 } = Spinner2({ ci });
|
|
@@ -14099,7 +14189,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
14099
14189
|
repoUrl: repo,
|
|
14100
14190
|
sha,
|
|
14101
14191
|
reference,
|
|
14102
|
-
shouldScan
|
|
14192
|
+
shouldScan,
|
|
14193
|
+
polling
|
|
14103
14194
|
});
|
|
14104
14195
|
uploadReportSpinner.success({ text: "\u{1F4C1} Report uploaded successfully" });
|
|
14105
14196
|
const mobbSpinner = createSpinner5("\u{1F575}\uFE0F\u200D\u2642\uFE0F Initiating Mobb analysis").start();
|
|
@@ -14117,7 +14208,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
14117
14208
|
pullRequest: params.pullRequest,
|
|
14118
14209
|
scanSource: _getScanSource(command, ci),
|
|
14119
14210
|
scanContext: ScanContext.BUGSY
|
|
14120
|
-
}
|
|
14211
|
+
},
|
|
14212
|
+
polling
|
|
14121
14213
|
});
|
|
14122
14214
|
if (sendReportRes.submitVulnerabilityReport.__typename !== "VulnerabilityReport") {
|
|
14123
14215
|
mobbSpinner.error({ text: "\u{1F575}\uFE0F\u200D\u2642\uFE0F Mobb analysis failed" });
|
|
@@ -14133,7 +14225,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
14133
14225
|
commitDirectly,
|
|
14134
14226
|
prId: pullRequest,
|
|
14135
14227
|
createSpinner: createSpinner5,
|
|
14136
|
-
createOnePr
|
|
14228
|
+
createOnePr,
|
|
14229
|
+
polling
|
|
14137
14230
|
});
|
|
14138
14231
|
}
|
|
14139
14232
|
await askToOpenAnalysis();
|
|
@@ -14143,7 +14236,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
14143
14236
|
githubActionToken,
|
|
14144
14237
|
analysisId: reportUploadInfo.fixReportId,
|
|
14145
14238
|
scanner,
|
|
14146
|
-
gqlClient
|
|
14239
|
+
gqlClient,
|
|
14240
|
+
polling
|
|
14147
14241
|
});
|
|
14148
14242
|
}
|
|
14149
14243
|
return reportUploadInfo.fixReportId;
|
|
@@ -14238,7 +14332,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
14238
14332
|
projectId,
|
|
14239
14333
|
command,
|
|
14240
14334
|
ci,
|
|
14241
|
-
shouldScan: shouldScan2
|
|
14335
|
+
shouldScan: shouldScan2,
|
|
14336
|
+
polling
|
|
14242
14337
|
});
|
|
14243
14338
|
const res = await _zipAndUploadRepo({
|
|
14244
14339
|
srcPath,
|
|
@@ -14261,7 +14356,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
14261
14356
|
projectId,
|
|
14262
14357
|
command,
|
|
14263
14358
|
ci,
|
|
14264
|
-
shouldScan: shouldScan2
|
|
14359
|
+
shouldScan: shouldScan2,
|
|
14360
|
+
polling
|
|
14265
14361
|
});
|
|
14266
14362
|
}
|
|
14267
14363
|
const mobbSpinner2 = createSpinner5("\u{1F575}\uFE0F\u200D\u2642\uFE0F Initiating Mobb analysis").start();
|
|
@@ -14279,7 +14375,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
14279
14375
|
pullRequest: params.pullRequest,
|
|
14280
14376
|
experimentalEnabled: !!experimentalEnabled,
|
|
14281
14377
|
scanContext: ScanContext.BUGSY
|
|
14282
|
-
}
|
|
14378
|
+
},
|
|
14379
|
+
polling
|
|
14283
14380
|
});
|
|
14284
14381
|
if (command === "review") {
|
|
14285
14382
|
await waitForAnaysisAndReviewPr({
|
|
@@ -14287,7 +14384,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
14287
14384
|
githubActionToken,
|
|
14288
14385
|
analysisId: reportUploadInfo.fixReportId,
|
|
14289
14386
|
scanner,
|
|
14290
|
-
gqlClient
|
|
14387
|
+
gqlClient,
|
|
14388
|
+
polling
|
|
14291
14389
|
});
|
|
14292
14390
|
}
|
|
14293
14391
|
} catch (e) {
|
|
@@ -14304,7 +14402,8 @@ async function _scan(params, { skipPrompts = false } = {}) {
|
|
|
14304
14402
|
commitDirectly,
|
|
14305
14403
|
prId: pullRequest,
|
|
14306
14404
|
createSpinner: createSpinner5,
|
|
14307
|
-
createOnePr
|
|
14405
|
+
createOnePr,
|
|
14406
|
+
polling
|
|
14308
14407
|
});
|
|
14309
14408
|
}
|
|
14310
14409
|
await askToOpenAnalysis();
|
|
@@ -14352,7 +14451,8 @@ async function _digestReport({
|
|
|
14352
14451
|
repoUrl,
|
|
14353
14452
|
sha,
|
|
14354
14453
|
reference,
|
|
14355
|
-
shouldScan
|
|
14454
|
+
shouldScan,
|
|
14455
|
+
polling
|
|
14356
14456
|
}) {
|
|
14357
14457
|
const digestSpinner = createSpinner4(
|
|
14358
14458
|
progressMassages.processingVulnerabilityReport
|
|
@@ -14369,19 +14469,46 @@ async function _digestReport({
|
|
|
14369
14469
|
shouldScan
|
|
14370
14470
|
}
|
|
14371
14471
|
);
|
|
14372
|
-
|
|
14373
|
-
|
|
14374
|
-
|
|
14375
|
-
|
|
14376
|
-
|
|
14377
|
-
|
|
14378
|
-
}),
|
|
14379
|
-
callbackStates: [
|
|
14380
|
-
"Digested" /* Digested */,
|
|
14381
|
-
"Finished" /* Finished */
|
|
14382
|
-
],
|
|
14383
|
-
timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
|
|
14472
|
+
const callbackStates = [
|
|
14473
|
+
"Digested" /* Digested */,
|
|
14474
|
+
"Finished" /* Finished */
|
|
14475
|
+
];
|
|
14476
|
+
const callback = (_analysisId) => digestSpinner.update({
|
|
14477
|
+
text: progressMassages.processingVulnerabilityReportSuccess
|
|
14384
14478
|
});
|
|
14479
|
+
if (polling) {
|
|
14480
|
+
debug18(
|
|
14481
|
+
"[_digestReport] Using POLLING mode for analysis state updates (--polling flag enabled)"
|
|
14482
|
+
);
|
|
14483
|
+
console.log(
|
|
14484
|
+
chalk6.cyan(
|
|
14485
|
+
"\u{1F504} [Polling Mode] Using HTTP polling instead of WebSocket for status updates"
|
|
14486
|
+
)
|
|
14487
|
+
);
|
|
14488
|
+
await gqlClient.pollForAnalysisState({
|
|
14489
|
+
analysisId: fixReportId,
|
|
14490
|
+
callback,
|
|
14491
|
+
callbackStates,
|
|
14492
|
+
timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
|
|
14493
|
+
});
|
|
14494
|
+
} else {
|
|
14495
|
+
debug18(
|
|
14496
|
+
"[_digestReport] Using WEBSOCKET mode for analysis state updates (default)"
|
|
14497
|
+
);
|
|
14498
|
+
console.log(
|
|
14499
|
+
chalk6.cyan(
|
|
14500
|
+
"\u{1F50C} [WebSocket Mode] Using WebSocket subscription for status updates"
|
|
14501
|
+
)
|
|
14502
|
+
);
|
|
14503
|
+
await gqlClient.subscribeToAnalysis({
|
|
14504
|
+
subscribeToAnalysisParams: {
|
|
14505
|
+
analysisId: fixReportId
|
|
14506
|
+
},
|
|
14507
|
+
callback,
|
|
14508
|
+
callbackStates,
|
|
14509
|
+
timeoutInMs: VUL_REPORT_DIGEST_TIMEOUT_MS
|
|
14510
|
+
});
|
|
14511
|
+
}
|
|
14385
14512
|
const vulnFiles = await gqlClient.getVulnerabilityReportPaths(
|
|
14386
14513
|
vulnerabilityReportId
|
|
14387
14514
|
);
|
|
@@ -14402,7 +14529,8 @@ async function waitForAnaysisAndReviewPr({
|
|
|
14402
14529
|
githubActionToken,
|
|
14403
14530
|
analysisId,
|
|
14404
14531
|
scanner,
|
|
14405
|
-
gqlClient
|
|
14532
|
+
gqlClient,
|
|
14533
|
+
polling
|
|
14406
14534
|
}) {
|
|
14407
14535
|
const params = z29.object({
|
|
14408
14536
|
repo: z29.string().url(),
|
|
@@ -14419,20 +14547,45 @@ async function waitForAnaysisAndReviewPr({
|
|
|
14419
14547
|
propagateExceptions: true
|
|
14420
14548
|
}
|
|
14421
14549
|
);
|
|
14422
|
-
|
|
14423
|
-
|
|
14424
|
-
analysisId
|
|
14425
|
-
|
|
14426
|
-
|
|
14427
|
-
|
|
14428
|
-
|
|
14429
|
-
|
|
14430
|
-
|
|
14431
|
-
|
|
14432
|
-
|
|
14433
|
-
|
|
14434
|
-
|
|
14435
|
-
|
|
14550
|
+
const callback = (analysisId2) => {
|
|
14551
|
+
return addFixCommentsForPr({
|
|
14552
|
+
analysisId: analysisId2,
|
|
14553
|
+
gqlClient,
|
|
14554
|
+
scm,
|
|
14555
|
+
scanner: z29.nativeEnum(SCANNERS).parse(scanner)
|
|
14556
|
+
});
|
|
14557
|
+
};
|
|
14558
|
+
if (polling) {
|
|
14559
|
+
debug18(
|
|
14560
|
+
"[waitForAnaysisAndReviewPr] Using POLLING mode for analysis state updates"
|
|
14561
|
+
);
|
|
14562
|
+
console.log(
|
|
14563
|
+
chalk6.cyan(
|
|
14564
|
+
"\u{1F504} [Polling Mode] Waiting for analysis completion using HTTP polling"
|
|
14565
|
+
)
|
|
14566
|
+
);
|
|
14567
|
+
await gqlClient.pollForAnalysisState({
|
|
14568
|
+
analysisId,
|
|
14569
|
+
callback,
|
|
14570
|
+
callbackStates: ["Finished" /* Finished */]
|
|
14571
|
+
});
|
|
14572
|
+
} else {
|
|
14573
|
+
debug18(
|
|
14574
|
+
"[waitForAnaysisAndReviewPr] Using WEBSOCKET mode for analysis state updates"
|
|
14575
|
+
);
|
|
14576
|
+
console.log(
|
|
14577
|
+
chalk6.cyan(
|
|
14578
|
+
"\u{1F50C} [WebSocket Mode] Waiting for analysis completion using WebSocket"
|
|
14579
|
+
)
|
|
14580
|
+
);
|
|
14581
|
+
await gqlClient.subscribeToAnalysis({
|
|
14582
|
+
subscribeToAnalysisParams: {
|
|
14583
|
+
analysisId
|
|
14584
|
+
},
|
|
14585
|
+
callback,
|
|
14586
|
+
callbackStates: ["Finished" /* Finished */]
|
|
14587
|
+
});
|
|
14588
|
+
}
|
|
14436
14589
|
}
|
|
14437
14590
|
|
|
14438
14591
|
// src/commands/index.ts
|
|
@@ -14447,7 +14600,8 @@ async function review(params, { skipPrompts = true } = {}) {
|
|
|
14447
14600
|
pullRequest,
|
|
14448
14601
|
githubToken,
|
|
14449
14602
|
scanner,
|
|
14450
|
-
srcPath
|
|
14603
|
+
srcPath,
|
|
14604
|
+
polling
|
|
14451
14605
|
} = params;
|
|
14452
14606
|
await runAnalysis(
|
|
14453
14607
|
{
|
|
@@ -14463,7 +14617,8 @@ async function review(params, { skipPrompts = true } = {}) {
|
|
|
14463
14617
|
githubToken,
|
|
14464
14618
|
scanner,
|
|
14465
14619
|
command: "review",
|
|
14466
|
-
srcPath
|
|
14620
|
+
srcPath,
|
|
14621
|
+
polling
|
|
14467
14622
|
},
|
|
14468
14623
|
{ skipPrompts }
|
|
14469
14624
|
);
|
|
@@ -14481,7 +14636,8 @@ async function analyze({
|
|
|
14481
14636
|
autoPr,
|
|
14482
14637
|
createOnePr,
|
|
14483
14638
|
commitDirectly,
|
|
14484
|
-
pullRequest
|
|
14639
|
+
pullRequest,
|
|
14640
|
+
polling
|
|
14485
14641
|
}, { skipPrompts = false } = {}) {
|
|
14486
14642
|
!ci && await showWelcomeMessage(skipPrompts);
|
|
14487
14643
|
await runAnalysis(
|
|
@@ -14499,7 +14655,8 @@ async function analyze({
|
|
|
14499
14655
|
autoPr,
|
|
14500
14656
|
commitDirectly,
|
|
14501
14657
|
pullRequest,
|
|
14502
|
-
createOnePr
|
|
14658
|
+
createOnePr,
|
|
14659
|
+
polling
|
|
14503
14660
|
},
|
|
14504
14661
|
{ skipPrompts }
|
|
14505
14662
|
);
|
|
@@ -14639,7 +14796,7 @@ function analyzeBuilder(yargs2) {
|
|
|
14639
14796
|
describe: chalk8.bold("Number of the pull request"),
|
|
14640
14797
|
type: "number",
|
|
14641
14798
|
demandOption: false
|
|
14642
|
-
}).example(
|
|
14799
|
+
}).option("polling", pollingOption).example(
|
|
14643
14800
|
"npx mobbdev@latest analyze -r https://github.com/WebGoat/WebGoat -f <your_vulnerability_report_path>",
|
|
14644
14801
|
"analyze an existing repository"
|
|
14645
14802
|
).help();
|
|
@@ -14948,7 +15105,14 @@ var defaultLogger2 = {
|
|
|
14948
15105
|
}
|
|
14949
15106
|
};
|
|
14950
15107
|
var PromptItemZ = z31.object({
|
|
14951
|
-
type: z31.enum([
|
|
15108
|
+
type: z31.enum([
|
|
15109
|
+
"USER_PROMPT",
|
|
15110
|
+
"AI_RESPONSE",
|
|
15111
|
+
"TOOL_EXECUTION",
|
|
15112
|
+
"AI_THINKING",
|
|
15113
|
+
"MCP_TOOL_CALL"
|
|
15114
|
+
// MCP (Model Context Protocol) tool invocation
|
|
15115
|
+
]),
|
|
14952
15116
|
attachedFiles: z31.array(
|
|
14953
15117
|
z31.object({
|
|
14954
15118
|
relativePath: z31.string(),
|
|
@@ -14966,7 +15130,12 @@ var PromptItemZ = z31.object({
|
|
|
14966
15130
|
parameters: z31.string(),
|
|
14967
15131
|
result: z31.string(),
|
|
14968
15132
|
rawArguments: z31.string().optional(),
|
|
14969
|
-
accepted: z31.boolean().optional()
|
|
15133
|
+
accepted: z31.boolean().optional(),
|
|
15134
|
+
// MCP-specific fields (only populated for MCP_TOOL_CALL type)
|
|
15135
|
+
mcpServer: z31.string().optional(),
|
|
15136
|
+
// MCP server name (e.g., "datadog", "mobb-mcp")
|
|
15137
|
+
mcpToolName: z31.string().optional()
|
|
15138
|
+
// MCP tool name without prefix (e.g., "scan_and_fix_vulnerabilities")
|
|
14970
15139
|
}).optional()
|
|
14971
15140
|
});
|
|
14972
15141
|
var PromptItemArrayZ = z31.array(PromptItemZ);
|
|
@@ -23845,7 +24014,7 @@ function reviewBuilder(yargs2) {
|
|
|
23845
24014
|
),
|
|
23846
24015
|
type: "string",
|
|
23847
24016
|
demandOption: false
|
|
23848
|
-
}).example(
|
|
24017
|
+
}).option("polling", pollingOption).example(
|
|
23849
24018
|
"npx mobbdev@latest review -r https://github.com/WebGoat/WebGoat -f <your_vulnerability_report_path> --ch <pr_last_commit> --pr <pr_number> --ref <pr_branch_name> --api-key <api_key> --src-path <your_repo_path>",
|
|
23850
24019
|
"add fixes to your pr"
|
|
23851
24020
|
).help();
|
|
@@ -23865,7 +24034,7 @@ async function reviewHandler(args) {
|
|
|
23865
24034
|
|
|
23866
24035
|
// src/args/commands/scan.ts
|
|
23867
24036
|
function scanBuilder(args) {
|
|
23868
|
-
return args.coerce("scanner", (arg) => arg.toLowerCase()).option("repo", repoOption).option("ref", refOption).option("scanner", scannerOptions).option("org", organizationIdOptions).option("mobb-project-name", mobbProjectNameOption).option("y", yesOption).option("ci", ciOption).option("api-key", apiKeyOption).option("cx-project-name", projectNameOption).option("auto-pr", autoPrOption).example(
|
|
24037
|
+
return args.coerce("scanner", (arg) => arg.toLowerCase()).option("repo", repoOption).option("ref", refOption).option("scanner", scannerOptions).option("org", organizationIdOptions).option("mobb-project-name", mobbProjectNameOption).option("y", yesOption).option("ci", ciOption).option("api-key", apiKeyOption).option("cx-project-name", projectNameOption).option("auto-pr", autoPrOption).option("polling", pollingOption).example(
|
|
23869
24038
|
"npx mobbdev@latest scan -r https://github.com/WebGoat/WebGoat",
|
|
23870
24039
|
"Scan an existing repository"
|
|
23871
24040
|
).help();
|