@empiricalrun/test-gen 0.47.3 → 0.48.0

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 (65) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/agent/browsing/run.d.ts +4 -10
  3. package/dist/agent/browsing/run.d.ts.map +1 -1
  4. package/dist/agent/browsing/run.js +10 -17
  5. package/dist/agent/browsing/utils.d.ts +16 -13
  6. package/dist/agent/browsing/utils.d.ts.map +1 -1
  7. package/dist/agent/browsing/utils.js +33 -41
  8. package/dist/agent/chat.d.ts +7 -0
  9. package/dist/agent/chat.d.ts.map +1 -0
  10. package/dist/agent/chat.js +111 -0
  11. package/dist/agent/codegen/create-test-block.d.ts +2 -3
  12. package/dist/agent/codegen/create-test-block.d.ts.map +1 -1
  13. package/dist/agent/codegen/create-test-block.js +4 -9
  14. package/dist/agent/codegen/fix-ts-errors.d.ts +2 -3
  15. package/dist/agent/codegen/fix-ts-errors.d.ts.map +1 -1
  16. package/dist/agent/codegen/fix-ts-errors.js +4 -5
  17. package/dist/agent/codegen/run.d.ts +6 -4
  18. package/dist/agent/codegen/run.d.ts.map +1 -1
  19. package/dist/agent/codegen/run.js +8 -6
  20. package/dist/agent/codegen/update-flow.d.ts +7 -5
  21. package/dist/agent/codegen/update-flow.d.ts.map +1 -1
  22. package/dist/agent/codegen/update-flow.js +9 -49
  23. package/dist/agent/codegen/utils.d.ts +2 -4
  24. package/dist/agent/codegen/utils.d.ts.map +1 -1
  25. package/dist/agent/codegen/utils.js +1 -2
  26. package/dist/agent/diagnosis-agent/index.d.ts +2 -9
  27. package/dist/agent/diagnosis-agent/index.d.ts.map +1 -1
  28. package/dist/agent/diagnosis-agent/index.js +1 -8
  29. package/dist/agent/enrich-prompt/index.d.ts.map +1 -1
  30. package/dist/agent/enrich-prompt/index.js +0 -1
  31. package/dist/agent/infer-agent/index.d.ts.map +1 -1
  32. package/dist/agent/infer-agent/index.js +0 -9
  33. package/dist/agent/master/browser-tests/skills.spec.js +3 -0
  34. package/dist/agent/master/run.d.ts +1 -0
  35. package/dist/agent/master/run.d.ts.map +1 -1
  36. package/dist/agent/master/run.js +4 -2
  37. package/dist/bin/index.js +53 -35
  38. package/dist/bin/utils/index.d.ts +1 -0
  39. package/dist/bin/utils/index.d.ts.map +1 -1
  40. package/dist/bin/utils/index.js +9 -3
  41. package/dist/file/server.d.ts +2 -0
  42. package/dist/file/server.d.ts.map +1 -1
  43. package/dist/file/server.js +18 -1
  44. package/dist/tools/browser-agent.d.ts +3 -0
  45. package/dist/tools/browser-agent.d.ts.map +1 -0
  46. package/dist/tools/browser-agent.js +120 -0
  47. package/dist/tools/codegen-agent.d.ts +3 -0
  48. package/dist/tools/codegen-agent.d.ts.map +1 -0
  49. package/dist/tools/codegen-agent.js +56 -0
  50. package/dist/tools/diagnosis-fetcher.d.ts +3 -0
  51. package/dist/tools/diagnosis-fetcher.d.ts.map +1 -0
  52. package/dist/tools/diagnosis-fetcher.js +88 -0
  53. package/dist/tools/test-run.d.ts +3 -0
  54. package/dist/tools/test-run.d.ts.map +1 -0
  55. package/dist/tools/test-run.js +49 -0
  56. package/dist/tools/types.d.ts +11 -0
  57. package/dist/tools/types.d.ts.map +1 -0
  58. package/dist/tools/types.js +2 -0
  59. package/dist/utils/git.d.ts +2 -0
  60. package/dist/utils/git.d.ts.map +1 -0
  61. package/dist/utils/git.js +11 -0
  62. package/dist/utils/repo-tree.d.ts +2 -0
  63. package/dist/utils/repo-tree.d.ts.map +1 -0
  64. package/dist/utils/repo-tree.js +75 -0
  65. package/package.json +4 -3
