@alwaysmeticulous/debug-workspace 2.275.1 → 2.276.2
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 +8 -1
- package/dist/__tests__/extract-screenshot-dom-files.spec.d.ts +1 -0
- package/dist/__tests__/extract-screenshot-dom-files.spec.js +59 -0
- package/dist/__tests__/extract-screenshot-dom-files.spec.js.map +1 -0
- package/dist/__tests__/fetch-dom-diffs.spec.d.ts +1 -0
- package/dist/__tests__/fetch-dom-diffs.spec.js +316 -0
- package/dist/__tests__/fetch-dom-diffs.spec.js.map +1 -0
- package/dist/download-debug-data.js +25 -11
- package/dist/download-debug-data.js.map +1 -1
- package/dist/extract-screenshot-dom-files.d.ts +6 -0
- package/dist/extract-screenshot-dom-files.js +104 -0
- package/dist/extract-screenshot-dom-files.js.map +1 -0
- package/dist/fetch-dom-diffs.d.ts +36 -0
- package/dist/fetch-dom-diffs.js +338 -0
- package/dist/fetch-dom-diffs.js.map +1 -0
- package/dist/generate-debug-derived-files.js +57 -91
- package/dist/generate-debug-derived-files.js.map +1 -1
- package/dist/generate-debug-workspace.d.ts +10 -2
- package/dist/generate-debug-workspace.js +81 -84
- package/dist/generate-debug-workspace.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/pipeline.d.ts +2 -1
- package/dist/pipeline.js +6 -5
- package/dist/pipeline.js.map +1 -1
- package/dist/replay-walk.d.ts +40 -0
- package/dist/replay-walk.js +57 -0
- package/dist/replay-walk.js.map +1 -0
- package/dist/resolve-debug-context.js +12 -15
- package/dist/resolve-debug-context.js.map +1 -1
- package/dist/screenshot-identifier.d.ts +19 -0
- package/dist/screenshot-identifier.js +51 -0
- package/dist/screenshot-identifier.js.map +1 -0
- package/dist/templates/CLAUDE.md +115 -78
- package/package.json +6 -6
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="3c3e6a18-3b50-54ba-a2e4-296e73c18524")}catch(e){}}();
|
|
3
3
|
|
|
4
4
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
5
5
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
@@ -13,11 +13,13 @@ const path_1 = require("path");
|
|
|
13
13
|
const common_1 = require("@alwaysmeticulous/common");
|
|
14
14
|
const chalk_1 = __importDefault(require("chalk"));
|
|
15
15
|
const debug_constants_1 = require("./debug-constants");
|
|
16
|
+
const extract_screenshot_dom_files_1 = require("./extract-screenshot-dom-files");
|
|
17
|
+
const fetch_dom_diffs_1 = require("./fetch-dom-diffs");
|
|
16
18
|
const generate_debug_derived_files_1 = require("./generate-debug-derived-files");
|
|
19
|
+
const screenshot_identifier_1 = require("./screenshot-identifier");
|
|
17
20
|
const TEMPLATES_DIR = (0, path_1.join)(__dirname, "templates");
|
|
18
|
-
const generateDebugWorkspace = (options) => {
|
|
19
|
-
|
|
20
|
-
const { debugContext, workspaceDir } = options;
|
|
21
|
+
const generateDebugWorkspace = async (options) => {
|
|
22
|
+
const { client, debugContext, workspaceDir } = options;
|
|
21
23
|
const claudeDir = (0, path_1.join)(workspaceDir, ".claude");
|
|
22
24
|
(0, fs_1.mkdirSync)(claudeDir, { recursive: true });
|
|
23
25
|
copyClaudeMd(workspaceDir, options.additionalTemplatesDir);
|
|
@@ -30,13 +32,20 @@ const generateDebugWorkspace = (options) => {
|
|
|
30
32
|
generateTimelineSummaries(workspaceDir);
|
|
31
33
|
generateSessionSummaries(debugContext, workspaceDir);
|
|
32
34
|
prettifySnapshotAssets(workspaceDir);
|
|
35
|
+
(0, extract_screenshot_dom_files_1.extractScreenshotDomFiles)(workspaceDir);
|
|
36
|
+
const domDiffMap = await (0, fetch_dom_diffs_1.fetchDomDiffs)({
|
|
37
|
+
client,
|
|
38
|
+
debugContext,
|
|
39
|
+
workspaceDir,
|
|
40
|
+
maxConcurrency: options.maxConcurrency,
|
|
41
|
+
});
|
|
33
42
|
(0, generate_debug_derived_files_1.generateDebugDerivedFiles)(workspaceDir);
|
|
34
43
|
const screenshotMap = buildScreenshotMap(debugContext, workspaceDir);
|
|
35
44
|
generateScreenshotContext(debugContext, workspaceDir, screenshotMap);
|
|
36
45
|
const replayComparison = buildReplayComparison(debugContext, workspaceDir);
|
|
37
46
|
const fileMetadata = collectFileMetadata(debugContext, workspaceDir);
|
|
38
|
-
const writeCtx =
|
|
39
|
-
writeCtx(debugContext, workspaceDir, fileMetadata, options.projectRepoDir, screenshotMap, replayComparison);
|
|
47
|
+
const writeCtx = options.writeContextJson ?? defaultWriteContextJson;
|
|
48
|
+
writeCtx(debugContext, workspaceDir, fileMetadata, options.projectRepoDir, screenshotMap, replayComparison, domDiffMap);
|
|
40
49
|
copyClaudeSubdir(workspaceDir, "rules", options.additionalTemplatesDir);
|
|
41
50
|
copyClaudeSubdir(workspaceDir, "hooks", options.additionalTemplatesDir, {
|
|
42
51
|
makeExecutable: true,
|
|
@@ -234,7 +243,6 @@ const generateLogDiffs = (debugContext, workspaceDir) => {
|
|
|
234
243
|
}
|
|
235
244
|
};
|
|
236
245
|
const generateLogDiffPair = (basePath, headPath, workspaceDir, baseName) => {
|
|
237
|
-
var _a;
|
|
238
246
|
const diffDir = (0, path_1.join)(workspaceDir, debug_constants_1.DEBUG_DATA_DIRECTORY, "log-diffs");
|
|
239
247
|
(0, fs_1.mkdirSync)(diffDir, { recursive: true });
|
|
240
248
|
let rawDiff;
|
|
@@ -245,7 +253,7 @@ const generateLogDiffPair = (basePath, headPath, workspaceDir, baseName) => {
|
|
|
245
253
|
});
|
|
246
254
|
}
|
|
247
255
|
catch (error) {
|
|
248
|
-
rawDiff =
|
|
256
|
+
rawDiff = error?.stdout ?? "";
|
|
249
257
|
}
|
|
250
258
|
if (!rawDiff.trim()) {
|
|
251
259
|
return;
|
|
@@ -278,12 +286,11 @@ const filterLogDiff = (rawDiff) => {
|
|
|
278
286
|
return removeIdenticalHunks(filteredLines.join("\n"));
|
|
279
287
|
};
|
|
280
288
|
const removeIdenticalHunks = (diff) => {
|
|
281
|
-
var _a;
|
|
282
289
|
const parts = diff.split(/^(@@[^@]*@@.*$)/m);
|
|
283
290
|
const result = [parts[0]];
|
|
284
291
|
for (let i = 1; i < parts.length; i += 2) {
|
|
285
292
|
const hunkHeader = parts[i];
|
|
286
|
-
const hunkBody =
|
|
293
|
+
const hunkBody = parts[i + 1] ?? "";
|
|
287
294
|
const addedLines = [];
|
|
288
295
|
const removedLines = [];
|
|
289
296
|
for (const line of hunkBody.split("\n")) {
|
|
@@ -330,7 +337,7 @@ const summarizeLogDiff = (rawDiff) => {
|
|
|
330
337
|
`================`,
|
|
331
338
|
``,
|
|
332
339
|
`Total changed lines: ${addedCount + removedCount} (+${addedCount} in head, -${removedCount} in base)`,
|
|
333
|
-
`First divergence at base log line: ${firstDivergenceLine
|
|
340
|
+
`First divergence at base log line: ${firstDivergenceLine ?? "unknown"}`,
|
|
334
341
|
``,
|
|
335
342
|
`Change categories (+ = extra in head, - = extra in base):`,
|
|
336
343
|
];
|
|
@@ -348,10 +355,9 @@ const summarizeLogDiff = (rawDiff) => {
|
|
|
348
355
|
return parts.join("\n");
|
|
349
356
|
};
|
|
350
357
|
const categorizeLogLine = (line, categories, direction) => {
|
|
351
|
-
var _a;
|
|
352
358
|
const content = line.slice(1);
|
|
353
359
|
const category = classifyLogContent(content);
|
|
354
|
-
const entry =
|
|
360
|
+
const entry = categories[category] ?? { added: 0, removed: 0 };
|
|
355
361
|
entry[direction]++;
|
|
356
362
|
categories[category] = entry;
|
|
357
363
|
};
|
|
@@ -380,7 +386,6 @@ const classifyLogContent = (content) => {
|
|
|
380
386
|
return "other";
|
|
381
387
|
};
|
|
382
388
|
const generateDiffSummaries = (workspaceDir) => {
|
|
383
|
-
var _a, _b;
|
|
384
389
|
const diffsDir = (0, path_1.join)(workspaceDir, debug_constants_1.DEBUG_DATA_DIRECTORY, "diffs");
|
|
385
390
|
if (!(0, fs_1.existsSync)(diffsDir)) {
|
|
386
391
|
return;
|
|
@@ -389,7 +394,7 @@ const generateDiffSummaries = (workspaceDir) => {
|
|
|
389
394
|
const jsonFiles = (0, fs_1.readdirSync)(diffsDir).filter((f) => f.endsWith(".json") && !f.endsWith(".summary.json"));
|
|
390
395
|
for (const file of jsonFiles) {
|
|
391
396
|
const raw = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(diffsDir, file), "utf8"));
|
|
392
|
-
const results =
|
|
397
|
+
const results = raw?.data?.screenshotDiffResults ?? [];
|
|
393
398
|
if (results.length === 0) {
|
|
394
399
|
continue;
|
|
395
400
|
}
|
|
@@ -425,7 +430,6 @@ const generateDiffSummaries = (workspaceDir) => {
|
|
|
425
430
|
// PR diff from project repo
|
|
426
431
|
// ---------------------------------------------------------------------------
|
|
427
432
|
const generatePrDiff = (debugContext, workspaceDir) => {
|
|
428
|
-
var _a;
|
|
429
433
|
const projectRepoDir = (0, path_1.join)(workspaceDir, "project-repo");
|
|
430
434
|
if (!(0, fs_1.existsSync)(projectRepoDir)) {
|
|
431
435
|
return;
|
|
@@ -435,7 +439,7 @@ const generatePrDiff = (debugContext, workspaceDir) => {
|
|
|
435
439
|
if (!headSha) {
|
|
436
440
|
return;
|
|
437
441
|
}
|
|
438
|
-
const effectiveBaseSha = baseSha
|
|
442
|
+
const effectiveBaseSha = baseSha ?? resolveBaseShaFromGit(projectRepoDir, headSha);
|
|
439
443
|
if (!effectiveBaseSha) {
|
|
440
444
|
return;
|
|
441
445
|
}
|
|
@@ -444,7 +448,7 @@ const generatePrDiff = (debugContext, workspaceDir) => {
|
|
|
444
448
|
diffOutput = (0, child_process_1.execFileSync)("git", ["diff", `${effectiveBaseSha}..${headSha}`], { cwd: projectRepoDir, encoding: "utf8", maxBuffer: 50 * 1024 * 1024 });
|
|
445
449
|
}
|
|
446
450
|
catch (error) {
|
|
447
|
-
diffOutput =
|
|
451
|
+
diffOutput = error?.stdout ?? "";
|
|
448
452
|
}
|
|
449
453
|
if (diffOutput.trim()) {
|
|
450
454
|
(0, fs_1.writeFileSync)((0, path_1.join)(workspaceDir, debug_constants_1.DEBUG_DATA_DIRECTORY, "pr-diff.txt"), diffOutput);
|
|
@@ -469,7 +473,6 @@ const resolveBaseShaFromGit = (repoDir, headSha) => {
|
|
|
469
473
|
// Params diffs
|
|
470
474
|
// ---------------------------------------------------------------------------
|
|
471
475
|
const generateParamsDiffs = (debugContext, workspaceDir) => {
|
|
472
|
-
var _a;
|
|
473
476
|
const paramsFile = "launchBrowserAndReplayParams.json";
|
|
474
477
|
const pairs = [];
|
|
475
478
|
for (const diff of debugContext.replayDiffs) {
|
|
@@ -510,7 +513,7 @@ const generateParamsDiffs = (debugContext, workspaceDir) => {
|
|
|
510
513
|
});
|
|
511
514
|
}
|
|
512
515
|
catch (diffError) {
|
|
513
|
-
diffOutput =
|
|
516
|
+
diffOutput = diffError?.stdout ?? "";
|
|
514
517
|
}
|
|
515
518
|
finally {
|
|
516
519
|
safeUnlink(tmpA);
|
|
@@ -578,7 +581,6 @@ const generateAssetsDiff = (debugContext, workspaceDir) => {
|
|
|
578
581
|
}
|
|
579
582
|
};
|
|
580
583
|
const compareAssetDirs = (baseDir, headDir) => {
|
|
581
|
-
var _a;
|
|
582
584
|
const baseFiles = listAssetFiles(baseDir);
|
|
583
585
|
const headFiles = listAssetFiles(headDir);
|
|
584
586
|
if (baseFiles.size === 0 && headFiles.size === 0) {
|
|
@@ -593,7 +595,7 @@ const compareAssetDirs = (baseDir, headDir) => {
|
|
|
593
595
|
const baseInfo = baseFiles.get(name);
|
|
594
596
|
const headInfo = headFiles.get(name);
|
|
595
597
|
if (!baseInfo) {
|
|
596
|
-
added.push(` + ${name} (${
|
|
598
|
+
added.push(` + ${name} (${headInfo?.size ?? 0} bytes)`);
|
|
597
599
|
}
|
|
598
600
|
else if (!headInfo) {
|
|
599
601
|
removed.push(` - ${name} (${baseInfo.size} bytes)`);
|
|
@@ -681,7 +683,6 @@ const generateTimelineSummaries = (workspaceDir) => {
|
|
|
681
683
|
}
|
|
682
684
|
};
|
|
683
685
|
const summarizeTimeline = (timeline, replayId, role) => {
|
|
684
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
685
686
|
const eventKindCounts = {};
|
|
686
687
|
const screenshotEntries = [];
|
|
687
688
|
let navigationCount = 0;
|
|
@@ -693,7 +694,7 @@ const summarizeTimeline = (timeline, replayId, role) => {
|
|
|
693
694
|
const flakinessWarnings = [];
|
|
694
695
|
for (const entry of timeline) {
|
|
695
696
|
const kind = entry.kind;
|
|
696
|
-
eventKindCounts[kind] = (
|
|
697
|
+
eventKindCounts[kind] = (eventKindCounts[kind] ?? 0) + 1;
|
|
697
698
|
const vt = entry.virtualTimeStart;
|
|
698
699
|
if (vt != null) {
|
|
699
700
|
if (firstVirtualTime == null || vt < firstVirtualTime) {
|
|
@@ -706,17 +707,19 @@ const summarizeTimeline = (timeline, replayId, role) => {
|
|
|
706
707
|
if (kind.startsWith("potentialFlakinessWarning")) {
|
|
707
708
|
flakinessWarnings.push({
|
|
708
709
|
kind,
|
|
709
|
-
message:
|
|
710
|
+
message: entry.data?.message ??
|
|
711
|
+
entry.data?.warning ??
|
|
712
|
+
JSON.stringify(entry.data ?? {}),
|
|
710
713
|
virtualTime: vt,
|
|
711
714
|
});
|
|
712
715
|
}
|
|
713
716
|
switch (kind) {
|
|
714
717
|
case "screenshot": {
|
|
715
|
-
const filename =
|
|
716
|
-
? screenshotIdentifierToFilename(entry.data.identifier)
|
|
718
|
+
const filename = entry.data?.identifier
|
|
719
|
+
? (0, screenshot_identifier_1.screenshotIdentifierToFilename)(entry.data.identifier)
|
|
717
720
|
: undefined;
|
|
718
721
|
screenshotEntries.push({
|
|
719
|
-
filename: filename
|
|
722
|
+
filename: filename ?? "unknown",
|
|
720
723
|
virtualTime: vt,
|
|
721
724
|
});
|
|
722
725
|
break;
|
|
@@ -748,7 +751,7 @@ const summarizeTimeline = (timeline, replayId, role) => {
|
|
|
748
751
|
"",
|
|
749
752
|
`Total timeline entries: ${timeline.length}`,
|
|
750
753
|
`Total virtual time: ${totalVirtualTimeMs != null ? `${totalVirtualTimeMs}ms` : "unknown"}`,
|
|
751
|
-
`Virtual time range: ${firstVirtualTime
|
|
754
|
+
`Virtual time range: ${firstVirtualTime ?? "?"} - ${lastVirtualTime ?? "?"}`,
|
|
752
755
|
"",
|
|
753
756
|
"Key counts:",
|
|
754
757
|
` Screenshots: ${screenshotEntries.length}`,
|
|
@@ -878,7 +881,6 @@ const findAssetFilesRecursive = (baseDir, relativeTo) => {
|
|
|
878
881
|
// ---------------------------------------------------------------------------
|
|
879
882
|
const SCREENSHOT_LOG_CONTEXT_LINES = 30;
|
|
880
883
|
const buildScreenshotMap = (debugContext, workspaceDir) => {
|
|
881
|
-
var _a, _b, _c, _d;
|
|
882
884
|
const map = {};
|
|
883
885
|
for (const subDir of ["head", "base", "other"]) {
|
|
884
886
|
const subDirPath = (0, path_1.join)(workspaceDir, debug_constants_1.DEBUG_DATA_DIRECTORY, "replays", subDir);
|
|
@@ -894,22 +896,32 @@ const buildScreenshotMap = (debugContext, workspaceDir) => {
|
|
|
894
896
|
if (!Array.isArray(timeline)) {
|
|
895
897
|
continue;
|
|
896
898
|
}
|
|
899
|
+
const screenshotsDir = (0, path_1.join)(subDirPath, replayId, "screenshots");
|
|
897
900
|
for (const entry of timeline) {
|
|
898
901
|
const e = entry;
|
|
899
|
-
if (e.kind !== "screenshot" || !
|
|
902
|
+
if (e.kind !== "screenshot" || !e.data?.identifier) {
|
|
900
903
|
continue;
|
|
901
904
|
}
|
|
902
|
-
const filename = screenshotIdentifierToFilename(e.data.identifier);
|
|
905
|
+
const filename = (0, screenshot_identifier_1.screenshotIdentifierToFilename)(e.data.identifier);
|
|
903
906
|
if (!filename) {
|
|
904
907
|
continue;
|
|
905
908
|
}
|
|
909
|
+
const baseName = filename.endsWith(".png")
|
|
910
|
+
? filename.slice(0, -".png".length)
|
|
911
|
+
: filename;
|
|
912
|
+
const htmlFilename = `${baseName}.html`;
|
|
913
|
+
const afterHtmlFilename = `${baseName}.after.html`;
|
|
914
|
+
const htmlExists = (0, fs_1.existsSync)((0, path_1.join)(screenshotsDir, htmlFilename));
|
|
915
|
+
const afterHtmlExists = (0, fs_1.existsSync)((0, path_1.join)(screenshotsDir, afterHtmlFilename));
|
|
906
916
|
map[`${subDir}/${replayId}/${filename}`] = {
|
|
907
917
|
replayId,
|
|
908
918
|
replayRole: subDir,
|
|
909
919
|
filename,
|
|
910
|
-
virtualTimeStart:
|
|
911
|
-
virtualTimeEnd:
|
|
912
|
-
eventNumber:
|
|
920
|
+
virtualTimeStart: e.virtualTimeStart ?? null,
|
|
921
|
+
virtualTimeEnd: e.virtualTimeEnd ?? null,
|
|
922
|
+
eventNumber: e.data.identifier.eventNumber ?? null,
|
|
923
|
+
htmlFilename: htmlExists ? htmlFilename : null,
|
|
924
|
+
afterHtmlFilename: afterHtmlExists ? afterHtmlFilename : null,
|
|
913
925
|
};
|
|
914
926
|
}
|
|
915
927
|
}
|
|
@@ -919,23 +931,7 @@ const buildScreenshotMap = (debugContext, workspaceDir) => {
|
|
|
919
931
|
}
|
|
920
932
|
return map;
|
|
921
933
|
};
|
|
922
|
-
const screenshotIdentifierToFilename = (identifier) => {
|
|
923
|
-
const variantPortion = identifier.variant === "redacted" ? ".redacted" : "";
|
|
924
|
-
if (identifier.type === "end-state") {
|
|
925
|
-
return identifier.logicVersion == null
|
|
926
|
-
? `final-state${variantPortion}.png`
|
|
927
|
-
: `final-state-v${identifier.logicVersion}${variantPortion}.png`;
|
|
928
|
-
}
|
|
929
|
-
if (identifier.type === "after-event" && identifier.eventNumber != null) {
|
|
930
|
-
const eventIndexStr = identifier.eventNumber.toString().padStart(5, "0");
|
|
931
|
-
return identifier.logicVersion == null
|
|
932
|
-
? `screenshot-after-event-${eventIndexStr}${variantPortion}.png`
|
|
933
|
-
: `screenshot-after-event-${eventIndexStr}-v${identifier.logicVersion}${variantPortion}.png`;
|
|
934
|
-
}
|
|
935
|
-
return undefined;
|
|
936
|
-
};
|
|
937
934
|
const generateScreenshotContext = (debugContext, workspaceDir, screenshotMap) => {
|
|
938
|
-
var _a, _b, _c, _d;
|
|
939
935
|
if (!debugContext.screenshot) {
|
|
940
936
|
return;
|
|
941
937
|
}
|
|
@@ -952,14 +948,14 @@ const generateScreenshotContext = (debugContext, workspaceDir, screenshotMap) =>
|
|
|
952
948
|
"",
|
|
953
949
|
];
|
|
954
950
|
if (headEntry) {
|
|
955
|
-
parts.push(`HEAD (${diff.headReplayId}) @ virtualTime ${
|
|
951
|
+
parts.push(`HEAD (${diff.headReplayId}) @ virtualTime ${headEntry.virtualTimeStart ?? "?"}ms, event ${headEntry.eventNumber ?? "?"}:`, "");
|
|
956
952
|
const headContext = extractLogContext(headLogPath, headEntry);
|
|
957
|
-
parts.push(headContext
|
|
953
|
+
parts.push(headContext ?? " (could not extract log context)", "");
|
|
958
954
|
}
|
|
959
955
|
if (baseEntry) {
|
|
960
|
-
parts.push(`BASE (${diff.baseReplayId}) @ virtualTime ${
|
|
956
|
+
parts.push(`BASE (${diff.baseReplayId}) @ virtualTime ${baseEntry.virtualTimeStart ?? "?"}ms, event ${baseEntry.eventNumber ?? "?"}:`, "");
|
|
961
957
|
const baseContext = extractLogContext(baseLogPath, baseEntry);
|
|
962
|
-
parts.push(baseContext
|
|
958
|
+
parts.push(baseContext ?? " (could not extract log context)", "");
|
|
963
959
|
}
|
|
964
960
|
if (headEntry || baseEntry) {
|
|
965
961
|
const contextDir = (0, path_1.join)(workspaceDir, debug_constants_1.DEBUG_DATA_DIRECTORY, "screenshot-context");
|
|
@@ -1026,7 +1022,6 @@ const buildReplayComparison = (debugContext, workspaceDir) => {
|
|
|
1026
1022
|
return entries;
|
|
1027
1023
|
};
|
|
1028
1024
|
const extractReplayStats = (replayDir) => {
|
|
1029
|
-
var _a, _b, _c;
|
|
1030
1025
|
const stats = {
|
|
1031
1026
|
totalEvents: null,
|
|
1032
1027
|
totalNetworkRequests: null,
|
|
@@ -1037,10 +1032,10 @@ const extractReplayStats = (replayDir) => {
|
|
|
1037
1032
|
const timelineStatsPath = (0, path_1.join)(replayDir, "timeline-stats.json");
|
|
1038
1033
|
if ((0, fs_1.existsSync)(timelineStatsPath)) {
|
|
1039
1034
|
const timelineStats = JSON.parse((0, fs_1.readFileSync)(timelineStatsPath, "utf8"));
|
|
1040
|
-
const counts =
|
|
1035
|
+
const counts = timelineStats.countByType ?? {};
|
|
1041
1036
|
stats.totalEvents = Object.values(counts).reduce((sum, n) => sum + n, 0);
|
|
1042
|
-
stats.totalNetworkRequests =
|
|
1043
|
-
stats.totalAnimationFrames =
|
|
1037
|
+
stats.totalNetworkRequests = counts["pollyReplay"] ?? null;
|
|
1038
|
+
stats.totalAnimationFrames = counts["jsReplay"] ?? null;
|
|
1044
1039
|
}
|
|
1045
1040
|
const timelinePath = (0, path_1.join)(replayDir, "timeline.json");
|
|
1046
1041
|
if ((0, fs_1.existsSync)(timelinePath)) {
|
|
@@ -1155,22 +1150,21 @@ const generateSessionSummaries = (debugContext, workspaceDir) => {
|
|
|
1155
1150
|
}
|
|
1156
1151
|
};
|
|
1157
1152
|
const summarizeSession = (data, sessionId) => {
|
|
1158
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5;
|
|
1159
1153
|
const parts = [
|
|
1160
1154
|
`Session Summary: ${sessionId}`,
|
|
1161
1155
|
"=".repeat(20 + sessionId.length),
|
|
1162
1156
|
"",
|
|
1163
1157
|
];
|
|
1164
|
-
const win =
|
|
1165
|
-
parts.push(`Window: ${
|
|
1166
|
-
if (
|
|
1158
|
+
const win = data.userEvents?.window;
|
|
1159
|
+
parts.push(`Window: ${win?.startUrl ?? "unknown"}`);
|
|
1160
|
+
if (win?.width != null && win?.height != null) {
|
|
1167
1161
|
parts.push(`Viewport: ${win.width} x ${win.height}`);
|
|
1168
1162
|
}
|
|
1169
|
-
parts.push(`Hostname: ${
|
|
1170
|
-
parts.push(`Recorded: ${
|
|
1163
|
+
parts.push(`Hostname: ${data.hostname ?? "unknown"}`);
|
|
1164
|
+
parts.push(`Recorded: ${data.datetime_first_payload ?? "unknown"}`);
|
|
1171
1165
|
parts.push(`Abandoned: ${data.abandoned ? "yes" : "no"}`);
|
|
1172
1166
|
parts.push("");
|
|
1173
|
-
const history =
|
|
1167
|
+
const history = data.urlHistory ?? [];
|
|
1174
1168
|
if (history.length > 0) {
|
|
1175
1169
|
parts.push(`URL History (${history.length} pages):`);
|
|
1176
1170
|
for (const entry of history) {
|
|
@@ -1178,16 +1172,16 @@ const summarizeSession = (data, sessionId) => {
|
|
|
1178
1172
|
const pattern = entry.urlPattern
|
|
1179
1173
|
? ` [pattern: ${entry.urlPattern}]`
|
|
1180
1174
|
: "";
|
|
1181
|
-
parts.push(` ${ts} ${
|
|
1175
|
+
parts.push(` ${ts} ${entry.url ?? "unknown"}${pattern}`);
|
|
1182
1176
|
}
|
|
1183
1177
|
parts.push("");
|
|
1184
1178
|
}
|
|
1185
|
-
const events =
|
|
1179
|
+
const events = data.userEvents?.event_log ?? [];
|
|
1186
1180
|
if (events.length > 0) {
|
|
1187
1181
|
const typeCounts = {};
|
|
1188
1182
|
for (const event of events) {
|
|
1189
|
-
typeCounts[
|
|
1190
|
-
(
|
|
1183
|
+
typeCounts[event.type ?? "unknown"] =
|
|
1184
|
+
(typeCounts[event.type ?? "unknown"] ?? 0) + 1;
|
|
1191
1185
|
}
|
|
1192
1186
|
parts.push(`User Events: ${events.length} events`);
|
|
1193
1187
|
for (const [type, count] of Object.entries(typeCounts).sort(([, a], [, b]) => b - a)) {
|
|
@@ -1195,15 +1189,15 @@ const summarizeSession = (data, sessionId) => {
|
|
|
1195
1189
|
}
|
|
1196
1190
|
parts.push("");
|
|
1197
1191
|
}
|
|
1198
|
-
const harContainer =
|
|
1192
|
+
const harContainer = data.pollyHAR?.pollyHAR;
|
|
1199
1193
|
if (harContainer) {
|
|
1200
|
-
const allEntries = Object.values(harContainer).flatMap((r) =>
|
|
1194
|
+
const allEntries = Object.values(harContainer).flatMap((r) => r?.log?.entries ?? []);
|
|
1201
1195
|
if (allEntries.length > 0) {
|
|
1202
1196
|
parts.push(`Network Requests: ${allEntries.length} total`);
|
|
1203
1197
|
const methodCounts = {};
|
|
1204
1198
|
for (const entry of allEntries) {
|
|
1205
|
-
const method =
|
|
1206
|
-
methodCounts[method] = (
|
|
1199
|
+
const method = entry.request?.method ?? "UNKNOWN";
|
|
1200
|
+
methodCounts[method] = (methodCounts[method] ?? 0) + 1;
|
|
1207
1201
|
}
|
|
1208
1202
|
parts.push(` Methods: ${Object.entries(methodCounts)
|
|
1209
1203
|
.sort(([, a], [, b]) => b - a)
|
|
@@ -1212,19 +1206,19 @@ const summarizeSession = (data, sessionId) => {
|
|
|
1212
1206
|
parts.push("");
|
|
1213
1207
|
}
|
|
1214
1208
|
}
|
|
1215
|
-
const localStorage =
|
|
1216
|
-
const sessionStorage =
|
|
1217
|
-
const cookies =
|
|
1209
|
+
const localStorage = data.randomEvents?.localStorage?.state?.length ?? 0;
|
|
1210
|
+
const sessionStorage = data.randomEvents?.sessionStorage?.state?.length ?? 0;
|
|
1211
|
+
const cookies = data.cookies?.length ?? 0;
|
|
1218
1212
|
parts.push("Storage:");
|
|
1219
1213
|
parts.push(` localStorage: ${localStorage} entries`);
|
|
1220
1214
|
parts.push(` sessionStorage: ${sessionStorage} entries`);
|
|
1221
1215
|
parts.push(` Cookies: ${cookies}`);
|
|
1222
1216
|
parts.push("");
|
|
1223
|
-
const connections =
|
|
1217
|
+
const connections = data.webSocketData ?? [];
|
|
1224
1218
|
if (connections.length > 0) {
|
|
1225
1219
|
parts.push(`WebSocket Connections: ${connections.length}`);
|
|
1226
1220
|
for (const conn of connections) {
|
|
1227
|
-
parts.push(` ${
|
|
1221
|
+
parts.push(` ${conn.url ?? "unknown"} (${conn.events?.length ?? 0} events)`);
|
|
1228
1222
|
}
|
|
1229
1223
|
parts.push("");
|
|
1230
1224
|
}
|
|
@@ -1234,21 +1228,21 @@ const summarizeSession = (data, sessionId) => {
|
|
|
1234
1228
|
if (ctx.userId || ctx.userEmail) {
|
|
1235
1229
|
parts.push(` User: ${[ctx.userId, ctx.userEmail].filter(Boolean).join(" / ")}`);
|
|
1236
1230
|
}
|
|
1237
|
-
const flags = Object.entries(
|
|
1231
|
+
const flags = Object.entries(ctx.featureFlags ?? {});
|
|
1238
1232
|
if (flags.length > 0) {
|
|
1239
1233
|
parts.push(` Feature flags: ${flags.map(([k, v]) => `${k}=${v}`).join(", ")}`);
|
|
1240
1234
|
}
|
|
1241
1235
|
parts.push("");
|
|
1242
1236
|
}
|
|
1243
1237
|
const appData = data.applicationSpecificData;
|
|
1244
|
-
if (appData
|
|
1238
|
+
if (appData?.nextJs) {
|
|
1245
1239
|
parts.push("Framework: Next.js");
|
|
1246
1240
|
if (appData.nextJs.page) {
|
|
1247
1241
|
parts.push(` Page: ${appData.nextJs.page}`);
|
|
1248
1242
|
}
|
|
1249
1243
|
parts.push("");
|
|
1250
1244
|
}
|
|
1251
|
-
else if (appData
|
|
1245
|
+
else if (appData?.reactRouter) {
|
|
1252
1246
|
parts.push("Framework: React Router");
|
|
1253
1247
|
parts.push("");
|
|
1254
1248
|
}
|
|
@@ -1257,7 +1251,7 @@ const summarizeSession = (data, sessionId) => {
|
|
|
1257
1251
|
// ---------------------------------------------------------------------------
|
|
1258
1252
|
// Context JSON generation (default implementation)
|
|
1259
1253
|
// ---------------------------------------------------------------------------
|
|
1260
|
-
const defaultWriteContextJson = (debugContext, workspaceDir, fileMetadata, projectRepoDir, screenshotMap, replayComparison) => {
|
|
1254
|
+
const defaultWriteContextJson = (debugContext, workspaceDir, fileMetadata, projectRepoDir, screenshotMap, replayComparison, domDiffMap) => {
|
|
1261
1255
|
const headIds = new Set(debugContext.replayDiffs.map((d) => d.headReplayId));
|
|
1262
1256
|
const baseIds = new Set(debugContext.replayDiffs.map((d) => d.baseReplayId));
|
|
1263
1257
|
const headReplays = [];
|
|
@@ -1293,6 +1287,7 @@ const defaultWriteContextJson = (debugContext, workspaceDir, fileMetadata, proje
|
|
|
1293
1287
|
sessions: debugContext.sessionIds,
|
|
1294
1288
|
screenshotMap,
|
|
1295
1289
|
replayComparison,
|
|
1290
|
+
domDiffMap,
|
|
1296
1291
|
paths: {
|
|
1297
1292
|
replays: "replays/",
|
|
1298
1293
|
sessions: "sessions/",
|
|
@@ -1304,6 +1299,8 @@ const defaultWriteContextJson = (debugContext, workspaceDir, fileMetadata, proje
|
|
|
1304
1299
|
assetsDiffs: "assets-diffs/",
|
|
1305
1300
|
timelineSummaries: "timeline-summaries/",
|
|
1306
1301
|
screenshotContext: "screenshot-context/",
|
|
1302
|
+
domDiffs: "dom-diffs/",
|
|
1303
|
+
domDiffsSummary: "dom-diffs/*.summary.txt",
|
|
1307
1304
|
prDiff: "pr-diff.txt",
|
|
1308
1305
|
formattedAssets: "formatted-assets/",
|
|
1309
1306
|
testRun: "test-run/",
|
|
@@ -1314,4 +1311,4 @@ const defaultWriteContextJson = (debugContext, workspaceDir, fileMetadata, proje
|
|
|
1314
1311
|
(0, fs_1.writeFileSync)((0, path_1.join)(workspaceDir, debug_constants_1.DEBUG_DATA_DIRECTORY, "context.json"), JSON.stringify(context, null, 2));
|
|
1315
1312
|
};
|
|
1316
1313
|
//# sourceMappingURL=generate-debug-workspace.js.map
|
|
1317
|
-
//# debugId=
|
|
1314
|
+
//# debugId=3c3e6a18-3b50-54ba-a2e4-296e73c18524
|