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 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(["USER_PROMPT", "AI_RESPONSE", "TOOL_EXECUTION", "AI_THINKING"]),
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);