@@ -6,12 +6,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.validateAndCompleteCliOptions = void 0;
7
7
  const inquirer_1 = __importDefault(require("inquirer"));
8
8
  async function validateAndCompleteCliOptions(options) {
9
+ // For existing flow between dashboard <> test-gen (via ci-worker)
9
10
  const hasToken = !!options.token;
10
11
  if (hasToken) {
11
12
  return options;
12
13
  }
14
+ let requiredFields = ["name", "file", "prompt"];
15
+ // For new chat flow in local CLI usage, only prompt is required
16
+ if (options.useChat) {
17
+ requiredFields = ["prompt"];
18
+ }
13
19
  const questions = [];
14
- if (!options.name) {
20
+ if (!options.name && requiredFields.includes("name")) {
15
21
  questions.push({
16
22
  type: "input",
17
23
  name: "name",
@@ -19,7 +25,7 @@ async function validateAndCompleteCliOptions(options) {
19
25
  validate: (input) => input.trim().length > 0 || "Test name is required",
20
26
  });
21
27
  }
22
- if (!options.file) {
28
+ if (!options.file && requiredFields.includes("file")) {
23
29
  questions.push({
24
30
  type: "input",
25
31
  name: "file",
@@ -27,7 +33,7 @@ async function validateAndCompleteCliOptions(options) {
27
33
  validate: (input) => input.trim().length > 0 || "Test file path is required",
28
34
  });
29
35
  }
30
- if (!options.prompt) {
36
+ if (!options.prompt && requiredFields.includes("prompt")) {
31
37
  questions.push({
32
38
  type: "editor",
33
39
  name: "prompt",
@@ -2,12 +2,14 @@ export declare class FileService {
2
2
  private port;
3
3
  private filePath;
4
4
  private repoDir;
5
+ private server;
5
6
  constructor({ port, repoDir }: {
6
7
  port: number;
7
8
  repoDir: string;
8
9
  });
9
10
  setFilePath(filePath: string): void;
10
11
  startFileService(): Promise<number>;
12
+ stop(): Promise<void>;
11
13
  }
12
14
  export declare function startFileService(): Promise<void>;
13
15
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/file/server.ts"],"names":[],"mappings":"AAWA,qBAAa,WAAW;IACtB,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,OAAO,CAAc;gBAEjB,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAKhE,WAAW,CAAC,QAAQ,EAAE,MAAM;IAItB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;CAyC1C;AAED,wBAAsB,gBAAgB,kBAAK"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/file/server.ts"],"names":[],"mappings":"AAWA,qBAAa,WAAW;IACtB,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,MAAM,CAA4C;gBAE9C,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAKhE,WAAW,CAAC,QAAQ,EAAE,MAAM;IAItB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;IA0CnC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAgB5B;AAED,wBAAsB,gBAAgB,kBAAK"}
@@ -13,6 +13,7 @@ class FileService {
13
13
  port = 0;
14
14
  filePath = "";
15
15
  repoDir = "";
16
+ server;
16
17
  constructor({ port, repoDir }) {
17
18
  this.port = port;
18
19
  this.repoDir = repoDir;
@@ -43,7 +44,23 @@ class FileService {
43
44
  return res.send({ success: false });
44
45
  });
45
46
  return new Promise((resolve) => {
46
- app.listen(this.port, () => resolve(this.port));
47
+ this.server = app.listen(this.port, () => resolve(this.port));
48
+ });
49
+ }
50
+ async stop() {
51
+ return new Promise((resolve, reject) => {
52
+ if (!this.server) {
53
+ resolve();
54
+ return;
55
+ }
56
+ this.server.close((err) => {
57
+ if (err) {
58
+ reject(err);
59
+ return;
60
+ }
61
+ this.server = undefined;
62
+ resolve();
63
+ });
47
64
  });
48
65
  }
49
66
  }
@@ -0,0 +1,3 @@
1
+ import type { Tool } from "./types";
2
+ export declare const browserAgentTool: Tool;
3
+ //# sourceMappingURL=browser-agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-agent.d.ts","sourceRoot":"","sources":["../../src/tools/browser-agent.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAUpC,eAAO,MAAM,gBAAgB,EAAE,IAkH9B,CAAC"}
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.browserAgentTool = void 0;
4
+ const run_1 = require("../agent/browsing/run");
5
+ const utils_1 = require("../agent/browsing/utils");
6
+ const scenarios_1 = require("../bin/utils/scenarios");
7
+ const git_1 = require("../utils/git");
8
+ exports.browserAgentTool = {
9
+ schema: {
10
+ type: "function",
11
+ function: {
12
+ name: "generateTestWithBrowserAgent",
13
+ description: `
14
+ Create or modify a test case with browser agent. The browser agent can take user interactions in a web browser
15
+ and generate Playwright code for that actions. This is a useful tool when the modifications require knowing the
16
+ locator/selector for an element on the page.
17
+
18
+ IMPORTANT: Before you invoke this tool, you need to ensure that the test code is correctly prepared for this
19
+ agent. Preparation involves adding a TODO comment that describes the change that needs to be made. A good
20
+ comment calls out the element and browser interactions sto take on them. The TODO comment also has (agent) next to it, to
21
+ clearly label that the change is for the agent to make.
22
+
23
+ For example: This is a good TODO comment
24
+
25
+ \`\`\`
26
+ test("Example test code", async ({ page }) => {
27
+ await page.goto("https://example.com");
28
+ // TODO(agent): Click on the login button
29
+ });
30
+ \`\`\`
31
+
32
+ The browser agent will execute the steps before the TODO comment and replace the TODO comment with the Playwright
33
+ code that performs the actions described in the comment. For instance, on the running the tool, the agent will
34
+ output the following final code:
35
+
36
+ \`\`\`
37
+ test("Example test code", async ({ page }) => {
38
+ await page.goto("https://example.com");
39
+ await page.getByRole("button", { name: "Login" }).click();
40
+ });
41
+ \`\`\`
42
+ `,
43
+ parameters: {
44
+ type: "object",
45
+ properties: {
46
+ testName: {
47
+ type: "string",
48
+ description: "The name of the test to create or modify",
49
+ },
50
+ testSuites: {
51
+ type: "array",
52
+ description: "The suites (describe blocks) where the test is located",
53
+ items: {
54
+ type: "string",
55
+ },
56
+ },
57
+ fileName: {
58
+ type: "string",
59
+ description: "The name of the file where the test is located. File name must end with .spec.ts",
60
+ },
61
+ project: {
62
+ type: "string",
63
+ description: "The Playwright project to run tests against (e.g. 'chromium' or 'firefox')",
64
+ },
65
+ changeToMake: {
66
+ type: "string",
67
+ description: "The change to make to the test",
68
+ },
69
+ },
70
+ required: [
71
+ "testName",
72
+ "testSuites",
73
+ "fileName",
74
+ "changeToMake",
75
+ "project",
76
+ ],
77
+ },
78
+ },
79
+ },
80
+ execute: async (input) => {
81
+ const { testName, testSuites, fileName, changeToMake, project } = input;
82
+ await (0, utils_1.replaceTodoWithCreateTest)({
83
+ testCaseName: testName,
84
+ testCaseSuites: testSuites,
85
+ testFilePath: fileName,
86
+ });
87
+ const { isError, error } = await (0, run_1.generateTestsUsingMasterAgent)({
88
+ testFilePath: fileName,
89
+ filePathToUpdate: fileName,
90
+ pwProjectsFilter: [project],
91
+ testGenToken: (0, scenarios_1.buildTokenFromOptions)({
92
+ name: testName,
93
+ file: fileName,
94
+ prompt: changeToMake,
95
+ }),
96
+ repoDir: process.cwd(),
97
+ });
98
+ if (!isError) {
99
+ const gitPatch = (0, git_1.getGitDiff)(fileName);
100
+ return {
101
+ isError,
102
+ result: `Test was generated successfully. Here is the git patch:
103
+ \`\`\`
104
+ ${gitPatch}
105
+ \`\`\`
106
+ `,
107
+ };
108
+ }
109
+ else {
110
+ return {
111
+ isError,
112
+ result: `Test was not generated successfully. Here is the error:
113
+ \`\`\`
114
+ ${error}
115
+ \`\`\`
116
+ `,
117
+ };
118
+ }
119
+ },
120
+ };
@@ -0,0 +1,3 @@
1
+ import type { Tool } from "./types";
2
+ export declare const codegenTool: Tool;
3
+ //# sourceMappingURL=codegen-agent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codegen-agent.d.ts","sourceRoot":"","sources":["../../src/tools/codegen-agent.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AASpC,eAAO,MAAM,WAAW,EAAE,IAsDzB,CAAC"}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.codegenTool = void 0;
4
+ const run_1 = require("../agent/codegen/run");
5
+ exports.codegenTool = {
6
+ schema: {
7
+ type: "function",
8
+ function: {
9
+ name: "generateTestWithCodegen",
10
+ description: "Create or modify a test case with code generation. This is useful when modifications can be done with TypeScript only, and don't require any browser interactions or element selectors.",
11
+ parameters: {
12
+ type: "object",
13
+ properties: {
14
+ testName: {
15
+ type: "string",
16
+ description: "The name of the test to create or modify",
17
+ },
18
+ testSuites: {
19
+ type: "array",
20
+ description: "The suites (describe blocks) where the test is located",
21
+ items: {
22
+ type: "string",
23
+ },
24
+ },
25
+ fileName: {
26
+ type: "string",
27
+ description: "The name of the file where the test is located. File name must end with .spec.ts",
28
+ },
29
+ changeToMake: {
30
+ type: "string",
31
+ description: "The change to make to the test",
32
+ },
33
+ },
34
+ required: ["testName", "testSuites", "fileName", "changeToMake"],
35
+ },
36
+ },
37
+ },
38
+ execute: async (input) => {
39
+ const { testName, testSuites, fileName, changeToMake } = input;
40
+ const testCase = {
41
+ id: 0,
42
+ name: testName,
43
+ filePath: fileName,
44
+ suites: testSuites,
45
+ steps: [changeToMake],
46
+ };
47
+ const result = await (0, run_1.generateTestWithCodegen)({
48
+ testCase,
49
+ file: fileName,
50
+ });
51
+ return {
52
+ result: JSON.stringify(result),
53
+ isError: false,
54
+ };
55
+ },
56
+ };
@@ -0,0 +1,3 @@
1
+ import type { Tool } from "./types";
2
+ export declare const diagnosisTool: Tool;
3
+ //# sourceMappingURL=diagnosis-fetcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnosis-fetcher.d.ts","sourceRoot":"","sources":["../../src/tools/diagnosis-fetcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAMpC,eAAO,MAAM,aAAa,EAAE,IA4F3B,CAAC"}
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.diagnosisTool = void 0;
7
+ const promises_1 = __importDefault(require("fs/promises"));
8
+ const path_1 = __importDefault(require("path"));
9
+ exports.diagnosisTool = {
10
+ schema: {
11
+ type: "function",
12
+ function: {
13
+ name: "fetchDiagnosisDetails",
14
+ description: "Fetch details about a test case diagnosis using its URL or slug",
15
+ parameters: {
16
+ type: "object",
17
+ properties: {
18
+ diagnosisUrl: {
19
+ type: "string",
20
+ description: "The full URL of the diagnosis (e.g. https://dash.empirical.run/shopflo-tests/diagnosis/split-cod-place-the-order--byynrPjCml57)",
21
+ },
22
+ },
23
+ required: ["diagnosisUrl"],
24
+ },
25
+ },
26
+ },
27
+ execute: async (input) => {
28
+ const { diagnosisUrl } = input;
29
+ // Extract the slug from the URL - it's the part after the last '--'
30
+ const slug = diagnosisUrl.split("--").pop();
31
+ if (!slug) {
32
+ throw new Error("Invalid diagnosis URL - could not extract slug");
33
+ }
34
+ // Make the API call to fetch diagnosis details
35
+ const response = await fetch(`https://dash.empirical.run/api/diagnosis/${slug}/detailed`, {
36
+ method: "GET",
37
+ headers: {
38
+ Authorization: "weQPMWKT", // Using the auth token from test-endpoint.mdc
39
+ },
40
+ });
41
+ if (!response.ok) {
42
+ return {
43
+ result: `Failed to fetch diagnosis details: ${response.statusText}`,
44
+ isError: true,
45
+ };
46
+ }
47
+ const data = await response.json();
48
+ const { test_case, diagnosis } = data.data;
49
+ const project = diagnosis[0]?.test_project || "unknown";
50
+ const sourceContext = await promises_1.default.readFile(path_1.default.join("tests", test_case.file_path), "utf-8");
51
+ // Format the response as markdown
52
+ const markdownResponse = `
53
+ # Test Case Diagnosis
54
+
55
+ ## Test Case Information
56
+ - **Test Case Name**: ${test_case.name}
57
+ - **Test Suite**: ${test_case.suites}
58
+ - **File Name**: tests/${test_case.file_path}
59
+ - **Project**: ${project}
60
+
61
+ ## Source Context
62
+ ${sourceContext}
63
+
64
+ ## What Happened in the Test Run
65
+
66
+ ### Failure Details
67
+ - **Failing Line**: ${diagnosis[0]?.failing_line || "No failing line available"}
68
+
69
+ #### Error Stack
70
+ \`\`\`
71
+ ${diagnosis[0]?.failed_run_metadata?.stack?.replace("/runner/_work/shopflo-tests/shopflo-tests/source-repo/", "") || "No error stack available"}
72
+ \`\`\`
73
+
74
+ #### Error Summary
75
+ ${diagnosis[0]?.error_stack_summary?.content || "No error summary available"}
76
+
77
+ #### Visual Analysis
78
+ ${diagnosis[0]?.visual_diff_summary?.summary || "No visual analysis available"}
79
+
80
+ #### Merged Summary
81
+ ${diagnosis[0]?.merged_summary?.content || "No merged summary available"}
82
+ `;
83
+ return {
84
+ result: markdownResponse,
85
+ isError: false,
86
+ };
87
+ },
88
+ };
@@ -0,0 +1,3 @@
1
+ import type { Tool } from "./types";
2
+ export declare const runTestTool: Tool;
3
+ //# sourceMappingURL=test-run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-run.d.ts","sourceRoot":"","sources":["../../src/tools/test-run.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AASpC,eAAO,MAAM,WAAW,EAAE,IA8CzB,CAAC"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runTestTool = void 0;
4
+ const test_run_1 = require("@empiricalrun/test-run");
5
+ exports.runTestTool = {
6
+ schema: {
7
+ type: "function",
8
+ function: {
9
+ name: "runTest",
10
+ description: "Run a test",
11
+ parameters: {
12
+ type: "object",
13
+ properties: {
14
+ testName: {
15
+ type: "string",
16
+ description: "The name of the test to run",
17
+ },
18
+ suites: {
19
+ type: "array",
20
+ description: "The suites (describe blocks) where the test is located.",
21
+ items: { type: "string" },
22
+ },
23
+ fileName: {
24
+ type: "string",
25
+ description: "The name of the file where the test is located. File name must end with .spec.ts",
26
+ },
27
+ project: {
28
+ type: "string",
29
+ description: "The project to run the test on",
30
+ },
31
+ },
32
+ required: ["testName", "suites", "fileName", "project"],
33
+ },
34
+ },
35
+ },
36
+ execute: async (input) => {
37
+ const { testName, suites, fileName, project } = input;
38
+ const result = await (0, test_run_1.runSingleTest)({
39
+ testName,
40
+ suites,
41
+ fileName,
42
+ projects: [project],
43
+ });
44
+ return {
45
+ result: JSON.stringify(result),
46
+ isError: false,
47
+ };
48
+ },
49
+ };
@@ -0,0 +1,11 @@
1
+ import type { OpenAI } from "openai";
2
+ export type ToolSchema = OpenAI.Chat.Completions.ChatCompletionTool;
3
+ export type ToolResult = {
4
+ result: string;
5
+ isError: boolean;
6
+ };
7
+ export type Tool = {
8
+ schema: ToolSchema;
9
+ execute: (input: any) => Promise<ToolResult>;
10
+ };
11
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAErC,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC;AAEpE,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,IAAI,GAAG;IAIjB,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;CAC9C,CAAC"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ export declare function getGitDiff(filepath: string): string;
2
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAEA,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKnD"}
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getGitDiff = void 0;
4
+ const child_process_1 = require("child_process");
5
+ function getGitDiff(filepath) {
6
+ const diff = (0, child_process_1.execSync)(`git diff ${filepath}`, {
7
+ encoding: "utf-8",
8
+ });
9
+ return diff;
10
+ }
11
+ exports.getGitDiff = getGitDiff;
@@ -0,0 +1,2 @@
1
+ export declare function generateAsciiTree(dirPath: string, options?: {}): string;
2
+ //# sourceMappingURL=repo-tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-tree.d.ts","sourceRoot":"","sources":["../../src/utils/repo-tree.ts"],"names":[],"mappings":"AAYA,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,UAsE9D"}
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.generateAsciiTree = void 0;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const DEFAULT_EXCLUDE = [
10
+ "node_modules",
11
+ "dist",
12
+ "build",
13
+ /\.git/,
14
+ ".DS_Store",
15
+ "playwright-report",
16
+ ];
17
+ function generateAsciiTree(dirPath, options = {}) {
18
+ const defaultOptions = {
19
+ showHidden: false,
20
+ exclude: DEFAULT_EXCLUDE,
21
+ maxDepth: 10,
22
+ };
23
+ const opts = { ...defaultOptions, ...options };
24
+ // Make sure the path exists and is a directory
25
+ if (!fs_1.default.existsSync(dirPath) || !fs_1.default.statSync(dirPath).isDirectory()) {
26
+ throw new Error(`"${dirPath}" is not a valid directory path`);
27
+ }
28
+ // Start with the root directory name
29
+ const rootName = path_1.default.basename(dirPath);
30
+ let result = rootName + "\n";
31
+ function processDirectory(currentPath, prefix = "", depth = 1) {
32
+ if (depth > opts.maxDepth)
33
+ return;
34
+ const items = fs_1.default.readdirSync(currentPath);
35
+ // Sort items: directories first, then files
36
+ const sortedItems = items.sort((a, b) => {
37
+ const aIsDir = fs_1.default.statSync(path_1.default.join(currentPath, a)).isDirectory();
38
+ const bIsDir = fs_1.default.statSync(path_1.default.join(currentPath, b)).isDirectory();
39
+ if (aIsDir && !bIsDir)
40
+ return -1;
41
+ if (!aIsDir && bIsDir)
42
+ return 1;
43
+ return a.localeCompare(b);
44
+ });
45
+ // Process each item
46
+ sortedItems.forEach((item, index) => {
47
+ // Skip hidden files if not showing hidden
48
+ if (!opts.showHidden && item.startsWith("."))
49
+ return;
50
+ // Skip excluded patterns
51
+ if (opts.exclude.some((pattern) => typeof pattern === "string"
52
+ ? item === pattern
53
+ : pattern instanceof RegExp
54
+ ? pattern.test(item)
55
+ : false))
56
+ return;
57
+ const itemPath = path_1.default.join(currentPath, item);
58
+ const isDirectory = fs_1.default.statSync(itemPath).isDirectory();
59
+ const isLast = index === sortedItems.length - 1;
60
+ // Current item symbols
61
+ const symbol = isLast ? "└── " : "├── ";
62
+ const nextPrefix = isLast ? " " : "│ ";
63
+ // Add the current item to the result
64
+ result += `${prefix}${symbol}${item}${isDirectory ? "/" : ""}\n`;
65
+ // Process subdirectories
66
+ if (isDirectory) {
67
+ processDirectory(itemPath, prefix + nextPrefix, depth + 1);
68
+ }
69
+ });
70
+ }
71
+ // Start the recursive processing
72
+ processDirectory(dirPath);
73
+ return result;
74
+ }
75
+ exports.generateAsciiTree = generateAsciiTree;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@empiricalrun/test-gen",
3
- "version": "0.47.3",
3
+ "version": "0.48.0",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"
@@ -73,9 +73,10 @@
73
73
  "ts-morph": "^23.0.0",
74
74
  "tsx": "^4.16.2",
75
75
  "typescript": "^5.3.3",
76
- "@empiricalrun/llm": "^0.9.36",
76
+ "@empiricalrun/llm": "^0.10.0",
77
77
  "@empiricalrun/r2-uploader": "^0.3.8",
78
- "@empiricalrun/reporter": "^0.23.1"
78
+ "@empiricalrun/reporter": "^0.23.1",
79
+ "@empiricalrun/test-run": "^0.7.2"
79
80
  },
80
81
  "devDependencies": {
81
82
  "@playwright/test": "1.47.1",