@empiricalrun/test-gen 0.79.3 → 0.79.4

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.
Files changed (117) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/agent/chat/index.d.ts.map +1 -1
  3. package/dist/agent/chat/index.js +21 -2
  4. package/dist/agent/chat/prompt/pw-utils-docs.d.ts +1 -1
  5. package/dist/agent/chat/prompt/pw-utils-docs.d.ts.map +1 -1
  6. package/dist/agent/chat/prompt/pw-utils-docs.js +1 -1
  7. package/dist/agent/chat/prompt/trace-utils-docs.d.ts +2 -0
  8. package/dist/agent/chat/prompt/trace-utils-docs.d.ts.map +1 -0
  9. package/dist/agent/chat/prompt/trace-utils-docs.js +208 -0
  10. package/dist/agent/code-review/index.d.ts +1 -1
  11. package/dist/agent/code-review/index.d.ts.map +1 -1
  12. package/dist/agent/code-review/index.js +4 -4
  13. package/dist/agent/code-review/{parser.d.ts → xml-parser.d.ts} +1 -1
  14. package/dist/agent/code-review/xml-parser.d.ts.map +1 -0
  15. package/dist/agent/code-review/{parser.js → xml-parser.js} +1 -1
  16. package/dist/agent/fast-triage/index.d.ts.map +1 -1
  17. package/dist/agent/fast-triage/index.js +31 -3
  18. package/dist/agent/master/element-annotation.d.ts.map +1 -1
  19. package/dist/agent/master/element-annotation.js +2 -19
  20. package/dist/bin/index.js +0 -2
  21. package/dist/constants/index.d.ts +1 -1
  22. package/dist/constants/index.js +1 -1
  23. package/dist/dashboard/client.d.ts +5 -0
  24. package/dist/dashboard/client.d.ts.map +1 -1
  25. package/dist/dashboard/client.js +11 -0
  26. package/dist/dashboard/index.d.ts +1 -0
  27. package/dist/dashboard/index.d.ts.map +1 -1
  28. package/dist/dashboard/index.js +4 -1
  29. package/dist/dashboard/tool-response-from-sandbox.d.ts +5 -0
  30. package/dist/dashboard/tool-response-from-sandbox.d.ts.map +1 -0
  31. package/dist/dashboard/tool-response-from-sandbox.js +40 -0
  32. package/dist/dashboard/tool-response.d.ts +1 -0
  33. package/dist/dashboard/tool-response.d.ts.map +1 -1
  34. package/dist/dashboard/tool-response.js +1 -0
  35. package/dist/file-info/adapters/github/reader.d.ts.map +1 -1
  36. package/dist/file-info/adapters/github/reader.js +9 -3
  37. package/dist/generate-summary/generate-error-stack-summary.js +1 -4
  38. package/dist/generate-summary/generate-failed-step-screenshot-diff-summary.d.ts.map +1 -1
  39. package/dist/generate-summary/generate-failed-step-screenshot-diff-summary.js +8 -8
  40. package/dist/generate-summary/generate-grouped-summary.js +1 -4
  41. package/dist/generate-summary/merge-summary.js +1 -4
  42. package/dist/telemetry/index.d.ts +3 -3
  43. package/dist/telemetry/index.d.ts.map +1 -1
  44. package/dist/telemetry/index.js +8 -5
  45. package/dist/tools/analyse-video/index.js +1 -1
  46. package/dist/tools/definitions/publish-markdown-report.d.ts +8 -0
  47. package/dist/tools/definitions/publish-markdown-report.d.ts.map +1 -0
  48. package/dist/tools/definitions/publish-markdown-report.js +29 -0
  49. package/dist/tools/diagnosis-fetcher.d.ts +5 -0
  50. package/dist/tools/diagnosis-fetcher.d.ts.map +1 -1
  51. package/dist/tools/diagnosis-fetcher.js +17 -12
  52. package/dist/tools/executor/index.d.ts.map +1 -1
  53. package/dist/tools/executor/index.js +2 -2
  54. package/dist/tools/fetch-file/index.d.ts.map +1 -1
  55. package/dist/tools/fetch-file/index.js +11 -10
  56. package/dist/tools/fetch-file/utils.d.ts +13 -1
  57. package/dist/tools/fetch-file/utils.d.ts.map +1 -1
  58. package/dist/tools/fetch-file/utils.js +44 -118
  59. package/dist/tools/index.d.ts +1 -1
  60. package/dist/tools/index.d.ts.map +1 -1
  61. package/dist/tools/index.js +9 -5
  62. package/dist/tools/issues-v1/index.d.ts +0 -2
  63. package/dist/tools/issues-v1/index.d.ts.map +1 -1
  64. package/dist/tools/issues-v1/index.js +1 -5
  65. package/dist/tools/publish-markdown-report/index.d.ts +3 -0
  66. package/dist/tools/publish-markdown-report/index.d.ts.map +1 -0
  67. package/dist/tools/publish-markdown-report/index.js +196 -0
  68. package/dist/tools/test-gen-browser.js +1 -1
  69. package/dist/tools/trace-dot-zip/index.d.ts.map +1 -1
  70. package/dist/tools/trace-dot-zip/index.js +19 -9
  71. package/dist/utils/model.d.ts.map +1 -1
  72. package/dist/utils/model.js +2 -6
  73. package/package.json +2 -11
  74. package/tsconfig.tsbuildinfo +1 -1
  75. package/dist/agent/code-review/parser.d.ts.map +0 -1
  76. package/dist/agent/master/icon-descriptor/index.d.ts +0 -22
  77. package/dist/agent/master/icon-descriptor/index.d.ts.map +0 -1
  78. package/dist/agent/master/icon-descriptor/index.js +0 -249
  79. package/dist/agent/master/icon-descriptor/normalize-svg.d.ts +0 -2
  80. package/dist/agent/master/icon-descriptor/normalize-svg.d.ts.map +0 -1
  81. package/dist/agent/master/icon-descriptor/normalize-svg.js +0 -247
  82. package/dist/tools/issues-v1/create-issue.d.ts +0 -3
  83. package/dist/tools/issues-v1/create-issue.d.ts.map +0 -1
  84. package/dist/tools/issues-v1/create-issue.js +0 -72
  85. package/dist/tools/issues-v1/update-issue.d.ts +0 -3
  86. package/dist/tools/issues-v1/update-issue.d.ts.map +0 -1
  87. package/dist/tools/issues-v1/update-issue.js +0 -74
  88. package/dist/trace-utils/cli.d.ts +0 -3
  89. package/dist/trace-utils/cli.d.ts.map +0 -1
  90. package/dist/trace-utils/cli.js +0 -302
  91. package/dist/trace-utils/console.d.ts +0 -11
  92. package/dist/trace-utils/console.d.ts.map +0 -1
  93. package/dist/trace-utils/console.js +0 -74
  94. package/dist/trace-utils/dom-snapshot.d.ts +0 -19
  95. package/dist/trace-utils/dom-snapshot.d.ts.map +0 -1
  96. package/dist/trace-utils/dom-snapshot.js +0 -328
  97. package/dist/trace-utils/index.d.ts +0 -12
  98. package/dist/trace-utils/index.d.ts.map +0 -1
  99. package/dist/trace-utils/index.js +0 -28
  100. package/dist/trace-utils/network.d.ts +0 -16
  101. package/dist/trace-utils/network.d.ts.map +0 -1
  102. package/dist/trace-utils/network.js +0 -178
  103. package/dist/trace-utils/normalize-trace-url.d.ts +0 -2
  104. package/dist/trace-utils/normalize-trace-url.d.ts.map +0 -1
  105. package/dist/trace-utils/normalize-trace-url.js +0 -15
  106. package/dist/trace-utils/screenshots.d.ts +0 -24
  107. package/dist/trace-utils/screenshots.d.ts.map +0 -1
  108. package/dist/trace-utils/screenshots.js +0 -197
  109. package/dist/trace-utils/steps.d.ts +0 -10
  110. package/dist/trace-utils/steps.d.ts.map +0 -1
  111. package/dist/trace-utils/steps.js +0 -126
  112. package/dist/trace-utils/types.d.ts +0 -51
  113. package/dist/trace-utils/types.d.ts.map +0 -1
  114. package/dist/trace-utils/types.js +0 -2
  115. package/dist/utils/playwright-report-parser.d.ts +0 -2
  116. package/dist/utils/playwright-report-parser.d.ts.map +0 -1
  117. package/dist/utils/playwright-report-parser.js +0 -10
