@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
|
-
|
|
288
|
-
|
|
289
|
-
|
|
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
|
-
|
|
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)
|