@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.
- package/CHANGELOG.md +41 -0
- package/dist/agent/browsing/run.d.ts +4 -10
- package/dist/agent/browsing/run.d.ts.map +1 -1
- package/dist/agent/browsing/run.js +10 -17
- package/dist/agent/browsing/utils.d.ts +16 -13
- package/dist/agent/browsing/utils.d.ts.map +1 -1
- package/dist/agent/browsing/utils.js +33 -41
- package/dist/agent/chat.d.ts +7 -0
- package/dist/agent/chat.d.ts.map +1 -0
- package/dist/agent/chat.js +111 -0
- package/dist/agent/codegen/create-test-block.d.ts +2 -3
- package/dist/agent/codegen/create-test-block.d.ts.map +1 -1
- package/dist/agent/codegen/create-test-block.js +4 -9
- package/dist/agent/codegen/fix-ts-errors.d.ts +2 -3
- package/dist/agent/codegen/fix-ts-errors.d.ts.map +1 -1
- package/dist/agent/codegen/fix-ts-errors.js +4 -5
- package/dist/agent/codegen/run.d.ts +6 -4
- package/dist/agent/codegen/run.d.ts.map +1 -1
- package/dist/agent/codegen/run.js +8 -6
- package/dist/agent/codegen/update-flow.d.ts +7 -5
- package/dist/agent/codegen/update-flow.d.ts.map +1 -1
- package/dist/agent/codegen/update-flow.js +9 -49
- package/dist/agent/codegen/utils.d.ts +2 -4
- package/dist/agent/codegen/utils.d.ts.map +1 -1
- package/dist/agent/codegen/utils.js +1 -2
- package/dist/agent/diagnosis-agent/index.d.ts +2 -9
- package/dist/agent/diagnosis-agent/index.d.ts.map +1 -1
- package/dist/agent/diagnosis-agent/index.js +1 -8
- package/dist/agent/enrich-prompt/index.d.ts.map +1 -1
- package/dist/agent/enrich-prompt/index.js +0 -1
- package/dist/agent/infer-agent/index.d.ts.map +1 -1
- package/dist/agent/infer-agent/index.js +0 -9
- package/dist/agent/master/browser-tests/skills.spec.js +3 -0
- package/dist/agent/master/run.d.ts +1 -0
- package/dist/agent/master/run.d.ts.map +1 -1
- package/dist/agent/master/run.js +4 -2
- package/dist/bin/index.js +53 -35
- package/dist/bin/utils/index.d.ts +1 -0
- package/dist/bin/utils/index.d.ts.map +1 -1
- package/dist/bin/utils/index.js +9 -3
- package/dist/file/server.d.ts +2 -0
- package/dist/file/server.d.ts.map +1 -1
- package/dist/file/server.js +18 -1
- package/dist/tools/browser-agent.d.ts +3 -0
- package/dist/tools/browser-agent.d.ts.map +1 -0
- package/dist/tools/browser-agent.js +120 -0
- package/dist/tools/codegen-agent.d.ts +3 -0
- package/dist/tools/codegen-agent.d.ts.map +1 -0
- package/dist/tools/codegen-agent.js +56 -0
- package/dist/tools/diagnosis-fetcher.d.ts +3 -0
- package/dist/tools/diagnosis-fetcher.d.ts.map +1 -0
- package/dist/tools/diagnosis-fetcher.js +88 -0
- package/dist/tools/test-run.d.ts +3 -0
- package/dist/tools/test-run.d.ts.map +1 -0
- package/dist/tools/test-run.js +49 -0
- package/dist/tools/types.d.ts +11 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/utils/git.d.ts +2 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +11 -0
- package/dist/utils/repo-tree.d.ts +2 -0
- package/dist/utils/repo-tree.d.ts.map +1 -0
- package/dist/utils/repo-tree.js +75 -0
- package/package.json +4 -3
package/dist/bin/utils/index.js
CHANGED
|
@@ -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",
|
package/dist/file/server.d.ts
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/file/server.js
CHANGED
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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.
|
|
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.
|
|
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",
|