@empiricalrun/test-gen 0.47.3 → 0.47.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.
- package/CHANGELOG.md +20 -0
- package/dist/agent/browsing/run.d.ts +4 -1
- package/dist/agent/browsing/run.d.ts.map +1 -1
- package/dist/agent/browsing/run.js +8 -3
- package/dist/agent/browsing/utils.d.ts +6 -13
- package/dist/agent/browsing/utils.d.ts.map +1 -1
- package/dist/agent/browsing/utils.js +9 -38
- package/dist/agent/chat.d.ts +7 -0
- package/dist/agent/chat.d.ts.map +1 -0
- package/dist/agent/chat.js +89 -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/bin/index.js +49 -34
- 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 +16 -0
- package/dist/tools/browser-agent.d.ts.map +1 -0
- package/dist/tools/browser-agent.js +76 -0
- package/dist/tools/codegen-agent.d.ts +9 -0
- package/dist/tools/codegen-agent.d.ts.map +1 -0
- package/dist/tools/codegen-agent.js +44 -0
- package/dist/tools/test-run.d.ts +10 -0
- package/dist/tools/test-run.d.ts.map +1 -0
- package/dist/tools/test-run.js +35 -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/package.json +3 -2
|
@@ -5,16 +5,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.appendCreateTestBlock = exports.getAppendCreateTestBlockCompletion = exports.updateTest = exports.getUpdateTestCodeCompletion = void 0;
|
|
7
7
|
const llm_1 = require("@empiricalrun/llm");
|
|
8
|
-
const crypto_1 = __importDefault(require("crypto"));
|
|
9
8
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
10
9
|
const logger_1 = require("../../bin/logger");
|
|
11
10
|
const context_1 = require("../../bin/utils/context");
|
|
12
11
|
const fs_1 = require("../../bin/utils/fs");
|
|
13
12
|
const web_1 = require("../../bin/utils/platform/web");
|
|
14
13
|
const constants_1 = require("../../constants");
|
|
15
|
-
const promptTemplate_0 = "{{#section \"system\"}}\n\nYou are a software test engineer who is given a task to update a test case. You will be provided with steps of a test\ncase scenario and you are given a snippet with interface await createTest(task, playwright_page_instance).\n\nYou need to analyze the request and place createTest snippet at the correct position and pass on the steps to this\n`createTest` method with the correct page instance.\n\nYou will be provided with current tests, fixtures and page object models for you to use and update code as per the\ntask provided to you.\nYou need to respond with file path and updated code block inside the file.\n\nHere is the list of current tests and fixtures:\n\n{{testFiles}}\n\n\nHere is the list of current page object models:\n\n{{pageFiles}}\n{{/section}}\n\n\n{{#section \"user\"}}\nFollowing is the test scenario for which you need to update the test:\ntest name:\n{{scenarioName}}\n\
|
|
14
|
+
const promptTemplate_0 = "{{#section \"system\"}}\n\nYou are a software test engineer who is given a task to update a test case. You will be provided with steps of a test\ncase scenario and you are given a snippet with interface await createTest(task, playwright_page_instance).\n\nYou need to analyze the request and place createTest snippet at the correct position and pass on the steps to this\n`createTest` method with the correct page instance.\n\nYou will be provided with current tests, fixtures and page object models for you to use and update code as per the\ntask provided to you.\nYou need to respond with file path and updated code block inside the file.\n\nHere is the list of current tests and fixtures:\n\n{{testFiles}}\n\n\nHere is the list of current page object models:\n\n{{pageFiles}}\n{{/section}}\n\n\n{{#section \"user\"}}\nFollowing is the test scenario for which you need to update the test:\n\ntest name:\n{{scenarioName}}\n\nTask:\n{{scenarioSteps}}\n\nFollow these steps to complete the task:\n\n1. Determine the task's intent:\n- The default intent is **\"add steps\"**.\n- If the task explicitly mentions (using words like \"replace\", \"remove\", \"delete\") that existing test steps should\nbe replaced or deleted, the intent is **\"update steps\"**. Identify the specific steps to be replaced or removed.\n- Do not assume that providing new or different steps implies an intent to update or replace existing steps. Unless\nthe task explicitly instructs to replace or remove existing code, interpret the intent as adding new steps to the\nexisting test.\n\n2. Identify the test block that requires updating.\n\n3. Place the `createTest` snippet:\n- Insert the `createTest` snippet at the location determined by the task, and pass the Playwright page instance.\n- If the intent is \"add\", do not alter the existing test code; simply append the `createTest` snippet based on any\nprovided location hints.\n- If the task includes location hints that don't match steps within the test, check dependent methods called from\nthe test for the update.\n- If no location hint is provided, place the `createTest` snippet at the end of the test block.\n- Even if the task includes steps that overlap with or are similar to existing steps, do not modify the existing\ncode. Unless the task explicitly instructs to replace or remove existing code, interpret the intent as adding new\nsteps to the existing test.\n\n4. Strip location hints from the task:\n- Remove any location hints (e.g., \"replace the current assertion and\") before passing the task to the `createTest`\nmethod.\n- The task passed into `createTest` should not contain any location hints. It should only contain actions that\nare required to be performed.\n- For example, if the original task: \"replace the current assertion and add a new assertion\" should be transformed to\n\"add a new assertion\" before passing it to the `createTest` method. This is the \"task_without_location_hints\"\n\nSubmission Guidelines:\n\n- Focus only on the provided test case and any related page object model methods used in the test.\n- Do not modify or add code within the `createTest` snippet.\n- Do not update or modify any other code apart from adding `createTest` code snippet.\n- Since the response will be used for search-and-replace operations, always provide the immediate parent AST node\nfor any code updates.\n- Include the full test block if any part of it is updated, preserving all unchanged code.\n- Do not use markdown syntax or backticks.\n- Respond using the following XML format:\n<reason_for_intent></reason_for_intent>\n<intent></intent>\n<location_of_update></location_of_update>\n<task_without_location_hints></task_without_location_hints>\n<file_path></file_path>\n<old_code_block></old_code_block>\n<new_code_block></new_code_block>\n<change></change>\n\n- Each `<old_code_block>` and `<new_code_block>` should contain only one test block or page object model method\n definition. Provide separate blocks for multiple updates.\n- The `<change></change>` tag should also mention the file path being updated.\n- There should be only one `createTest` block in the `new_code_block`. The `createTest` method should be passed\nwith entire task. Do not split the task while forwarding it to `createTest`.\n- `<new_code_block>` code snippet should be syntactically correct.\n - The code_block should not contain any import statements.\n{{/section}}";
|
|
16
15
|
const promptTemplate_1 = "{{#section \"system\"}}\nYou are a software test engineer who is given an objective to update test basis the task provided.\nYou will be provided with a test name, test and test file path.\n\nYou will be provided with current tests, fixtures and page object models for you to use and update code as per the task\nprovided to you. You need to respond with file path and updated code block inside the file.\n\nBefore responding you need to ensure that the code change is minimal and the change is reusable across tests. You need\nto ensure the code follows DRY principle.\n\nHere is the list of current tests and fixtures:\n\n{{testFiles}}\n\n\nHere is the list of current page object models:\n\n{{pageFiles}}\n\n{{/section}}\n\n{{#section \"user\"}}\nFollowing are the test details and the task to complete your objective:\nTest name:\n{{scenarioName}}\n\nTest case:\n{{currentScenarioCodeBlock}}\n\nTask:\n{{scenarioSteps}}\n\nIn order to execute the task:\n- Think step by step and first identify current test block which needs update and the methods which the current test\nblock depend on.\n- The task will demand changes in the current test case or the methods it depend on. Based on the task, identify list of\nfile paths which need change, the reason for change and the code change they need.\n- Next make changes to code blocks in each file paths.\n\n------\n\nFollow these instructions before responding with output:\n- Read the code line by line and ensure that achieve the task provided to you\n- Read the dependencies of the code block by scanning through file paths and file provided to you. refer the same file\npath while responding with output.\n- Focus only on the test case provided and associated JS methods called from the test case.\n- Since the response will be used to search and replace blocks, always respond with output which includes the full\nlexical scope surrounding the modified code.\n- If there are any updates inside test code block, ensure responding with full test block with unchanged code as well\n- Each code block should contain edits to only one code block in file path\n- DO NOT respond with any backticks or markdown syntax\n- Respond only with file path where the code block to be updated is present, old code block, new code block and a one\nliner reason for the change\n- Respond with <file_path></file_path>, <old_code_block></old_code_block>, <new_code_block></new_code_block> and\n<change></change> as xml tags\n- The reason for change should adhere to coding principles provided and review if the updated code is present in the\nfile path mentioned\n- The code change should belong to the right file path\n- The response must start with <file_path>\n {{/section}}";
|
|
17
|
-
const session_1 = require("../../session");
|
|
18
16
|
const test_update_feedback_1 = require("./test-update-feedback");
|
|
19
17
|
const utils_1 = require("./utils");
|
|
20
18
|
async function getUpdateTestCodeCompletion({ testCase, testFileContent, testFiles, pageFiles, testFilePath, options, trace, }) {
|
|
@@ -65,31 +63,18 @@ async function getUpdateTestCodeCompletion({ testCase, testFileContent, testFile
|
|
|
65
63
|
};
|
|
66
64
|
}
|
|
67
65
|
exports.getUpdateTestCodeCompletion = getUpdateTestCodeCompletion;
|
|
68
|
-
async function updateTest(testCase, file,
|
|
69
|
-
const logger = new logger_1.CustomLogger({ useReporter:
|
|
66
|
+
async function updateTest({ testCase, file, trace, }) {
|
|
67
|
+
const logger = new logger_1.CustomLogger({ useReporter: true });
|
|
70
68
|
const context = await (0, context_1.contextForGeneration)(file);
|
|
71
69
|
const { codePrompt, pomPrompt, nonSpecFilePrompt, testFileContent } = context;
|
|
72
70
|
const generatedTestCases = [];
|
|
73
71
|
logger.logEmptyLine();
|
|
74
|
-
const session = (0, session_1.getSessionDetails)();
|
|
75
|
-
trace =
|
|
76
|
-
trace ||
|
|
77
|
-
llm_1.langfuseInstance?.trace({
|
|
78
|
-
name: "update-test",
|
|
79
|
-
id: crypto_1.default.randomUUID(),
|
|
80
|
-
release: session.version,
|
|
81
|
-
tags: [
|
|
82
|
-
options?.metadata.projectName || "",
|
|
83
|
-
options?.metadata.environment || "",
|
|
84
|
-
].filter((s) => !!s),
|
|
85
|
-
});
|
|
86
72
|
const request = {
|
|
87
73
|
testCase,
|
|
88
74
|
testFileContent,
|
|
89
75
|
testFiles: codePrompt,
|
|
90
76
|
pageFiles: pomPrompt,
|
|
91
77
|
testFilePath: file,
|
|
92
|
-
options,
|
|
93
78
|
};
|
|
94
79
|
const updateTestSpan = trace?.span({
|
|
95
80
|
name: "update-test",
|
|
@@ -105,7 +90,6 @@ async function updateTest(testCase, file, options, logging = true, validate = tr
|
|
|
105
90
|
testCase,
|
|
106
91
|
fileChanges,
|
|
107
92
|
logger,
|
|
108
|
-
testGenOptions: options,
|
|
109
93
|
pomPrompt: pomPrompt,
|
|
110
94
|
nonSpecFilePrompt: nonSpecFilePrompt,
|
|
111
95
|
});
|
|
@@ -125,18 +109,16 @@ async function updateTest(testCase, file, options, logging = true, validate = tr
|
|
|
125
109
|
testCase,
|
|
126
110
|
fileChanges: filteredFileChanges,
|
|
127
111
|
logger,
|
|
128
|
-
testGenOptions: options,
|
|
129
112
|
pomPrompt: pomPrompt,
|
|
130
113
|
nonSpecFilePrompt: nonSpecFilePrompt,
|
|
131
114
|
});
|
|
132
115
|
}
|
|
133
116
|
await (0, utils_1.validateTypesAndFormatCode)({
|
|
134
|
-
validateTypes:
|
|
117
|
+
validateTypes: true,
|
|
135
118
|
trace: updateTestSpan,
|
|
136
119
|
testCase,
|
|
137
120
|
filePaths: fileChanges.map((f) => f.filePath),
|
|
138
121
|
logger,
|
|
139
|
-
testGenOptions: options,
|
|
140
122
|
pomPrompt: pomPrompt,
|
|
141
123
|
nonSpecFilePrompt: nonSpecFilePrompt,
|
|
142
124
|
});
|
|
@@ -153,19 +135,7 @@ async function updateTest(testCase, file, options, logging = true, validate = tr
|
|
|
153
135
|
return generatedTestCases;
|
|
154
136
|
}
|
|
155
137
|
exports.updateTest = updateTest;
|
|
156
|
-
async function getAppendCreateTestBlockCompletion({ testFiles, pageFiles, testCase, testFilePath,
|
|
157
|
-
const session = (0, session_1.getSessionDetails)();
|
|
158
|
-
trace =
|
|
159
|
-
trace ||
|
|
160
|
-
llm_1.langfuseInstance?.trace({
|
|
161
|
-
name: "append-create-test-block",
|
|
162
|
-
id: crypto_1.default.randomUUID(),
|
|
163
|
-
release: session.version,
|
|
164
|
-
tags: [
|
|
165
|
-
options?.metadata.projectName || "",
|
|
166
|
-
options?.metadata.environment || "",
|
|
167
|
-
].filter((s) => !!s),
|
|
168
|
-
});
|
|
138
|
+
async function getAppendCreateTestBlockCompletion({ testFiles, pageFiles, testCase, testFilePath, trace, }) {
|
|
169
139
|
const appendCreateTestSpan = trace?.span({
|
|
170
140
|
name: "append-create-test-block",
|
|
171
141
|
input: {
|
|
@@ -175,9 +145,6 @@ async function getAppendCreateTestBlockCompletion({ testFiles, pageFiles, testCa
|
|
|
175
145
|
testFilePath,
|
|
176
146
|
},
|
|
177
147
|
});
|
|
178
|
-
const promptSpan = trace?.span({
|
|
179
|
-
name: "append-create-test-block-prompt",
|
|
180
|
-
});
|
|
181
148
|
const instruction = (0, llm_1.compilePrompt)(promptTemplate_0, {
|
|
182
149
|
testFiles: testFiles,
|
|
183
150
|
pageFiles: pageFiles,
|
|
@@ -185,7 +152,6 @@ async function getAppendCreateTestBlockCompletion({ testFiles, pageFiles, testCa
|
|
|
185
152
|
scenarioSteps: testCase.steps.join("\n"),
|
|
186
153
|
scenarioFile: testFilePath,
|
|
187
154
|
});
|
|
188
|
-
promptSpan?.end({ output: { instruction } });
|
|
189
155
|
const [userInstruction] = instruction.filter((s) => s.role === "user");
|
|
190
156
|
const [systemInstruction] = instruction.filter((s) => s.role === "system");
|
|
191
157
|
userInstruction.content = `${systemInstruction?.content}
|
|
@@ -193,7 +159,7 @@ async function getAppendCreateTestBlockCompletion({ testFiles, pageFiles, testCa
|
|
|
193
159
|
${userInstruction?.content}
|
|
194
160
|
`;
|
|
195
161
|
const llm = new llm_1.LLM({
|
|
196
|
-
trace,
|
|
162
|
+
trace: appendCreateTestSpan,
|
|
197
163
|
provider: "anthropic",
|
|
198
164
|
defaultModel: "claude-3-5-sonnet-latest",
|
|
199
165
|
providerApiKey: constants_1.MODEL_API_KEYS["anthropic"],
|
|
@@ -201,7 +167,6 @@ async function getAppendCreateTestBlockCompletion({ testFiles, pageFiles, testCa
|
|
|
201
167
|
const chatCompletionParams = {
|
|
202
168
|
messages: [userInstruction],
|
|
203
169
|
modelParameters: {
|
|
204
|
-
...options?.modelParameters,
|
|
205
170
|
...constants_1.DEFAULT_MODEL_PARAMETERS,
|
|
206
171
|
},
|
|
207
172
|
};
|
|
@@ -245,7 +210,7 @@ Respond with the same xml format which was originally expected.
|
|
|
245
210
|
return response;
|
|
246
211
|
}
|
|
247
212
|
exports.getAppendCreateTestBlockCompletion = getAppendCreateTestBlockCompletion;
|
|
248
|
-
async function appendCreateTestBlock({ testCase, file,
|
|
213
|
+
async function appendCreateTestBlock({ testCase, file, trace, validateTypes = true, }) {
|
|
249
214
|
const logger = new logger_1.CustomLogger({ useReporter: false });
|
|
250
215
|
logger.log("Appending create test block");
|
|
251
216
|
const context = await (0, context_1.contextForGeneration)(file);
|
|
@@ -258,22 +223,19 @@ async function appendCreateTestBlock({ testCase, file, options, trace, validateT
|
|
|
258
223
|
]);
|
|
259
224
|
const { pomPrompt, nonSpecFilePrompt } = context;
|
|
260
225
|
const generatedTestCases = [];
|
|
261
|
-
const
|
|
226
|
+
const appendCreateTestResp = await getAppendCreateTestBlockCompletion({
|
|
262
227
|
testCase,
|
|
263
228
|
testFilePath: file,
|
|
264
|
-
options,
|
|
265
229
|
trace,
|
|
266
230
|
pageFiles: pomPrompt,
|
|
267
231
|
testFiles: testCodePrompt,
|
|
268
|
-
};
|
|
269
|
-
const appendCreateTestResp = await getAppendCreateTestBlockCompletion(appendCreateTestParams);
|
|
232
|
+
});
|
|
270
233
|
const fileChanges = (0, utils_1.extractAppendTestUpdates)(appendCreateTestResp);
|
|
271
234
|
await (0, utils_1.applyFileChanges)({
|
|
272
235
|
trace,
|
|
273
236
|
testCase,
|
|
274
237
|
fileChanges,
|
|
275
238
|
logger,
|
|
276
|
-
testGenOptions: options,
|
|
277
239
|
pomPrompt: pomPrompt,
|
|
278
240
|
nonSpecFilePrompt: nonSpecFilePrompt,
|
|
279
241
|
});
|
|
@@ -282,7 +244,6 @@ async function appendCreateTestBlock({ testCase, file, options, trace, validateT
|
|
|
282
244
|
testCase,
|
|
283
245
|
filePaths: fileChanges.map((f) => f.filePath),
|
|
284
246
|
logger,
|
|
285
|
-
testGenOptions: options,
|
|
286
247
|
pomPrompt: pomPrompt,
|
|
287
248
|
nonSpecFilePrompt: nonSpecFilePrompt,
|
|
288
249
|
validateTypes,
|
|
@@ -294,7 +255,6 @@ async function appendCreateTestBlock({ testCase, file, options, trace, validateT
|
|
|
294
255
|
...testCase,
|
|
295
256
|
updatedFiles: fileChanges.map((f) => f.filePath),
|
|
296
257
|
});
|
|
297
|
-
await (0, llm_1.flushAllTraces)();
|
|
298
258
|
return generatedTestCases;
|
|
299
259
|
}
|
|
300
260
|
exports.appendCreateTestBlock = appendCreateTestBlock;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TraceClient } from "@empiricalrun/llm";
|
|
2
|
-
import type { TestCase
|
|
2
|
+
import type { TestCase } from "@empiricalrun/shared-types";
|
|
3
3
|
import { CustomLogger } from "../../bin/logger";
|
|
4
4
|
import { TestGenUpdatesReporter } from "../../reporter";
|
|
5
5
|
import { CodeUpdate, CreateTestCodeUpdate, FileUpdateResponse } from "./types";
|
|
@@ -57,13 +57,12 @@ export declare function extractTestStepsSuggestions(input: string): {
|
|
|
57
57
|
reason: string;
|
|
58
58
|
methodName: string;
|
|
59
59
|
}[];
|
|
60
|
-
export declare function validateTypesAndFormatCode({ validateTypes, trace, testCase, filePaths, logger,
|
|
60
|
+
export declare function validateTypesAndFormatCode({ validateTypes, trace, testCase, filePaths, logger, pomPrompt, nonSpecFilePrompt, }: {
|
|
61
61
|
validateTypes?: boolean;
|
|
62
62
|
trace?: TraceClient;
|
|
63
63
|
testCase: TestCase;
|
|
64
64
|
filePaths: (string | undefined)[];
|
|
65
65
|
logger?: CustomLogger;
|
|
66
|
-
testGenOptions?: TestGenConfigOptions;
|
|
67
66
|
pomPrompt?: string;
|
|
68
67
|
nonSpecFilePrompt?: string;
|
|
69
68
|
}): Promise<void>;
|
|
@@ -103,7 +102,6 @@ export declare function applyFileChanges({ trace, testCase, fileChanges, logger,
|
|
|
103
102
|
reason: string | undefined;
|
|
104
103
|
}[];
|
|
105
104
|
logger?: CustomLogger;
|
|
106
|
-
testGenOptions?: TestGenConfigOptions;
|
|
107
105
|
pomPrompt?: string;
|
|
108
106
|
nonSpecFilePrompt?: string;
|
|
109
107
|
}): Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/agent/codegen/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/agent/codegen/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -127,7 +127,7 @@ function extractTestStepsSuggestions(input) {
|
|
|
127
127
|
return result.filter((r) => !!r.filePath && !!r.usageExample);
|
|
128
128
|
}
|
|
129
129
|
exports.extractTestStepsSuggestions = extractTestStepsSuggestions;
|
|
130
|
-
async function validateTypesAndFormatCode({ validateTypes = true, trace, testCase, filePaths, logger,
|
|
130
|
+
async function validateTypesAndFormatCode({ validateTypes = true, trace, testCase, filePaths, logger, pomPrompt, nonSpecFilePrompt, }) {
|
|
131
131
|
for (let filePath of filePaths) {
|
|
132
132
|
if (!filePath) {
|
|
133
133
|
continue;
|
|
@@ -141,7 +141,6 @@ async function validateTypesAndFormatCode({ validateTypes = true, trace, testCas
|
|
|
141
141
|
pomCode: pomPrompt ?? "",
|
|
142
142
|
nonSpecFileCode: nonSpecFilePrompt ?? "",
|
|
143
143
|
testCase: testCase,
|
|
144
|
-
options: testGenOptions,
|
|
145
144
|
});
|
|
146
145
|
}
|
|
147
146
|
trace?.event({ name: "format-file" });
|
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
import { TraceClient } from "@empiricalrun/llm";
|
|
2
|
-
import { TestErrorDiagnosisDetails
|
|
2
|
+
import { TestErrorDiagnosisDetails } from "@empiricalrun/shared-types";
|
|
3
3
|
import { CustomLogger } from "../../bin/logger";
|
|
4
|
-
|
|
5
|
-
*
|
|
6
|
-
* inputs
|
|
7
|
-
* - task
|
|
8
|
-
* - diagnosis
|
|
9
|
-
*/
|
|
10
|
-
export declare function createTaskUsingFailureDiagnosis({ options, trace, diagnosis, logger, }: {
|
|
11
|
-
options?: TestGenConfigOptions;
|
|
4
|
+
export declare function createTaskUsingFailureDiagnosis({ trace, diagnosis, logger, }: {
|
|
12
5
|
trace?: TraceClient;
|
|
13
6
|
diagnosis: TestErrorDiagnosisDetails;
|
|
14
7
|
logger?: CustomLogger;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/diagnosis-agent/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/diagnosis-agent/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAEvE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAuChD,wBAAsB,+BAA+B,CAAC,EACpD,KAAK,EACL,SAAS,EACT,MAAM,GACP,EAAE;IACD,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,yBAAyB,CAAC;IACrC,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CA6E5B"}
|
|
@@ -30,13 +30,7 @@ const responseFormat = {
|
|
|
30
30
|
},
|
|
31
31
|
},
|
|
32
32
|
};
|
|
33
|
-
|
|
34
|
-
*
|
|
35
|
-
* inputs
|
|
36
|
-
* - task
|
|
37
|
-
* - diagnosis
|
|
38
|
-
*/
|
|
39
|
-
async function createTaskUsingFailureDiagnosis({ options, trace, diagnosis, logger, }) {
|
|
33
|
+
async function createTaskUsingFailureDiagnosis({ trace, diagnosis, logger, }) {
|
|
40
34
|
trace =
|
|
41
35
|
trace ||
|
|
42
36
|
llm_1.langfuseInstance?.trace({
|
|
@@ -48,7 +42,6 @@ async function createTaskUsingFailureDiagnosis({ options, trace, diagnosis, logg
|
|
|
48
42
|
name: "auto-fix",
|
|
49
43
|
input: {
|
|
50
44
|
diagnosisId: diagnosis.diagnosisId,
|
|
51
|
-
prjRepoName: options?.metadata.projectRepoName,
|
|
52
45
|
},
|
|
53
46
|
});
|
|
54
47
|
logger?.log("Trying to fix the test using failure diagnosis. Fetching key moments of the diagnosis");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/enrich-prompt/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAmCpE,eAAO,MAAM,2BAA2B;eAM3B,MAAM;kBACH,MAAM;sBACF,MAAM;;;YAGhB,MAAM;8BACY,OAAO;uBACd,MAAM;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/enrich-prompt/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAmCpE,eAAO,MAAM,2BAA2B;eAM3B,MAAM;kBACH,MAAM;sBACF,MAAM;;;YAGhB,MAAM;8BACY,OAAO;uBACd,MAAM;EAyD1B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/infer-agent/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/infer-agent/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAUzE,wBAAsB,mBAAmB,CAAC,EACxC,IAAI,EACJ,OAAO,EACP,KAAK,GACN,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,KAAK,CAAA;CAAE,CAAC,CA4D/B"}
|
|
@@ -4,16 +4,7 @@ exports.inferAgentBasedTask = void 0;
|
|
|
4
4
|
const llm_1 = require("@empiricalrun/llm");
|
|
5
5
|
const constants_1 = require("../../constants");
|
|
6
6
|
const promptTemplate_0 = "{{#section \"system\"}}\nYou are a software test engineer specializing in Playwright end-to-end tests. You are given a task which is a part of an\nend-to-end test scenario. The task may involve updating an existing end-to-end test case or writing a new test case from\nscratch. Tests involve user interactions (e.g. click on element) or other actions supported by Playwright (e.g.\nintercept network requests)\n\nYour objective is to identify whether the task requires accessing a web browser or not.\n\nTo fulfill your objective, answer the following questions:\n\n1. Does it require you to interact with a UI element in the browser? Examples of interactions are click, fill, type, key\npress, assert visibility of the element. Actions that interact with network requests are not UI element interactions.\n\n2. Is the locator of this UI element given to you in the task? Locators look like `getByText(...)`, `getByTestId(...)`\nand other locator methods in Playwright\n\n3. Decide if you need a browser: if you need to interact with a UI element AND you are NOT given the locator for that\nelement, you WILL NEED a browser.\n\n4. If you NEED a browser, then respond with answer as \"master\", otherwise respond with \"code\"\n\n\n# Example 1\n## Input\nTask:\nin this test don't delete the agent and remove steps after that\n\n## Output\n- ui_interaction_to_be_performed: There is no interaction here\n- ui_element_to_interact_with: No element specified\n- has_locator_for_that_element: No element specified\n- reasoning_for_browser_required: No interaction hence browser is not required\n- answer: code\n\n# Example 2\n## Input\nTask:\nin the swapfast test, replace the selectTokenForSwap method. Instead we will do this\\nclick on token button - this will\nshow a drawer\\nEnter usd in the search field that shows up in the drawer\\nSelect USDC.axl for Cosmos Hub - very\nimportant to choose this instead of USDC.axl on Osmosis\n\n## Output\n- ui_interaction_to_be_performed: Click on token button\n- ui_element_to_interact_with: Token button\n- has_locator_for_that_element: false\n- reasoning_for_browser_required: Task requires interacting with a UI element and identifying its locator which needs a\nbrowser\n- answer: master\n{{/section}}\n\n{{#section \"user\"}}\nTask:\n{{task}}\n{{/section}}";
|
|
7
|
-
const session_1 = require("../../session");
|
|
8
|
-
const session = (0, session_1.getSessionDetails)();
|
|
9
7
|
async function inferAgentBasedTask({ task, options, trace, }) {
|
|
10
|
-
trace =
|
|
11
|
-
trace ||
|
|
12
|
-
llm_1.langfuseInstance?.trace({
|
|
13
|
-
name: "infer-agent-task",
|
|
14
|
-
id: crypto.randomUUID(),
|
|
15
|
-
release: session.version,
|
|
16
|
-
});
|
|
17
8
|
const inferAgentSpan = trace?.span({
|
|
18
9
|
name: "infer-agent",
|
|
19
10
|
input: {
|
package/dist/bin/index.js
CHANGED
|
@@ -9,6 +9,7 @@ const commander_1 = require("commander");
|
|
|
9
9
|
const dotenv_1 = __importDefault(require("dotenv"));
|
|
10
10
|
const run_1 = require("../agent/browsing/run");
|
|
11
11
|
const utils_1 = require("../agent/browsing/utils");
|
|
12
|
+
const chat_1 = require("../agent/chat");
|
|
12
13
|
const repo_edit_1 = require("../agent/codegen/repo-edit");
|
|
13
14
|
const run_2 = require("../agent/codegen/run");
|
|
14
15
|
const diagnosis_agent_1 = require("../agent/diagnosis-agent");
|
|
@@ -31,14 +32,12 @@ process.on("beforeExit", async () => await flushEvents());
|
|
|
31
32
|
process.on("exit", async () => await flushEvents());
|
|
32
33
|
process.on("SIGINT", async () => await flushEvents());
|
|
33
34
|
process.on("SIGTERM", async () => await flushEvents());
|
|
34
|
-
async function
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
trace,
|
|
35
|
+
async function runChatAgent(prompt) {
|
|
36
|
+
return await (0, chat_1.chatAgent)({
|
|
37
|
+
prompt,
|
|
38
38
|
});
|
|
39
|
-
return response;
|
|
40
39
|
}
|
|
41
|
-
async function
|
|
40
|
+
async function runAgentsWorkflow(testGenConfig, testGenToken) {
|
|
42
41
|
const logger = new logger_1.CustomLogger();
|
|
43
42
|
const { specPath, testCase } = testGenConfig;
|
|
44
43
|
if (process.env.LOG_URL) {
|
|
@@ -89,29 +88,10 @@ async function runAgent(testGenConfig, testGenToken) {
|
|
|
89
88
|
});
|
|
90
89
|
return;
|
|
91
90
|
}
|
|
92
|
-
// TODO: this needs to be moved to an orchestrator which decides what needs to be done first before executing the sub tasks
|
|
93
|
-
if (testGenConfig.testErrorDiagnosis &&
|
|
94
|
-
testGenConfig.testErrorDiagnosis.failingLine &&
|
|
95
|
-
// TODO: fix this hardcoding of user prompt - ideally its an auto fix intent
|
|
96
|
-
testCase.steps[0]?.toLowerCase().trim() == "can you please fix the test") {
|
|
97
|
-
const { task: updatedTask } = await (0, diagnosis_agent_1.createTaskUsingFailureDiagnosis)({
|
|
98
|
-
options: testGenConfig.options,
|
|
99
|
-
trace,
|
|
100
|
-
diagnosis: testGenConfig.testErrorDiagnosis,
|
|
101
|
-
});
|
|
102
|
-
if (updatedTask) {
|
|
103
|
-
testCase.steps = [updatedTask];
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
if (!agent || agent === "auto") {
|
|
107
|
-
agent = await resolveAgentUsingTask({
|
|
108
|
-
testCase,
|
|
109
|
-
trace,
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
logger.success(`Generating test using ${agent} agent. ${process.env.LOG_URL ? `[view log](${process.env.LOG_URL})` : ""}`);
|
|
113
91
|
if (testGenConfig.testErrorDiagnosis &&
|
|
114
92
|
testGenConfig.testErrorDiagnosis.failingLine) {
|
|
93
|
+
// If failure context is available, we can enrich the user prompt to contain
|
|
94
|
+
// the failure context
|
|
115
95
|
const requestedChangeResp = await (0, enrich_prompt_1.enrichPromptWithFailingLine)({
|
|
116
96
|
trace,
|
|
117
97
|
testBlock: testGenConfig.testErrorDiagnosis.failingLine,
|
|
@@ -119,7 +99,28 @@ async function runAgent(testGenConfig, testGenToken) {
|
|
|
119
99
|
suggestionForFix: testCase.steps.join("\n"),
|
|
120
100
|
});
|
|
121
101
|
testCase.steps = [requestedChangeResp.output];
|
|
102
|
+
// For "auto-fix" we use the user prompt (which is hard-coded in the dashboard
|
|
103
|
+
// entrypoints), and invoke more interesting enrichment
|
|
104
|
+
if (
|
|
105
|
+
// TODO: fix this hardcoding of user prompt - ideally its an auto fix intent
|
|
106
|
+
testCase.steps[0]?.toLowerCase().trim() == "can you please fix the test") {
|
|
107
|
+
const { task: updatedTask } = await (0, diagnosis_agent_1.createTaskUsingFailureDiagnosis)({
|
|
108
|
+
trace,
|
|
109
|
+
diagnosis: testGenConfig.testErrorDiagnosis,
|
|
110
|
+
});
|
|
111
|
+
if (updatedTask) {
|
|
112
|
+
testCase.steps = [updatedTask];
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (!agent || agent === "auto") {
|
|
117
|
+
const { response } = await (0, infer_agent_1.inferAgentBasedTask)({
|
|
118
|
+
task: testCase.steps.join("\n"),
|
|
119
|
+
trace,
|
|
120
|
+
});
|
|
121
|
+
agent = response;
|
|
122
122
|
}
|
|
123
|
+
logger.success(`Generating test using ${agent} agent. ${process.env.LOG_URL ? `[view log](${process.env.LOG_URL})` : ""}`);
|
|
123
124
|
if (agent === "plan") {
|
|
124
125
|
const task = testCase.steps.join("\n");
|
|
125
126
|
const plan = await (0, run_3.planTask)({
|
|
@@ -132,11 +133,18 @@ async function runAgent(testGenConfig, testGenToken) {
|
|
|
132
133
|
await new reporter_1.TestGenUpdatesReporter().sendMessage(plan);
|
|
133
134
|
}
|
|
134
135
|
else if (agent === "code") {
|
|
135
|
-
await (0, run_2.
|
|
136
|
+
await (0, run_2.generateTestWithCodegen)({
|
|
137
|
+
testCase,
|
|
138
|
+
file: specPath,
|
|
139
|
+
trace,
|
|
140
|
+
});
|
|
136
141
|
}
|
|
137
142
|
else {
|
|
138
|
-
|
|
139
|
-
|
|
143
|
+
const filePathToUpdate = await (0, utils_1.prepareFileForMasterAgent)({
|
|
144
|
+
testCase,
|
|
145
|
+
specPath,
|
|
146
|
+
trace,
|
|
147
|
+
});
|
|
140
148
|
void (0, session_1.updateSessionStatus)(testGenConfig.options?.metadata.testSessionId, {
|
|
141
149
|
status: "agent_live_session_started",
|
|
142
150
|
});
|
|
@@ -155,10 +163,11 @@ async function runAgent(testGenConfig, testGenToken) {
|
|
|
155
163
|
const program = new commander_1.Command();
|
|
156
164
|
program
|
|
157
165
|
.option("--token <token>", "Test generation token")
|
|
166
|
+
.option("--prompt <prompt>", "Prompt for the chat agent")
|
|
158
167
|
.option("--name <test-name>", "Name of the test case")
|
|
159
|
-
.option("--prompt <prompt>", "Prompt for the test case")
|
|
160
168
|
.option("--file <test-file>", "File path of the test case (inside tests dir)")
|
|
161
169
|
.option("--suites <suites>", "Comma separated list of describe blocks")
|
|
170
|
+
.option("--use-chat", "Use chat agent (and not the workflow)")
|
|
162
171
|
.parse(process.argv);
|
|
163
172
|
const options = program.opts();
|
|
164
173
|
const completedOptions = await (0, utils_2.validateAndCompleteCliOptions)(options);
|
|
@@ -181,10 +190,16 @@ async function runAgent(testGenConfig, testGenToken) {
|
|
|
181
190
|
});
|
|
182
191
|
let testGenFailed = false;
|
|
183
192
|
let agentUsed;
|
|
193
|
+
// Download the build if repo has a download script
|
|
194
|
+
await (0, test_build_1.downloadBuild)(testGenConfig.build || {});
|
|
184
195
|
try {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
196
|
+
if (completedOptions.useChat) {
|
|
197
|
+
await runChatAgent(completedOptions.prompt);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
agentUsed = await runAgentsWorkflow(testGenConfig, testGenToken);
|
|
202
|
+
}
|
|
188
203
|
}
|
|
189
204
|
catch (e) {
|
|
190
205
|
testGenFailed = true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/bin/utils/index.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/bin/utils/index.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAQD,wBAAsB,6BAA6B,CACjD,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,UAAU,CAAC,CAyDrB"}
|
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,16 @@
|
|
|
1
|
+
import { OpenAI } from "openai";
|
|
2
|
+
export declare const schema: OpenAI.Chat.Completions.ChatCompletionTool;
|
|
3
|
+
export declare const generateTestWithBrowserAgentTool: ({ testName, fileName, changeToMake, }: {
|
|
4
|
+
testName: string;
|
|
5
|
+
fileName: string;
|
|
6
|
+
changeToMake: string;
|
|
7
|
+
}) => Promise<{
|
|
8
|
+
result: string;
|
|
9
|
+
gitPatch: string;
|
|
10
|
+
error?: undefined;
|
|
11
|
+
} | {
|
|
12
|
+
result: string;
|
|
13
|
+
error: string;
|
|
14
|
+
gitPatch?: undefined;
|
|
15
|
+
}>;
|
|
16
|
+
//# 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":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAQhC,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,kBA0B5C,CAAC;AAEF,eAAO,MAAM,gCAAgC;cAKjC,MAAM;cACN,MAAM;kBACF,MAAM;;;;;;;;;EAsCrB,CAAC"}
|