@empiricalrun/test-gen 0.31.19 → 0.31.21
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 +15 -0
- package/dist/actions/assert.d.ts.map +1 -1
- package/dist/actions/assert.js +6 -4
- package/dist/actions/click.d.ts.map +1 -1
- package/dist/actions/click.js +5 -3
- package/dist/actions/done.js +1 -1
- package/dist/actions/fill.d.ts.map +1 -1
- package/dist/actions/fill.js +4 -2
- package/dist/actions/goto.d.ts.map +1 -1
- package/dist/actions/goto.js +5 -3
- package/dist/actions/hover.js +2 -2
- package/dist/actions/index.d.ts +8 -3
- package/dist/actions/index.d.ts.map +1 -1
- package/dist/actions/index.js +56 -9
- package/dist/actions/reload-page.d.ts.map +1 -1
- package/dist/actions/reload-page.js +4 -2
- package/dist/actions/skill.d.ts +18 -0
- package/dist/actions/skill.d.ts.map +1 -0
- package/dist/actions/skill.js +94 -0
- package/dist/actions/text-content.d.ts.map +1 -1
- package/dist/actions/text-content.js +4 -2
- package/dist/agent/browsing/index.d.ts +13 -3
- package/dist/agent/browsing/index.d.ts.map +1 -1
- package/dist/agent/browsing/index.js +119 -207
- package/dist/agent/codegen/create-test-block.js +1 -1
- package/dist/agent/codegen/skills-retriever.d.ts +13 -0
- package/dist/agent/codegen/skills-retriever.d.ts.map +1 -0
- package/dist/agent/codegen/skills-retriever.js +61 -0
- package/dist/agent/codegen/use-skill.d.ts +9 -0
- package/dist/agent/codegen/use-skill.d.ts.map +1 -0
- package/dist/agent/codegen/use-skill.js +49 -0
- package/dist/agent/codegen/utils.d.ts +9 -0
- package/dist/agent/codegen/utils.d.ts.map +1 -1
- package/dist/agent/codegen/utils.js +20 -1
- package/dist/agent/master/run.d.ts +16 -5
- package/dist/agent/master/run.d.ts.map +1 -1
- package/dist/agent/master/run.js +178 -38
- package/dist/agent/verification/index.d.ts.map +1 -1
- package/dist/agent/verification/index.js +2 -0
- package/dist/bin/utils/context.d.ts +1 -0
- package/dist/bin/utils/context.d.ts.map +1 -1
- package/dist/bin/utils/context.js +7 -2
- package/dist/bin/utils/platform/web/index.d.ts +1 -0
- package/dist/bin/utils/platform/web/index.d.ts.map +1 -1
- package/dist/bin/utils/platform/web/index.js +28 -1
- package/dist/file/client.d.ts +2 -1
- package/dist/file/client.d.ts.map +1 -1
- package/dist/file/client.js +2 -2
- package/dist/file/server.d.ts.map +1 -1
- package/dist/file/server.js +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -5
- package/dist/types/index.d.ts +10 -4
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/agent/master/run.js
CHANGED
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.createTestUsingMasterAgent = exports.getNextAction = void 0;
|
|
4
4
|
const llm_1 = require("@empiricalrun/llm");
|
|
5
5
|
const vision_1 = require("@empiricalrun/llm/vision");
|
|
6
|
+
const actions_1 = require("../../actions");
|
|
6
7
|
const next_task_1 = require("../../actions/next-task");
|
|
8
|
+
const skill_1 = require("../../actions/skill");
|
|
9
|
+
const logger_1 = require("../../bin/logger");
|
|
7
10
|
const constants_1 = require("../../constants");
|
|
8
11
|
const reporter_1 = require("../../reporter");
|
|
9
|
-
|
|
10
|
-
|
|
12
|
+
const session_1 = require("../../session");
|
|
13
|
+
const browsing_1 = require("../browsing");
|
|
14
|
+
const utils_1 = require("../browsing/utils");
|
|
15
|
+
const skills_retriever_1 = require("../codegen/skills-retriever");
|
|
16
|
+
const verification_1 = require("../verification");
|
|
17
|
+
const MAX_ERROR_COUNT = 2;
|
|
18
|
+
async function getNextAction({ task, executedActions, failedActions, page, trace, llm, options, pageScreenshot, actions, disableSkills, }) {
|
|
19
|
+
const promptSpan = trace?.span({ name: "master-agent-prompt" });
|
|
11
20
|
const promptMessages = await (0, llm_1.getPrompt)("test-gen", {
|
|
12
21
|
task,
|
|
22
|
+
failedActions: failedActions.map((a) => a).join("\n"),
|
|
13
23
|
executedActions: executedActions.map((a) => a).join("\n"),
|
|
14
24
|
pageUrl: page.url(),
|
|
15
|
-
});
|
|
25
|
+
}, 14);
|
|
16
26
|
// assuming there is only one user message in the prompt. if there is a change in langfuse prompt format, this will need to be updated
|
|
17
27
|
const userMessage = promptMessages.filter((m) => m.role === "user")[0];
|
|
18
28
|
const systemMessage = promptMessages.filter((m) => m.role === "system")[0];
|
|
@@ -32,7 +42,10 @@ async function getNextAction({ task, executedActions, page, trace, llm, options,
|
|
|
32
42
|
systemMessage,
|
|
33
43
|
userMessage,
|
|
34
44
|
];
|
|
35
|
-
const
|
|
45
|
+
const actionSchemas = disableSkills || skill_1.testCaseSkills.getAvailableSkills().length === 0
|
|
46
|
+
? []
|
|
47
|
+
: actions.getMasterActionSchemas();
|
|
48
|
+
const tools = [next_task_1.NextTaskAction.schema, ...actionSchemas];
|
|
36
49
|
promptSpan?.end({ output: { messages } });
|
|
37
50
|
const completion = await llm.createChatCompletion({
|
|
38
51
|
messages,
|
|
@@ -43,6 +56,7 @@ async function getNextAction({ task, executedActions, page, trace, llm, options,
|
|
|
43
56
|
temperature: 1,
|
|
44
57
|
},
|
|
45
58
|
trace,
|
|
59
|
+
traceName: "master-agent-llm",
|
|
46
60
|
// @ts-ignore
|
|
47
61
|
tools,
|
|
48
62
|
});
|
|
@@ -50,43 +64,169 @@ async function getNextAction({ task, executedActions, page, trace, llm, options,
|
|
|
50
64
|
return toolCall;
|
|
51
65
|
}
|
|
52
66
|
exports.getNextAction = getNextAction;
|
|
53
|
-
async function
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
67
|
+
async function createTestUsingMasterAgent({ task, page, testCase, options, }) {
|
|
68
|
+
const logger = new logger_1.CustomLogger({ useReporter: false });
|
|
69
|
+
const testgenUpdatesReporter = new reporter_1.TestGenUpdatesReporter();
|
|
70
|
+
// add timeout for the page to settle in
|
|
71
|
+
await page.waitForTimeout(3000);
|
|
72
|
+
const trace = llm_1.langfuseInstance.trace({
|
|
73
|
+
name: "test-generator",
|
|
74
|
+
id: crypto.randomUUID(),
|
|
75
|
+
version: (0, session_1.getSessionDetails)().version,
|
|
76
|
+
metadata: {
|
|
77
|
+
generationId: (0, session_1.getSessionDetails)().generationId,
|
|
78
|
+
sessionId: (0, session_1.getSessionDetails)().sessionId,
|
|
79
|
+
},
|
|
80
|
+
tags: [
|
|
81
|
+
options.metadata?.projectName,
|
|
82
|
+
options.metadata?.environment,
|
|
83
|
+
].filter((s) => !!s),
|
|
84
|
+
});
|
|
85
|
+
const llm = new llm_1.LLM({
|
|
64
86
|
trace,
|
|
65
|
-
|
|
87
|
+
provider: options.modelProvider || constants_1.DEFAULT_MODEL_PROVIDER,
|
|
88
|
+
defaultModel: options.model || constants_1.DEFAULT_MODEL,
|
|
89
|
+
providerApiKey: constants_1.MODEL_API_KEYS[options.modelProvider || constants_1.DEFAULT_MODEL_PROVIDER],
|
|
90
|
+
// we will be using google model for larger context window, in such cases 1 million tokens is not enough
|
|
91
|
+
maxTokens: options.modelProvider === "google" ? 3000000 : 1000000,
|
|
92
|
+
});
|
|
93
|
+
const skills = await (0, skills_retriever_1.getAppropriateSkills)({
|
|
94
|
+
testCase,
|
|
95
|
+
trace,
|
|
96
|
+
//@ts-ignore
|
|
66
97
|
options,
|
|
67
|
-
pageScreenshot,
|
|
68
98
|
});
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
99
|
+
skill_1.testCaseSkills.updateSkills(skills);
|
|
100
|
+
const actions = new actions_1.PlaywrightActions(page);
|
|
101
|
+
await (0, utils_1.injectPwLocatorGenerator)(page);
|
|
102
|
+
trace.update({ input: { task } });
|
|
103
|
+
let isGivenTaskDone = false;
|
|
104
|
+
const masterAgentActions = [];
|
|
105
|
+
let failedActions = [];
|
|
106
|
+
let disableSkills = false;
|
|
107
|
+
while (!isGivenTaskDone) {
|
|
108
|
+
const masterAgentSpan = trace.span({
|
|
109
|
+
name: "master-agent",
|
|
110
|
+
input: {
|
|
111
|
+
task,
|
|
112
|
+
executedActions: masterAgentActions,
|
|
113
|
+
failedActions,
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
if (masterAgentActions.length > 0) {
|
|
117
|
+
const verificationAgentResp = await (0, verification_1.verificationAgent)({
|
|
118
|
+
llm,
|
|
119
|
+
trace: masterAgentSpan,
|
|
120
|
+
task,
|
|
121
|
+
conversation: ["Successfully executed actions", ...masterAgentActions],
|
|
122
|
+
});
|
|
123
|
+
isGivenTaskDone = verificationAgentResp.isDone;
|
|
124
|
+
if (isGivenTaskDone) {
|
|
125
|
+
await testgenUpdatesReporter.sendMessage(`${verificationAgentResp.reason} Marking the task as done.`);
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
76
128
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
129
|
+
const buffer = await page.screenshot({ fullPage: true });
|
|
130
|
+
const testGenReporter = new reporter_1.TestGenUpdatesReporter();
|
|
131
|
+
const testGenSnapshotUpdatePromise = testGenReporter.sendCurrentView(buffer);
|
|
132
|
+
const pageScreenshot = buffer.toString("base64");
|
|
133
|
+
let output;
|
|
134
|
+
const toolCall = await getNextAction({
|
|
135
|
+
task,
|
|
136
|
+
executedActions: masterAgentActions,
|
|
137
|
+
failedActions,
|
|
138
|
+
page,
|
|
139
|
+
trace: masterAgentSpan,
|
|
140
|
+
llm,
|
|
141
|
+
options,
|
|
142
|
+
pageScreenshot,
|
|
143
|
+
actions,
|
|
144
|
+
disableSkills,
|
|
145
|
+
});
|
|
146
|
+
if (toolCall) {
|
|
147
|
+
const args = JSON.parse(toolCall.function.arguments);
|
|
148
|
+
const masterAgentActionSpan = masterAgentSpan.span({
|
|
149
|
+
name: "master-agent-action",
|
|
150
|
+
});
|
|
151
|
+
try {
|
|
152
|
+
output = {
|
|
153
|
+
action: JSON.parse(toolCall.function.arguments).action ||
|
|
154
|
+
JSON.parse(toolCall.function.arguments).skill,
|
|
155
|
+
reason: JSON.parse(toolCall.function.arguments).reason,
|
|
156
|
+
};
|
|
157
|
+
void testGenReporter.sendMessage(output.reason);
|
|
158
|
+
logger.log(`Next Action: ${output.reason}`);
|
|
159
|
+
if (toolCall.function.name === skill_1.SKILL_USAGE) {
|
|
160
|
+
await actions.executeAction(toolCall.function.name, args, masterAgentActionSpan);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
await (0, browsing_1.executeTaskUsingBrowsingAgent)({
|
|
164
|
+
trace: masterAgentActionSpan,
|
|
165
|
+
action: output.action,
|
|
166
|
+
logger,
|
|
167
|
+
page,
|
|
168
|
+
options,
|
|
169
|
+
llm,
|
|
170
|
+
actions,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
// resetting error count as there is a successful action
|
|
174
|
+
failedActions = [];
|
|
175
|
+
masterAgentActions.push(output.action);
|
|
176
|
+
masterAgentActionSpan.end({
|
|
177
|
+
input: {
|
|
178
|
+
action: output.action,
|
|
179
|
+
reason: output.reason,
|
|
180
|
+
type: toolCall.function.name,
|
|
181
|
+
},
|
|
182
|
+
output: {
|
|
183
|
+
success: true,
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
// enable skills after success
|
|
187
|
+
disableSkills = false;
|
|
188
|
+
}
|
|
189
|
+
catch (e) {
|
|
190
|
+
if (toolCall.function.name === skill_1.SKILL_USAGE) {
|
|
191
|
+
logger.log("Disabling skill usage for next retry");
|
|
192
|
+
disableSkills = true;
|
|
193
|
+
}
|
|
194
|
+
masterAgentActionSpan.end({
|
|
195
|
+
input: {
|
|
196
|
+
action: output.action,
|
|
197
|
+
reason: output.reason,
|
|
198
|
+
type: toolCall.function.name,
|
|
199
|
+
},
|
|
200
|
+
output: {
|
|
201
|
+
error: true,
|
|
202
|
+
errorSummary: e.message,
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
logger.error("Failed to run master agent's next task", JSON.stringify(toolCall, null, 2), e);
|
|
206
|
+
failedActions.push(JSON.stringify(toolCall, null, 2));
|
|
207
|
+
if (failedActions.length >= MAX_ERROR_COUNT) {
|
|
208
|
+
const error = "Agent is not able to figure out next action, marking task as done";
|
|
209
|
+
logger.error(error);
|
|
210
|
+
await testgenUpdatesReporter.sendMessage(error);
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
83
214
|
}
|
|
215
|
+
trace.update({ input: { task }, output: { output } });
|
|
216
|
+
await testGenSnapshotUpdatePromise;
|
|
217
|
+
masterAgentSpan.end({
|
|
218
|
+
output: { action: output.action, reason: output.reason },
|
|
219
|
+
});
|
|
84
220
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
await
|
|
90
|
-
|
|
221
|
+
await page.close();
|
|
222
|
+
const { code, importPaths } = actions.generateCode();
|
|
223
|
+
trace.update({ input: { task }, output: { code } });
|
|
224
|
+
logger.success("Successfully generated code for the given task");
|
|
225
|
+
await testgenUpdatesReporter.sendMessage(`Successfully generated code for the given task. \n View [trace](${trace.getTraceUrl()})`);
|
|
226
|
+
logger.log(`Trace: ${trace.getTraceUrl()}`);
|
|
227
|
+
return {
|
|
228
|
+
code,
|
|
229
|
+
importPaths,
|
|
230
|
+
};
|
|
91
231
|
}
|
|
92
|
-
exports.
|
|
232
|
+
exports.createTestUsingMasterAgent = createTestUsingMasterAgent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/verification/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,GAAG,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhE;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,GAAG,EACH,KAAK,EACL,IAAI,EACJ,YAAY,GACb,EAAE;IACD,GAAG,EAAE,GAAG,CAAC;IACT,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACd;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/verification/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,GAAG,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhE;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,GAAG,EACH,KAAK,EACL,IAAI,EACJ,YAAY,GACb,EAAE;IACD,GAAG,EAAE,GAAG,CAAC;IACT,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACd;;;GAkDA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/bin/utils/context.ts"],"names":[],"mappings":"AAKA,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM;;;;
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/bin/utils/context.ts"],"names":[],"mappings":"AAKA,wBAAsB,yBAAyB,2CAS9C;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM;;;;GAOtD"}
|
|
@@ -3,11 +3,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.contextForGeneration = void 0;
|
|
6
|
+
exports.contextForGeneration = exports.createGitIgnoreFileFilter = void 0;
|
|
7
7
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
8
8
|
const ignore_1 = __importDefault(require("ignore"));
|
|
9
9
|
const fs_1 = require("./fs");
|
|
10
|
-
async function
|
|
10
|
+
async function createGitIgnoreFileFilter() {
|
|
11
11
|
const ignoreFn = (0, ignore_1.default)();
|
|
12
12
|
if (fs_extra_1.default.existsSync(".gitignore")) {
|
|
13
13
|
// Not checking for nested gitignore
|
|
@@ -15,6 +15,11 @@ async function contextForGeneration(file) {
|
|
|
15
15
|
ignoreFn.add(gitignore);
|
|
16
16
|
}
|
|
17
17
|
const filter = ignoreFn.createFilter();
|
|
18
|
+
return filter;
|
|
19
|
+
}
|
|
20
|
+
exports.createGitIgnoreFileFilter = createGitIgnoreFileFilter;
|
|
21
|
+
async function contextForGeneration(file) {
|
|
22
|
+
const filter = await createGitIgnoreFileFilter();
|
|
18
23
|
return {
|
|
19
24
|
codePrompt: await (0, fs_1.generatePromptFromDirectory)("./tests", filter),
|
|
20
25
|
pomPrompt: await (0, fs_1.generatePromptFromDirectory)("./pages", filter),
|
|
@@ -54,4 +54,5 @@ export declare const injectCodeSnippetBySuiteChain: ({ testFileContent, codeSnip
|
|
|
54
54
|
codeSnippet: string;
|
|
55
55
|
suites: string[];
|
|
56
56
|
}) => string;
|
|
57
|
+
export declare const importAllExportsStmtFromFilePaths: (filePaths: string[], testFilePath: string) => Promise<string[]>;
|
|
57
58
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/bin/utils/platform/web/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/bin/utils/platform/web/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,IAAI,EAIL,MAAM,UAAU,CAAC;AAGlB;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,YAAY,EACZ,MAAM,EACN,OAAO,GACR,EAAE;IACD,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB,GAAG;IACF,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,QAAQ,EAAE,IAAI,GAAG,SAAS,CAAC;CAC5B,CAuCA;AAwBD,wBAAsB,0CAA0C,CAC9D,QAAQ,EAAE,MAAM,oBA+BjB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,IAAI,GAAG,SAAS,GACrB,IAAI,GAAG,SAAS,CA4BlB;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAG5E;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CA8C7D;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,mCAWjB;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,iBAShD;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,iBAQhD;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,UAE5E;AAED,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,iBAMpD;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,UAcpD;AAED,wBAAsB,iCAAiC,CAAC,QAAQ,EAAE,MAAM,+BAoBvE;AAED,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,UA0CtB;AAED,eAAO,MAAM,6BAA6B;qBAKvB,MAAM;iBACV,MAAM;YACX,MAAM,EAAE;YA2DjB,CAAC;AAEF,eAAO,MAAM,iCAAiC,cACjC,MAAM,EAAE,gBACL,MAAM,sBAyBrB,CAAC"}
|
|
@@ -3,10 +3,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.injectCodeSnippetBySuiteChain = exports.replaceCreateTestWithNewCode = exports.getPageVariableNameFromCreateTest = exports.getFixtureImportPath = exports.removeTestOnly = exports.addNewImport = exports.formatCode = exports.lintErrors = exports.stripAndPrependImports = exports.validateTypescript = exports.appendToTestBlock = exports.findFirstSerialDescribeBlock = exports.hasTopLevelDescribeConfigureWithSerialMode = exports.getTypescriptTestBlock = void 0;
|
|
6
|
+
exports.importAllExportsStmtFromFilePaths = exports.injectCodeSnippetBySuiteChain = exports.replaceCreateTestWithNewCode = exports.getPageVariableNameFromCreateTest = exports.getFixtureImportPath = exports.removeTestOnly = exports.addNewImport = exports.formatCode = exports.lintErrors = exports.stripAndPrependImports = exports.validateTypescript = exports.appendToTestBlock = exports.findFirstSerialDescribeBlock = exports.hasTopLevelDescribeConfigureWithSerialMode = exports.getTypescriptTestBlock = void 0;
|
|
7
7
|
const eslint_1 = require("eslint");
|
|
8
8
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
9
9
|
const lodash_isequal_1 = __importDefault(require("lodash.isequal"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
10
11
|
const prettier_1 = __importDefault(require("prettier"));
|
|
11
12
|
const ts_morph_1 = require("ts-morph");
|
|
12
13
|
const typescript_1 = __importDefault(require("typescript"));
|
|
@@ -345,3 +346,29 @@ const injectCodeSnippetBySuiteChain = ({ testFileContent, codeSnippet, suites, }
|
|
|
345
346
|
return sourceFile.getFullText();
|
|
346
347
|
};
|
|
347
348
|
exports.injectCodeSnippetBySuiteChain = injectCodeSnippetBySuiteChain;
|
|
349
|
+
const importAllExportsStmtFromFilePaths = async (filePaths, testFilePath) => {
|
|
350
|
+
const statements = [];
|
|
351
|
+
for (const filePath of filePaths) {
|
|
352
|
+
const fullPath = path_1.default.resolve(process.cwd(), filePath);
|
|
353
|
+
let importPath = path_1.default.relative(path_1.default.dirname(testFilePath), filePath);
|
|
354
|
+
if (!importPath.startsWith(".")) {
|
|
355
|
+
importPath = "./" + importPath;
|
|
356
|
+
}
|
|
357
|
+
const file = await fs_extra_1.default.readFile(fullPath, "utf-8");
|
|
358
|
+
const project = new ts_morph_1.Project();
|
|
359
|
+
const sourceFile = project.createSourceFile("index.ts", file);
|
|
360
|
+
const exportedFunctions = sourceFile
|
|
361
|
+
.getFunctions()
|
|
362
|
+
.filter((fn) => fn.isExported())
|
|
363
|
+
.map((fn) => fn.getName());
|
|
364
|
+
const exportedVariables = sourceFile
|
|
365
|
+
.getVariableDeclarations()
|
|
366
|
+
.filter((v) => v.isExported())
|
|
367
|
+
.map((fn) => fn.getName());
|
|
368
|
+
const imports = [...exportedFunctions, ...exportedVariables];
|
|
369
|
+
const importStatement = `import { ${imports.join(",")} } from '${importPath.replace(".ts", "")}';`;
|
|
370
|
+
statements.push(importStatement);
|
|
371
|
+
}
|
|
372
|
+
return statements;
|
|
373
|
+
};
|
|
374
|
+
exports.importAllExportsStmtFromFilePaths = importAllExportsStmtFromFilePaths;
|
package/dist/file/client.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
declare class TestFileService {
|
|
2
2
|
baseUrl: string;
|
|
3
3
|
constructor(port: number);
|
|
4
|
-
updateTest({ generatedCode, task, }: {
|
|
4
|
+
updateTest({ generatedCode, task, importPaths, }: {
|
|
5
5
|
generatedCode: string;
|
|
6
6
|
task: string;
|
|
7
|
+
importPaths: string[];
|
|
7
8
|
}): Promise<void>;
|
|
8
9
|
}
|
|
9
10
|
export default TestFileService;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/file/client.ts"],"names":[],"mappings":"AAAA,cAAM,eAAe;IACnB,OAAO,EAAE,MAAM,CAAC;gBACJ,IAAI,EAAE,MAAM;IAIlB,UAAU,CAAC,EACf,aAAa,EACb,IAAI,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/file/client.ts"],"names":[],"mappings":"AAAA,cAAM,eAAe;IACnB,OAAO,EAAE,MAAM,CAAC;gBACJ,IAAI,EAAE,MAAM;IAIlB,UAAU,CAAC,EACf,aAAa,EACb,IAAI,EACJ,WAAW,GACZ,EAAE;QACD,aAAa,EAAE,MAAM,CAAC;QACtB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,EAAE,CAAC;KACvB;CAeF;AAED,eAAe,eAAe,CAAC"}
|
package/dist/file/client.js
CHANGED
|
@@ -5,13 +5,13 @@ class TestFileService {
|
|
|
5
5
|
constructor(port) {
|
|
6
6
|
this.baseUrl = `http://localhost:${port}`;
|
|
7
7
|
}
|
|
8
|
-
async updateTest({ generatedCode, task, }) {
|
|
8
|
+
async updateTest({ generatedCode, task, importPaths, }) {
|
|
9
9
|
const resp = await fetch(`${this.baseUrl}/test`, {
|
|
10
10
|
method: "POST",
|
|
11
11
|
headers: {
|
|
12
12
|
"Content-Type": "application/json",
|
|
13
13
|
},
|
|
14
|
-
body: JSON.stringify({ generatedCode, task }),
|
|
14
|
+
body: JSON.stringify({ generatedCode, task, importPaths }),
|
|
15
15
|
});
|
|
16
16
|
if (!resp.ok) {
|
|
17
17
|
throw new Error(resp.statusText);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/file/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/file/server.ts"],"names":[],"mappings":"AAUA,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,IAAI,CAAa;gBACb,EAAE,IAAI,EAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE;IAGtC,WAAW,CAAC,QAAQ,EAAE,MAAM;IAGtB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;CAuC1C;AAED,wBAAsB,gBAAgB,kBAAK"}
|
package/dist/file/server.js
CHANGED
|
@@ -21,13 +21,14 @@ class FileService {
|
|
|
21
21
|
const app = (0, express_1.default)();
|
|
22
22
|
app.use(express_1.default.json());
|
|
23
23
|
app.post("/test", async (req, res) => {
|
|
24
|
-
const { generatedCode } = req.body;
|
|
24
|
+
const { generatedCode, importPaths } = req.body;
|
|
25
25
|
try {
|
|
26
26
|
const testFilePath = path_1.default.resolve(process.cwd(), this.filePath);
|
|
27
27
|
if (testFilePath) {
|
|
28
28
|
const testFile = fs_1.default.readFileSync(testFilePath, "utf-8");
|
|
29
29
|
const newContents = (0, web_1.replaceCreateTestWithNewCode)(testFilePath, testFile, generatedCode);
|
|
30
|
-
|
|
30
|
+
const importStatements = await (0, web_1.importAllExportsStmtFromFilePaths)(importPaths, this.filePath);
|
|
31
|
+
fs_1.default.writeFileSync(testFilePath, `${importStatements.join("\n")}\n${newContents}`, "utf-8");
|
|
31
32
|
await (0, web_1.lintErrors)(testFilePath);
|
|
32
33
|
return res.send({ success: true });
|
|
33
34
|
}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAalC,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAalC,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,iBAmCxD"}
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.createTest = void 0;
|
|
7
7
|
const llm_1 = require("@empiricalrun/llm");
|
|
8
|
-
const
|
|
8
|
+
const run_1 = require("./agent/master/run");
|
|
9
9
|
const utils_1 = require("./bin/utils");
|
|
10
10
|
const client_1 = __importDefault(require("./file/client"));
|
|
11
11
|
const reporter_1 = require("./reporter");
|
|
@@ -31,15 +31,23 @@ async function createTest(task, page) {
|
|
|
31
31
|
generationId: testGenConfig.options?.metadata.generationId,
|
|
32
32
|
});
|
|
33
33
|
const fileService = new client_1.default(Number(port));
|
|
34
|
-
const code = await (0,
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
const { code, importPaths } = await (0, run_1.createTestUsingMasterAgent)({
|
|
35
|
+
testCase: testGenConfig.testCase,
|
|
36
|
+
page,
|
|
37
|
+
task,
|
|
38
|
+
options: {
|
|
39
|
+
htmlSanitize: {
|
|
40
|
+
disallowedStrings: [
|
|
41
|
+
"v-data-table__td v-data-table-column--align-start",
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
...testGenConfig.options,
|
|
37
45
|
},
|
|
38
|
-
...testGenConfig.options,
|
|
39
46
|
});
|
|
40
47
|
await fileService.updateTest({
|
|
41
48
|
task,
|
|
42
49
|
generatedCode: code,
|
|
50
|
+
importPaths,
|
|
43
51
|
});
|
|
44
52
|
}
|
|
45
53
|
exports.createTest = createTest;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LLMModel, LLMProvider, ModelParameters } from "@empiricalrun/llm";
|
|
1
|
+
import { LLMModel, LLMProvider, ModelParameters, TraceClient } from "@empiricalrun/llm";
|
|
2
2
|
import OpenAI from "openai";
|
|
3
3
|
import { Page } from "playwright";
|
|
4
4
|
export type FileContent = {
|
|
@@ -35,18 +35,24 @@ export type TestCase = {
|
|
|
35
35
|
group: string;
|
|
36
36
|
suites: string[];
|
|
37
37
|
};
|
|
38
|
-
export type PlaywrightActionGenerator = (page: Page, options
|
|
38
|
+
export type PlaywrightActionGenerator = (page: Page, options: {
|
|
39
39
|
stateVariables: Record<string, any>;
|
|
40
40
|
}) => Action;
|
|
41
41
|
export type ActionSchema = OpenAI.Chat.Completions.ChatCompletionTool;
|
|
42
42
|
export type Action = {
|
|
43
43
|
name: string;
|
|
44
44
|
schema: ActionSchema;
|
|
45
|
-
execute: (
|
|
45
|
+
execute: (options: {
|
|
46
|
+
args: Record<string, any>;
|
|
47
|
+
trace?: TraceClient;
|
|
48
|
+
}) => Promise<{
|
|
46
49
|
locator: string;
|
|
47
50
|
} | void>;
|
|
48
51
|
template: (args: Record<string, any>, options: {
|
|
49
52
|
locator: string;
|
|
50
|
-
}) =>
|
|
53
|
+
}) => {
|
|
54
|
+
code: string;
|
|
55
|
+
importPath?: string;
|
|
56
|
+
};
|
|
51
57
|
};
|
|
52
58
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,WAAW,EACX,eAAe,EACf,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC;IACzB,KAAK,EAAE,QAAQ,CAAC;IAChB,aAAa,EAAE,WAAW,CAAC;IAC3B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,QAAQ,EAAE;QACR,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,eAAe,EAAE,MAAM,CAAC;QACxB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,aAAa,GAAG,YAAY,CAAC;KAC3C,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,OAAO,CAAC,EAAE,oBAAoB,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,yBAAyB,GAAG,CACtC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE;IACP,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACrC,KACE,MAAM,CAAC;AAEZ,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC;AAEtE,MAAM,MAAM,MAAM,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,CAAC,OAAO,EAAE;QACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC1B,KAAK,CAAC,EAAE,WAAW,CAAC;KACrB,KAAK,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IAC1C,QAAQ,EAAE,CACR,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACzB,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,KACzB;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@empiricalrun/test-gen",
|
|
3
|
-
"version": "0.31.
|
|
3
|
+
"version": "0.31.21",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"registry": "https://registry.npmjs.org/",
|
|
6
6
|
"access": "public"
|
|
@@ -44,9 +44,9 @@
|
|
|
44
44
|
"ts-morph": "^23.0.0",
|
|
45
45
|
"tsx": "^4.16.2",
|
|
46
46
|
"typescript": "^5.3.3",
|
|
47
|
-
"@empiricalrun/llm": "^0.9.
|
|
47
|
+
"@empiricalrun/llm": "^0.9.4",
|
|
48
48
|
"@empiricalrun/r2-uploader": "^0.3.3",
|
|
49
|
-
"@empiricalrun/reporter": "^0.20.
|
|
49
|
+
"@empiricalrun/reporter": "^0.20.3"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@types/detect-port": "^1.3.5",
|