mobbdev 1.2.0 → 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 +510 -248
- 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);
|