@debugg-ai/debugg-ai-mcp 2.6.0 → 2.6.1

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.
@@ -24,6 +24,7 @@ import { extractLocalhostPort } from '../utils/urlParser.js';
24
24
  import { buildContext, findExistingTunnel, ensureTunnel, sanitizeResponseUrls, touchTunnelById, } from '../utils/tunnelContext.js';
25
25
  import { getCachedTemplateUuid, invalidateTemplateCache } from '../utils/handlerCaches.js';
26
26
  import { reaggregateByOriginPath, mapConsoleSlice } from '../utils/harSummarizer.js';
27
+ import { fetchImageAsBase64, imageContentBlock } from '../utils/imageUtils.js';
27
28
  const logger = new Logger({ module: 'probePageHandler' });
28
29
  const TEMPLATE_KEYWORD = 'page probe';
29
30
  export async function probePageHandler(input, context, rawProgressCallback) {
@@ -256,12 +257,6 @@ export async function probePageHandler(input, context, rawProgressCallback) {
256
257
  result.surferPageUuid = data.surferPageUuid;
257
258
  }
258
259
  results.push(result);
259
- // Backend stores screenshots on the SurferPage row referenced by
260
- // surfer_page_uuid; the inline screenshotB64 is no longer in capture
261
- // output. v1: skip the per-result image content block; the screenshot
262
- // is reachable via search_executions detail's surfer_page_uuid → SurferPage.
263
- // (Future enhancement: fetch the SurferPage's presigned screenshot_url
264
- // when input.captureScreenshots is true.)
265
260
  }
266
261
  const responsePayload = {
267
262
  executionId: executionUuid,
@@ -284,11 +279,35 @@ export async function probePageHandler(input, context, rawProgressCallback) {
284
279
  }
285
280
  }
286
281
  logger.toolComplete('probe_page', duration);
287
- return {
288
- content: [
289
- { type: 'text', text: JSON.stringify(sanitizedPayload, null, 2) },
290
- ],
291
- };
282
+ const responseContent = [
283
+ { type: 'text', text: JSON.stringify(sanitizedPayload, null, 2) },
284
+ ];
285
+ // Embed screenshots when captureScreenshots is true. The backend may return
286
+ // screenshotB64 or a URL-keyed field on browser.capture outputData.
287
+ if (input.captureScreenshots) {
288
+ const SCREENSHOT_URL_KEYS = ['screenshotB64', 'screenshot', 'screenshotUrl', 'screenshotUri', 'finalScreenshot'];
289
+ for (const node of captureNodes) {
290
+ const data = node?.outputData ?? {};
291
+ if (typeof data.screenshotB64 === 'string' && data.screenshotB64) {
292
+ responseContent.push(imageContentBlock(data.screenshotB64, 'image/png'));
293
+ }
294
+ else {
295
+ let screenshotUrl = null;
296
+ for (const key of SCREENSHOT_URL_KEYS) {
297
+ if (key !== 'screenshotB64' && typeof data[key] === 'string' && data[key]) {
298
+ screenshotUrl = data[key];
299
+ break;
300
+ }
301
+ }
302
+ if (screenshotUrl) {
303
+ const img = await fetchImageAsBase64(screenshotUrl).catch(() => null);
304
+ if (img)
305
+ responseContent.push(imageContentBlock(img.data, img.mimeType));
306
+ }
307
+ }
308
+ }
309
+ }
310
+ return { content: responseContent };
292
311
  }
293
312
  catch (error) {
294
313
  const duration = Date.now() - startTime;
@@ -13,6 +13,7 @@ import { handleExternalServiceError } from '../utils/errors.js';
13
13
  import { DebuggAIServerClient } from '../services/index.js';
14
14
  import { config } from '../config/index.js';
15
15
  import { toPaginationParams } from '../utils/pagination.js';
16
+ import { fetchImageAsBase64, imageContentBlock } from '../utils/imageUtils.js';
16
17
  const logger = new Logger({ module: 'searchExecutionsHandler' });
17
18
  function notFound(uuid) {
18
19
  return {
@@ -38,7 +39,53 @@ export async function searchExecutionsHandler(input, _context) {
38
39
  executions: [execution],
39
40
  };
40
41
  logger.toolComplete('search_executions', Date.now() - start);
41
- return { content: [{ type: 'text', text: JSON.stringify(payload, null, 2) }] };
42
+ const content = [
43
+ { type: 'text', text: JSON.stringify(payload, null, 2) },
44
+ ];
45
+ const SCREENSHOT_URL_KEYS = ['finalScreenshot', 'screenshot', 'screenshotUrl', 'screenshotUri'];
46
+ const GIF_KEYS = ['runGif', 'gifUrl', 'gif', 'videoUrl', 'recordingUrl'];
47
+ const nodes = execution.nodeExecutions ?? [];
48
+ const subworkflowNode = nodes.find((n) => n.nodeType === 'subworkflow.run');
49
+ let screenshotEmbedded = false;
50
+ let screenshotUrl = null;
51
+ let gifUrl = null;
52
+ const screenshotB64 = subworkflowNode?.outputData?.screenshotB64;
53
+ if (typeof screenshotB64 === 'string' && screenshotB64) {
54
+ content.push(imageContentBlock(screenshotB64, 'image/png'));
55
+ screenshotEmbedded = true;
56
+ }
57
+ for (const node of nodes) {
58
+ const data = node.outputData ?? {};
59
+ if (!screenshotEmbedded && !screenshotUrl) {
60
+ for (const key of SCREENSHOT_URL_KEYS) {
61
+ if (typeof data[key] === 'string' && data[key]) {
62
+ screenshotUrl = data[key];
63
+ break;
64
+ }
65
+ }
66
+ }
67
+ if (!gifUrl) {
68
+ for (const key of GIF_KEYS) {
69
+ if (typeof data[key] === 'string' && data[key]) {
70
+ gifUrl = data[key];
71
+ break;
72
+ }
73
+ }
74
+ }
75
+ if ((screenshotEmbedded || screenshotUrl) && gifUrl)
76
+ break;
77
+ }
78
+ if (!screenshotEmbedded && screenshotUrl) {
79
+ const img = await fetchImageAsBase64(screenshotUrl).catch(() => null);
80
+ if (img)
81
+ content.push(imageContentBlock(img.data, img.mimeType));
82
+ }
83
+ if (gifUrl) {
84
+ const gif = await fetchImageAsBase64(gifUrl).catch(() => null);
85
+ if (gif)
86
+ content.push(imageContentBlock(gif.data, 'image/gif'));
87
+ }
88
+ return { content };
42
89
  }
43
90
  catch (err) {
44
91
  if (err?.statusCode === 404 || err?.response?.status === 404)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@debugg-ai/debugg-ai-mcp",
3
- "version": "2.6.0",
3
+ "version": "2.6.1",
4
4
  "description": "Zero-Config, Fully AI-Managed End-to-End Testing for all code gen platforms.",
5
5
  "type": "module",
6
6
  "bin": {