@@ -1,136 +1,62 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.downscaleImageIfNeeded = downscaleImageIfNeeded;
3
+ exports.fetchAndDownscaleImage = fetchAndDownscaleImage;
4
4
  const MAX_IMAGE_DIMENSION = 1440;
5
- function detectImageFormat(buffer) {
6
- const arr = new Uint8Array(buffer.slice(0, 12));
7
- // PNG: 89 50 4E 47
8
- if (arr[0] === 0x89 &&
9
- arr[1] === 0x50 &&
10
- arr[2] === 0x4e &&
11
- arr[3] === 0x47) {
12
- return "png";
13
- }
14
- // JPEG: FF D8 FF
15
- if (arr[0] === 0xff && arr[1] === 0xd8 && arr[2] === 0xff) {
16
- return "jpeg";
17
- }
18
- // WebP: RIFF ... WEBP
19
- if (arr[0] === 0x52 &&
20
- arr[1] === 0x49 &&
21
- arr[2] === 0x46 &&
22
- arr[3] === 0x46 &&
23
- arr[8] === 0x57 &&
24
- arr[9] === 0x45 &&
25
- arr[10] === 0x42 &&
26
- arr[11] === 0x50) {
27
- return "webp";
28
- }
29
- // GIF: 47 49 46
30
- if (arr[0] === 0x47 && arr[1] === 0x49 && arr[2] === 0x46) {
31
- return "gif";
32
- }
33
- return null;
5
+ // Cloudflare zone used for image transformations via /cdn-cgi/image/
6
+ const CF_TRANSFORM_ZONE = "https://dashboard-uploads.empirical.run";
7
+ /**
8
+ * Build a Cloudflare Image Transform URL that downscales the source image
9
+ * so that its longest dimension is at most `MAX_IMAGE_DIMENSION`.
10
+ *
11
+ * @see https://developers.cloudflare.com/images/transform-images/transform-via-url/
12
+ */
13
+ function buildCfImageTransformUrl(sourceUrl) {
14
+ const options = `width=${MAX_IMAGE_DIMENSION},height=${MAX_IMAGE_DIMENSION},fit=scale-down`;
15
+ return `${CF_TRANSFORM_ZONE}/cdn-cgi/image/${options}/${sourceUrl}`;
34
16
  }
35
- async function downscaleWithJsquash(buffer, logger) {
36
- const format = detectImageFormat(buffer);
37
- if (!format) {
38
- logger.warn("Unable to detect image format for downscaling", {
39
- tool: "fetchFileTool",
40
- });
41
- return buffer;
42
- }
17
+ /**
18
+ * Fetch a remote image, using Cloudflare's image transform URL to downscale
19
+ * large images on the fly. Falls back to a direct fetch if the transform
20
+ * request fails (e.g. unsupported format, CF feature not enabled).
21
+ *
22
+ * Returns both the image buffer and the actual content type from the response,
23
+ * since CF transforms may convert the format (e.g. PNG → JPEG).
24
+ */
25
+ async function fetchAndDownscaleImage(sourceUrl, logger) {
26
+ const transformUrl = buildCfImageTransformUrl(sourceUrl);
43
27
  try {
44
- let imageData;
45
- if (format === "png") {
46
- const { decode } = await import("@jsquash/png");
47
- imageData = await decode(buffer);
48
- }
49
- else if (format === "jpeg") {
50
- const { decode } = await import("@jsquash/jpeg");
51
- imageData = await decode(buffer);
52
- }
53
- else if (format === "webp") {
54
- const { decode } = await import("@jsquash/webp");
55
- imageData = await decode(buffer);
56
- }
57
- else if (format === "gif") {
58
- logger.warn("GIF resizing not supported in edge environment", {
59
- tool: "fetchFileTool",
60
- });
61
- return buffer;
62
- }
63
- else {
64
- logger.warn("Unsupported format for edge resizing", {
65
- tool: "fetchFileTool",
66
- format,
67
- });
68
- return buffer;
69
- }
70
- const { width, height } = imageData;
71
- const maxDimension = Math.max(width, height);
72
- if (maxDimension <= MAX_IMAGE_DIMENSION) {
73
- logger.info("Image dimensions within limits, no downscaling needed", {
28
+ const response = await fetch(transformUrl);
29
+ if (response.ok) {
30
+ logger.info("Fetched image via Cloudflare transform", {
74
31
  tool: "fetchFileTool",
75
- width,
76
- height,
32
+ sourceUrl,
33
+ transformUrl,
77
34
  });
78
- return buffer;
79
- }
80
- const scale = MAX_IMAGE_DIMENSION / maxDimension;
81
- const newWidth = Math.round(width * scale);
82
- const newHeight = Math.round(height * scale);
83
- const resize = (await import("@jsquash/resize")).default;
84
- const resizedImageData = await resize(imageData, {
85
- width: newWidth,
86
- height: newHeight,
87
- });
88
- let encodedBuffer;
89
- if (format === "png") {
90
- const { encode } = await import("@jsquash/png");
91
- encodedBuffer = await encode(resizedImageData);
92
- }
93
- else if (format === "jpeg") {
94
- const { encode } = await import("@jsquash/jpeg");
95
- encodedBuffer = await encode(resizedImageData);
96
- }
97
- else if (format === "webp") {
98
- const { encode } = await import("@jsquash/webp");
99
- encodedBuffer = await encode(resizedImageData);
100
- }
101
- else {
102
- return buffer;
35
+ return {
36
+ buffer: await response.arrayBuffer(),
37
+ contentType: response.headers.get("content-type"),
38
+ };
103
39
  }
104
- logger.info("Image downscaled with jsquash", {
40
+ logger.warn("Cloudflare transform returned non-OK, falling back to direct fetch", {
105
41
  tool: "fetchFileTool",
106
- originalWidth: width,
107
- originalHeight: height,
108
- newWidth,
109
- newHeight,
110
- scale,
111
- format,
42
+ status: response.status,
43
+ sourceUrl,
112
44
  });
113
- return encodedBuffer;
114
45
  }
115
46
  catch (error) {
116
- logger.error("Error downscaling with jsquash", {
47
+ logger.warn("Cloudflare transform fetch failed, falling back to direct fetch", {
117
48
  tool: "fetchFileTool",
118
49
  error,
119
- format,
50
+ sourceUrl,
120
51
  });
121
- return buffer;
122
52
  }
123
- }
124
- async function downscaleImageIfNeeded(buffer, logger) {
125
- try {
126
- return await downscaleWithJsquash(buffer, logger);
127
- }
128
- catch (error) {
129
- logger.error("Error processing image for downscaling", {
130
- tool: "fetchFileTool",
131
- error,
132
- });
133
- // Return original buffer if processing fails
134
- return buffer;
53
+ // Fallback: fetch the original image directly (no resize)
54
+ const directResponse = await fetch(sourceUrl);
55
+ if (!directResponse.ok) {
56
+ throw new Error(`Failed to fetch image: ${directResponse.status}`);
135
57
  }
58
+ return {
59
+ buffer: await directResponse.arrayBuffer(),
60
+ contentType: directResponse.headers.get("content-type"),
61
+ };
136
62
  }
@@ -4,10 +4,10 @@ export { safeBashTool } from "./definitions/safe-bash";
4
4
  export { scrapeHtmlTool } from "./firecrawl-scrape";
5
5
  export { validateToolInput } from "./utils/validate-schema";
6
6
  type ToolOrToolDefinition = Tool | ToolDefinition;
7
- export declare const commonTools: ToolOrToolDefinition[];
8
7
  export declare const testGenerationTools: ToolOrToolDefinition[];
9
8
  export declare const allToolsDefinitions: ToolOrToolDefinition[];
10
9
  export declare function hasBuiltInTextEditor(model: SupportedChatModels): boolean;
10
+ export declare function hasBuiltInWebFetch(model: SupportedChatModels): boolean;
11
11
  export declare function textEditorToolsForModel(model: SupportedChatModels): ToolOrToolDefinition[];
12
12
  export declare function textViewToolsForModel(model: SupportedChatModels): ToolOrToolDefinition[];
13
13
  export declare function toolsNeedBrowser(toolCalls: PendingToolCall[]): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,IAAI,EACJ,cAAc,EACf,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,iDAAiD,CAAC;AAiCjF,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,KAAK,oBAAoB,GAAG,IAAI,GAAG,cAAc,CAAC;AAIlD,eAAO,MAAM,WAAW,EAAE,oBAAoB,EAS7C,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,oBAAoB,EAOrD,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,oBAAoB,EAerD,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,mBAAmB,WAE9D;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,mBAAmB,GACzB,oBAAoB,EAAE,CAExB;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,mBAAmB,GACzB,oBAAoB,EAAE,CAExB;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,eAAe,EAAE,WAM5D;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAQlE;AAED,wBAAsB,4BAA4B,CAAC,OAAO,EAAE,cAAc,iBAoBzE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,IAAI,EACJ,cAAc,EACf,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,iDAAiD,CAAC;AAkCjF,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,KAAK,oBAAoB,GAAG,IAAI,GAAG,cAAc,CAAC;AAelD,eAAO,MAAM,mBAAmB,EAAE,oBAAoB,EAOrD,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,oBAAoB,EAcrD,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,mBAAmB,WAE9D;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,mBAAmB,WAE5D;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,mBAAmB,GACzB,oBAAoB,EAAE,CAExB;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,mBAAmB,GACzB,oBAAoB,EAAE,CAExB;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,eAAe,EAAE,WAM5D;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,CAQlE;AAED,wBAAsB,4BAA4B,CAAC,OAAO,EAAE,cAAc,iBAoBzE"}
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.allToolsDefinitions = exports.testGenerationTools = exports.commonTools = exports.validateToolInput = exports.scrapeHtmlTool = exports.safeBashTool = void 0;
3
+ exports.allToolsDefinitions = exports.testGenerationTools = exports.validateToolInput = exports.scrapeHtmlTool = exports.safeBashTool = void 0;
4
4
  exports.hasBuiltInTextEditor = hasBuiltInTextEditor;
5
+ exports.hasBuiltInWebFetch = hasBuiltInWebFetch;
5
6
  exports.textEditorToolsForModel = textEditorToolsForModel;
6
7
  exports.textViewToolsForModel = textViewToolsForModel;
7
8
  exports.toolsNeedBrowser = toolsNeedBrowser;
@@ -15,6 +16,7 @@ const download_build_1 = require("./definitions/download-build");
15
16
  const grep_1 = require("./definitions/grep");
16
17
  const list_tests_and_projects_1 = require("./definitions/list-tests-and-projects");
17
18
  const merge_conflicts_1 = require("./definitions/merge-conflicts");
19
+ const publish_markdown_report_1 = require("./definitions/publish-markdown-report");
18
20
  const rename_file_1 = require("./definitions/rename-file");
19
21
  const run_test_1 = require("./definitions/run-test");
20
22
  const safe_bash_1 = require("./definitions/safe-bash");
@@ -39,7 +41,7 @@ var validate_schema_1 = require("./utils/validate-schema");
39
41
  Object.defineProperty(exports, "validateToolInput", { enumerable: true, get: function () { return validate_schema_1.validateToolInput; } });
40
42
  // TODO: Keep this list in sync with the ToolExecutor
41
43
  // Search for "Tool Executor Tools List"
42
- exports.commonTools = [
44
+ const commonTools = [
43
45
  run_test_1.runTestTool,
44
46
  grep_1.grepTool,
45
47
  list_environments_1.listEnvironmentsTool,
@@ -58,13 +60,11 @@ exports.testGenerationTools = [
58
60
  upgrade_packages_1.upgradePackagesTool,
59
61
  ];
60
62
  exports.allToolsDefinitions = [
61
- ...exports.commonTools,
63
+ ...commonTools,
62
64
  ...exports.testGenerationTools,
63
65
  analyse_video_1.analyseVideo,
64
66
  triage_summary_1.sendTriageSummaryTool,
65
67
  issues_v1_1.listIssuesTool,
66
- issues_v1_1.createIssueTool,
67
- issues_v1_1.updateIssueTool,
68
68
  diagnosis_fetcher_1.fetchDiagnosisReportTool,
69
69
  test_run_fetcher_1.fetchTestRunDetailsTool,
70
70
  fetch_session_diff_1.fetchSessionDiffTool,
@@ -72,10 +72,14 @@ exports.allToolsDefinitions = [
72
72
  list_tests_and_projects_1.listTestsForProjectTool,
73
73
  safe_bash_1.safeBashTool,
74
74
  firecrawl_scrape_1.scrapeHtmlTool,
75
+ publish_markdown_report_1.publishMarkdownReportDefinition,
75
76
  ];
76
77
  function hasBuiltInTextEditor(model) {
77
78
  return model.includes("claude");
78
79
  }
80
+ function hasBuiltInWebFetch(model) {
81
+ return model.includes("claude");
82
+ }
79
83
  function textEditorToolsForModel(model) {
80
84
  return !hasBuiltInTextEditor(model) ? Object.values(str_replace_editor_1.textEditorTools) : [];
81
85
  }
@@ -1,4 +1,2 @@
1
- export { createIssueTool } from "./create-issue";
2
1
  export { listIssuesTool } from "./list-issues";
3
- export { updateIssueTool } from "./update-issue";
4
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/issues-v1/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/issues-v1/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
@@ -1,9 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.updateIssueTool = exports.listIssuesTool = exports.createIssueTool = void 0;
4
- var create_issue_1 = require("./create-issue");
5
- Object.defineProperty(exports, "createIssueTool", { enumerable: true, get: function () { return create_issue_1.createIssueTool; } });
3
+ exports.listIssuesTool = void 0;
6
4
  var list_issues_1 = require("./list-issues");
7
5
  Object.defineProperty(exports, "listIssuesTool", { enumerable: true, get: function () { return list_issues_1.listIssuesTool; } });
8
- var update_issue_1 = require("./update-issue");
9
- Object.defineProperty(exports, "updateIssueTool", { enumerable: true, get: function () { return update_issue_1.updateIssueTool; } });
@@ -0,0 +1,3 @@
1
+ import type { Tool } from "@empiricalrun/shared-types/chat-agent";
2
+ export declare const publishMarkdownReportTool: Tool;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/publish-markdown-report/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAGV,IAAI,EAEL,MAAM,uCAAuC,CAAC;AAyG/C,eAAO,MAAM,yBAAyB,EAAE,IAsJvC,CAAC"}
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.publishMarkdownReportTool = void 0;
40
+ const fs = __importStar(require("fs"));
41
+ const mime_1 = __importDefault(require("mime"));
42
+ const path_1 = __importDefault(require("path"));
43
+ const publish_markdown_report_1 = require("../definitions/publish-markdown-report");
44
+ const FILE_URL_REGEX = /file:\/\/([^\s)>\]"']+)/g;
45
+ const R2_BUCKET = "test-report";
46
+ const R2_BASE_URL = "https://reports-r2.empirical.run";
47
+ function extractFileUrls(markdown) {
48
+ const matches = markdown.matchAll(FILE_URL_REGEX);
49
+ const urls = new Set();
50
+ for (const match of matches) {
51
+ urls.add(match[0]);
52
+ }
53
+ return Array.from(urls);
54
+ }
55
+ function fileUrlToPath(fileUrl) {
56
+ // Remove file:// prefix to get the absolute path
57
+ return fileUrl.replace(/^file:\/\//, "");
58
+ }
59
+ async function getPresignedUrls(apiClient, files, destinationDir, logger) {
60
+ const response = await apiClient.request("/api/upload", {
61
+ method: "POST",
62
+ body: {
63
+ files,
64
+ destination_dir: destinationDir,
65
+ bucket: R2_BUCKET,
66
+ },
67
+ });
68
+ if (response.error) {
69
+ logger.error("Failed to get presigned URLs", {
70
+ error: response.error.message,
71
+ });
72
+ throw new Error(`Failed to get presigned URLs: ${response.error.message}`);
73
+ }
74
+ if (!response.data) {
75
+ throw new Error("No presigned URL data returned");
76
+ }
77
+ return response.data.presigned_urls;
78
+ }
79
+ async function uploadFileToPresignedUrl(filePath, uploadUrl, contentType, logger) {
80
+ const fileBuffer = fs.readFileSync(filePath);
81
+ const response = await fetch(uploadUrl, {
82
+ method: "PUT",
83
+ headers: {
84
+ "Content-Type": contentType,
85
+ },
86
+ body: fileBuffer,
87
+ });
88
+ if (!response.ok) {
89
+ const errorText = await response.text();
90
+ logger.error("Failed to upload file to presigned URL", {
91
+ filePath,
92
+ status: response.status,
93
+ error: errorText,
94
+ });
95
+ throw new Error(`Failed to upload ${filePath}: ${response.status} ${errorText}`);
96
+ }
97
+ }
98
+ exports.publishMarkdownReportTool = {
99
+ ...publish_markdown_report_1.publishMarkdownReportDefinition,
100
+ execute: async ({ input, apiClient, chatSession, logger, }) => {
101
+ try {
102
+ if (!apiClient) {
103
+ return {
104
+ isError: true,
105
+ result: "Dashboard API client is not available.",
106
+ };
107
+ }
108
+ if (!chatSession?.id) {
109
+ return {
110
+ isError: true,
111
+ result: "Session ID is not available. Cannot publish report without a fast-triage session.",
112
+ };
113
+ }
114
+ let { markdown, slack_message } = input;
115
+ const fileUrls = extractFileUrls(markdown);
116
+ if (fileUrls.length > 0) {
117
+ logger.info(`Found ${fileUrls.length} file:// URL(s) in markdown, uploading...`);
118
+ // Collect files that exist on disk
119
+ const filesToUpload = [];
120
+ const seenFileNames = new Set();
121
+ for (const fileUrl of fileUrls) {
122
+ const filePath = fileUrlToPath(fileUrl);
123
+ if (!fs.existsSync(filePath)) {
124
+ logger.warn(`File not found, skipping: ${filePath}`);
125
+ continue;
126
+ }
127
+ let fileName = path_1.default.basename(filePath);
128
+ // Deduplicate file names to avoid collisions from different paths
129
+ if (seenFileNames.has(fileName)) {
130
+ const ext = path_1.default.extname(fileName);
131
+ const base = path_1.default.basename(fileName, ext);
132
+ const suffix = Math.random().toString(36).substring(2, 8);
133
+ fileName = `${base}-${suffix}${ext}`;
134
+ }
135
+ seenFileNames.add(fileName);
136
+ const contentType = mime_1.default.getType(filePath) || "application/octet-stream";
137
+ filesToUpload.push({ fileUrl, filePath, fileName, contentType });
138
+ }
139
+ if (filesToUpload.length > 0) {
140
+ const destinationDir = `fast-triage/${chatSession.id}/report`;
141
+ // Get presigned URLs from the dashboard
142
+ const presignedUrls = await getPresignedUrls(apiClient, filesToUpload.map((f) => ({
143
+ name: f.fileName,
144
+ type: f.contentType,
145
+ })), destinationDir, logger);
146
+ // Upload each file and build replacement map
147
+ const urlReplacements = new Map();
148
+ for (const file of filesToUpload) {
149
+ const presigned = presignedUrls.find((p) => p.file_name === file.fileName);
150
+ if (!presigned) {
151
+ logger.warn(`No presigned URL found for ${file.fileName}, skipping`);
152
+ continue;
153
+ }
154
+ await uploadFileToPresignedUrl(file.filePath, presigned.upload_url, file.contentType, logger);
155
+ const publicUrl = `${R2_BASE_URL}/${presigned.key}`;
156
+ urlReplacements.set(file.fileUrl, publicUrl);
157
+ }
158
+ // Replace all file:// URLs with public HTTP URLs
159
+ for (const [fileUrl, httpUrl] of urlReplacements) {
160
+ markdown = markdown.replaceAll(fileUrl, httpUrl);
161
+ if (slack_message) {
162
+ slack_message = slack_message.replaceAll(fileUrl, httpUrl);
163
+ }
164
+ }
165
+ logger.info(`Uploaded ${urlReplacements.size} file(s) and replaced URLs`);
166
+ }
167
+ }
168
+ // PATCH the markdown report to the fast-triage endpoint
169
+ const patchBody = {
170
+ markdown_report: markdown,
171
+ };
172
+ if (slack_message) {
173
+ patchBody.slack_message = slack_message;
174
+ }
175
+ await apiClient.request(`/api/fast-triage/${chatSession.id}`, {
176
+ method: "PATCH",
177
+ body: patchBody,
178
+ });
179
+ logger.info(`Published markdown report for fast-triage ${chatSession.id}`);
180
+ return {
181
+ isError: false,
182
+ result: `Report published successfully with ${fileUrls.length} file(s) processed.`,
183
+ };
184
+ }
185
+ catch (error) {
186
+ logger.error("Error publishing markdown report", {
187
+ tool: "publishMarkdownReport",
188
+ error,
189
+ });
190
+ return {
191
+ isError: true,
192
+ result: error instanceof Error ? error.message : String(error),
193
+ };
194
+ }
195
+ },
196
+ };
@@ -125,7 +125,7 @@ exports.generateTestWithBrowserAgent = {
125
125
  fs_1.default.writeFileSync(absoluteFilePath, fileBackup, "utf-8");
126
126
  const { isError, error, result: toolResult, usage } = agentResult;
127
127
  if (usage) {
128
- (0, telemetry_1.trackLLMResponse)({
128
+ await (0, telemetry_1.trackLLMResponse)({
129
129
  modelName: model_1.CUA_MODEL,
130
130
  projectRepoName: chatSession?.repoName || "unknown",
131
131
  chatSessionId: chatSession?.id,
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/trace-dot-zip/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAc,MAAM,uCAAuC,CAAC;AACzE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAEL,iBAAiB,EAClB,MAAM,8BAA8B,CAAC;AAEtC,eAAO,MAAM,eAAe,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CA4CnE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/trace-dot-zip/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAc,MAAM,uCAAuC,CAAC;AAMzE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAEL,iBAAiB,EAClB,MAAM,8BAA8B,CAAC;AAEtC,eAAO,MAAM,eAAe,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAqDnE,CAAC"}
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.traceDotZipTool = void 0;
4
- const trace_utils_1 = require("../../trace-utils");
4
+ const trace_utils_1 = require("@empiricalrun/trace-utils");
5
5
  const trace_dot_zip_1 = require("../definitions/trace-dot-zip");
6
6
  exports.traceDotZipTool = {
7
7
  ...trace_dot_zip_1.traceDotZip,
@@ -14,16 +14,26 @@ exports.traceDotZipTool = {
14
14
  result: "No trace.zip URL provided",
15
15
  };
16
16
  }
17
- const [networkResult, consoleResult] = await Promise.all([
18
- (0, trace_utils_1.searchNetwork)({ file: traceFileUrl, errors: true }),
19
- (0, trace_utils_1.getConsoleLogs)({ file: traceFileUrl, level: "error" }),
20
- ]);
21
- return {
22
- isError: false,
23
- result: JSON.stringify({
17
+ const pageIds = await (0, trace_utils_1.getUniquePageIds)(traceFileUrl);
18
+ const pagesToQuery = pageIds.length > 0 ? pageIds : [undefined];
19
+ const results = await Promise.all(pagesToQuery.map(async (pageId) => {
20
+ const [networkResult, consoleResult] = await Promise.all([
21
+ (0, trace_utils_1.searchNetwork)({ file: traceFileUrl, errors: true, page: pageId }),
22
+ (0, trace_utils_1.getConsoleLogs)({
23
+ file: traceFileUrl,
24
+ level: "error",
25
+ page: pageId,
26
+ }),
27
+ ]);
28
+ return {
29
+ pageId,
24
30
  failed_network_requests: networkResult.matches,
25
31
  console_error_logs: consoleResult.logs,
26
- }, null, 2),
32
+ };
33
+ }));
34
+ return {
35
+ isError: false,
36
+ result: JSON.stringify(results, null, 2),
27
37
  };
28
38
  }
29
39
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/utils/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAE5E,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAcrE,CAAC"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/utils/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAE5E,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAUrE,CAAC"}
@@ -2,13 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CLI_ARGS_TO_MODEL_MAP = void 0;
4
4
  exports.CLI_ARGS_TO_MODEL_MAP = {
5
- "claude-4": "claude-sonnet-4-20250514",
6
- "claude-4-5": "claude-sonnet-4-5-20250929",
7
- "claude-opus": "claude-opus-4-5-20251101",
8
- "claude-sonnet": "claude-sonnet-4-5-20250929",
5
+ "claude-opus": "claude-opus-4-6",
6
+ "claude-sonnet": "claude-sonnet-4-6",
9
7
  "claude-haiku": "claude-haiku-4-5-20251001",
10
- "gemini-2.5": "gemini-2.5-pro",
11
- "gemini-2.5-pro": "gemini-2.5-pro",
12
8
  "gemini-3": "gemini-3-pro-preview",
13
9
  "gemini-3-pro": "gemini-3-pro-preview",
14
10
  "gpt-5": "gpt-5-2025-08-07",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@empiricalrun/test-gen",
3
- "version": "0.79.3",
3
+ "version": "0.79.4",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"
@@ -50,10 +50,6 @@
50
50
  "types": "./dist/file-info/index.d.ts",
51
51
  "default": "./dist/file-info/index.js"
52
52
  },
53
- "./trace-utils": {
54
- "types": "./dist/trace-utils/index.d.ts",
55
- "default": "./dist/trace-utils/index.js"
56
- },
57
53
  "./telemetry": {
58
54
  "types": "./dist/telemetry/index.d.ts",
59
55
  "default": "./dist/telemetry/index.js"
@@ -68,10 +64,6 @@
68
64
  "@babel/parser": "^7.26.3",
69
65
  "@commander-js/extra-typings": "^14.0.0",
70
66
  "@epic-web/totp": "^4.0.1",
71
- "@jsquash/jpeg": "^1.6.0",
72
- "@jsquash/png": "^3.1.1",
73
- "@jsquash/resize": "^2.1.0",
74
- "@jsquash/webp": "^1.5.0",
75
67
  "@types/sanitize-html": "^2.11.0",
76
68
  "async-retry": "^1.3.3",
77
69
  "commander": "^14.0.2",
@@ -83,7 +75,6 @@
83
75
  "ignore": "^5.3.1",
84
76
  "inquirer": "^12.4.2",
85
77
  "istextorbinary": "^9.5.0",
86
- "jsdom": "^26.0.0",
87
78
  "lodash.isequal": "^4.5.0",
88
79
  "mime": "3.0.0",
89
80
  "minimatch": "^10.0.1",
@@ -103,6 +94,7 @@
103
94
  "@empiricalrun/ast-parser": "^0.0.10",
104
95
  "@empiricalrun/llm": "^0.25.2",
105
96
  "@empiricalrun/r2-uploader": "^0.9.1",
97
+ "@empiricalrun/trace-utils": "^0.1.0",
106
98
  "@empiricalrun/reporter": "^0.27.0",
107
99
  "@empiricalrun/test-run": "^0.14.2",
108
100
  "videostil": "0.3.4"
@@ -114,7 +106,6 @@
114
106
  "@types/detect-port": "^1.3.5",
115
107
  "@types/express": "^4.17.21",
116
108
  "@types/js-levenshtein": "^1.1.3",
117
- "@types/jsdom": "^21.1.7",
118
109
  "@types/lodash.isequal": "^4.5.8",
119
110
  "@types/mime": "3.0.0",
120
111
  "@types/node": "^24.3.0",