@empiricalrun/test-gen 0.51.0 → 0.51.1

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 CHANGED
@@ -1,5 +1,15 @@
1
1
  # @empiricalrun/test-gen
2
2
 
3
+ ## 0.51.1
4
+
5
+ ### Patch Changes
6
+
7
+ - d04190f: fix: remove process.on listeners to avoid leaks
8
+ - 75c7921: fix: show chat usage summary on ctrl+C
9
+ - Updated dependencies [d04190f]
10
+ - @empiricalrun/test-run@0.7.6
11
+ - @empiricalrun/llm@0.11.1
12
+
3
13
  ## 0.51.0
4
14
 
5
15
  ### Minor Changes
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/agent/browsing/run.ts"],"names":[],"mappings":"AAiBA,KAAK,iBAAiB,GAAG;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAsB,6BAA6B,CAAC,EAClD,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,OAAO,GACR,EAAE,iBAAiB;;;GA8EnB"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/agent/browsing/run.ts"],"names":[],"mappings":"AAiBA,KAAK,iBAAiB,GAAG;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAsB,6BAA6B,CAAC,EAClD,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,OAAO,GACR,EAAE,iBAAiB;;;GAgFnB"}
@@ -32,13 +32,14 @@ async function generateTestsUsingMasterAgent({ testFilePath, filePathToUpdate, p
32
32
  const testsDirectory = `${repoDir}/tests`;
33
33
  const isTestRunTriggeredForTeardown = teardownFileRegex.test(testFilePath);
34
34
  const teardowns = new utils_1.TeardownManager(testsDirectory);
35
- if (!isTestRunTriggeredForTeardown) {
36
- await teardowns.skipAll();
37
- }
35
+ let removeListeners;
38
36
  const command = `npx playwright test ${testFilePath} --retries 0 --project ${project} --timeout 0 --headed`;
39
37
  let isError = false;
40
38
  let error = "";
41
39
  try {
40
+ if (!isTestRunTriggeredForTeardown) {
41
+ removeListeners = await teardowns.skipAll();
42
+ }
42
43
  await (0, exec_1.cmd)(command.split(" "), {
43
44
  env: {
44
45
  APP_PORT: port.toString(),
@@ -55,7 +56,9 @@ async function generateTestsUsingMasterAgent({ testFilePath, filePathToUpdate, p
55
56
  console.error(error);
56
57
  isError = true;
57
58
  }
58
- if (!isTestRunTriggeredForTeardown) {
59
+ finally {
60
+ // Remove process listeners before unskipping files
61
+ removeListeners?.();
59
62
  teardowns.unskipAll();
60
63
  }
61
64
  // clean up the file if there is any error
@@ -39,7 +39,7 @@ export declare class TeardownManager {
39
39
  private teardownFiles;
40
40
  private getAllTeardownFiles;
41
41
  private skipTeardownFile;
42
- skipAll(): Promise<void>;
42
+ skipAll(): Promise<() => void>;
43
43
  unskipAll(): void;
44
44
  }
45
45
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/agent/browsing/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAe,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAIxE,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAsBvD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,MAAM,CAKhD;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,UAIvD;AAiFD,wBAAsB,yBAAyB,CAAC,EAC9C,YAAY,EACZ,YAAY,EACZ,cAAc,GACf,EAAE;IACD,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,iBAyBA;AAED,wBAAsB,cAAc,CAAC,EACnC,YAAY,EACZ,cAAc,EACd,QAAQ,GACT,EAAE;IACD,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;CAClB,iBAoBA;AAED,wBAAsB,yBAAyB,CAAC,EAC9C,QAAQ,EACR,QAAQ,EACR,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB,GAAG,OAAO,CAAC,MAAM,CAAC,CAyDlB;AAyBD,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,IAAI,iBA2HxD;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,oBAAoB,CAAC,CAM/B;AAWD,wBAAsB,oBAAoB,CACxC,gBAAgB,EAAE,oBAAoB,GACrC,OAAO,CAAC,MAAM,EAAE,CAAC,CAQnB;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,oBAAoB,EACtC,gBAAgB,GAAE,MAAM,EAAU,GACjC,OAAO,CAAC,MAAM,CAAC,CA+CjB;AAED,qBAAa,eAAe;IACd,OAAO,CAAC,SAAS;gBAAT,SAAS,EAAE,MAAM;IACrC,OAAO,CAAC,aAAa,CAAqB;YAE5B,mBAAmB;YAUnB,gBAAgB;IAsBjB,OAAO;IAuBb,SAAS;CAKjB"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/agent/browsing/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAe,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAIxE,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAsBvD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,MAAM,CAKhD;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,UAIvD;AAiFD,wBAAsB,yBAAyB,CAAC,EAC9C,YAAY,EACZ,YAAY,EACZ,cAAc,GACf,EAAE;IACD,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,iBAyBA;AAED,wBAAsB,cAAc,CAAC,EACnC,YAAY,EACZ,cAAc,EACd,QAAQ,GACT,EAAE;IACD,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;CAClB,iBAoBA;AAED,wBAAsB,yBAAyB,CAAC,EAC9C,QAAQ,EACR,QAAQ,EACR,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB,GAAG,OAAO,CAAC,MAAM,CAAC,CAyDlB;AAyBD,wBAAsB,wBAAwB,CAAC,IAAI,EAAE,IAAI,iBA2HxD;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,oBAAoB,CAAC,CAM/B;AAWD,wBAAsB,oBAAoB,CACxC,gBAAgB,EAAE,oBAAoB,GACrC,OAAO,CAAC,MAAM,EAAE,CAAC,CAQnB;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,MAAM,EACpB,gBAAgB,EAAE,oBAAoB,EACtC,gBAAgB,GAAE,MAAM,EAAU,GACjC,OAAO,CAAC,MAAM,CAAC,CA+CjB;AAED,qBAAa,eAAe;IACd,OAAO,CAAC,SAAS;gBAAT,SAAS,EAAE,MAAM;IACrC,OAAO,CAAC,aAAa,CAAqB;YAE5B,mBAAmB;YAUnB,gBAAgB;IAsBjB,OAAO;IAoBb,SAAS;CAKjB"}
@@ -400,18 +400,14 @@ class TeardownManager {
400
400
  async skipAll() {
401
401
  this.teardownFiles = await this.getAllTeardownFiles();
402
402
  await Promise.all(this.teardownFiles.map(async ({ filePath }) => await this.skipTeardownFile(filePath)));
403
- process.on("beforeExit", () => {
404
- this.unskipAll();
405
- });
406
- process.on("exit", () => {
407
- this.unskipAll();
408
- });
409
- process.on("SIGINT", () => {
410
- this.unskipAll();
411
- });
412
- process.on("SIGTERM", () => {
413
- this.unskipAll();
414
- });
403
+ const setupProcessListeners = (cleanup) => {
404
+ const events = ["beforeExit", "exit", "SIGINT", "SIGTERM"];
405
+ events.forEach((event) => process.on(event, cleanup));
406
+ return () => {
407
+ events.forEach((event) => process.removeListener(event, cleanup));
408
+ };
409
+ };
410
+ return setupProcessListeners(this.unskipAll.bind(this));
415
411
  }
416
412
  unskipAll() {
417
413
  this.teardownFiles.forEach(({ filePath, content }) => {
@@ -1 +1 @@
1
- {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/agent/chat.ts"],"names":[],"mappings":"AA8EA,wBAAsB,SAAS,CAAC,EAC9B,SAAwC,EACxC,mBAAmB,GACpB,EAAE;IACD,SAAS,CAAC,EAAE,4BAA4B,GAAG,4BAA4B,CAAC;IACxE,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;;;;GAoFA"}
1
+ {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/agent/chat.ts"],"names":[],"mappings":"AA8EA,wBAAsB,SAAS,CAAC,EAC9B,SAAwC,EACxC,mBAAmB,GACpB,EAAE;IACD,SAAS,CAAC,EAAE,4BAA4B,GAAG,4BAA4B,CAAC;IACxE,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;;;;GA6FA"}
@@ -89,9 +89,19 @@ async function chatAgent({ chatModel = "claude-3-7-sonnet-20250219", useDiskForC
89
89
  while (!userPrompt?.toLowerCase().includes("stop")) {
90
90
  chatState.saveToDisk();
91
91
  if (chatState.askUserForInput) {
92
- userPrompt = await human_in_the_loop_1.humanLoop.getFeedback({
93
- message: "User:",
94
- });
92
+ try {
93
+ userPrompt = await human_in_the_loop_1.humanLoop.getFeedback({
94
+ message: "User:",
95
+ });
96
+ }
97
+ catch (e) {
98
+ // https://github.com/SBoudrias/Inquirer.js/issues/1502#issuecomment-2275991680
99
+ if (e instanceof Error && e.name === "ExitPromptError") {
100
+ console.log("Exiting. Usage summary:", chatState.getUsageSummary());
101
+ process.exit(0);
102
+ }
103
+ throw e;
104
+ }
95
105
  chatState.pushMessage({
96
106
  role: "user",
97
107
  content: [
package/dist/bin/index.js CHANGED
@@ -28,10 +28,13 @@ dotenv_1.default.config({
28
28
  const flushEvents = async () => {
29
29
  await (0, llm_1.flushAllTraces)();
30
30
  };
31
- process.on("beforeExit", async () => await flushEvents());
32
- process.on("exit", async () => await flushEvents());
33
- process.on("SIGINT", async () => await flushEvents());
34
- process.on("SIGTERM", async () => await flushEvents());
31
+ function setupProcessListeners(cleanup) {
32
+ const events = ["beforeExit", "exit", "SIGINT", "SIGTERM"];
33
+ events.forEach((event) => process.on(event, cleanup));
34
+ return () => {
35
+ events.forEach((event) => process.removeListener(event, cleanup));
36
+ };
37
+ }
35
38
  async function runChatAgent(modelInput, useDiskForChatState) {
36
39
  const MODEL_MAPPING = {
37
40
  "claude-3-7": "claude-3-7-sonnet-20250219",
@@ -172,6 +175,7 @@ async function runAgentsWorkflow(testGenConfig, testGenToken) {
172
175
  return agent;
173
176
  }
174
177
  (async function main() {
178
+ const removeListeners = setupProcessListeners(flushEvents);
175
179
  console.log(`Running test-gen v${require("../../package.json").version} from ${__dirname}`);
176
180
  const program = new commander_1.Command();
177
181
  program
@@ -228,7 +232,7 @@ async function runAgentsWorkflow(testGenConfig, testGenToken) {
228
232
  testName: testGenConfig.testCase.name,
229
233
  });
230
234
  }
231
- // TODO: move these reporters to a better lifecycle
235
+ removeListeners();
232
236
  await (0, llm_1.flushAllTraces)();
233
237
  await (0, logger_1.waitForLogsToFlush)();
234
238
  await (0, session_1.endSession)();
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAOlC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAYpC,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,SAAS,iBAiC3E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAOlC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAepC,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,SAAS,iBAyC3E"}
package/dist/index.js CHANGED
@@ -14,42 +14,54 @@ const pw_test_1 = require("./utils/pw-test");
14
14
  const flushEvents = async () => {
15
15
  await (0, llm_1.flushAllTraces)();
16
16
  };
17
- process.on("beforeExit", async () => await flushEvents());
18
- process.on("exit", async () => await flushEvents());
19
- process.on("SIGINT", async () => await flushEvents());
20
- process.on("SIGTERM", async () => await flushEvents());
17
+ function setupProcessListeners(cleanup) {
18
+ const events = ["beforeExit", "exit", "SIGINT", "SIGTERM"];
19
+ events.forEach((event) => process.on(event, cleanup));
20
+ return () => {
21
+ events.forEach((event) => process.removeListener(event, cleanup));
22
+ };
23
+ }
21
24
  async function createTest(task, page, scope) {
22
- const testConfigArg = process.env.TEST_GEN_TOKEN;
23
- const testGenConfig = (0, scenarios_1.loadTestConfigs)(testConfigArg);
24
- (0, reporter_1.setReporterConfig)({
25
- projectRepoName: testGenConfig.options?.metadata.projectRepoName,
26
- testSessionId: testGenConfig.options?.metadata.testSessionId,
27
- generationId: testGenConfig.options?.metadata.generationId,
28
- });
29
- (0, session_1.setSessionDetails)({
30
- sessionId: testGenConfig.options?.metadata.testSessionId,
31
- generationId: testGenConfig.options?.metadata.generationId,
32
- testCaseId: testGenConfig.testCase.id,
33
- projectRepoName: testGenConfig.options?.metadata.projectRepoName,
34
- });
35
- const fileService = new client_1.default();
36
- const { testCase, specPath } = testGenConfig;
37
- const { code, importPaths } = await (0, run_1.createTestUsingMasterAgent)({
38
- testCase,
39
- specPath,
40
- page,
41
- task,
42
- options: {
43
- ...testGenConfig.options,
44
- },
45
- scopeVars: scope,
46
- });
47
- await fileService.updateTest({
48
- task,
49
- generatedCode: code,
50
- importPaths,
51
- });
52
- // skip the rest of the test once generation is over
53
- await (0, pw_test_1.skipTest)();
25
+ const removeListeners = setupProcessListeners(flushEvents);
26
+ try {
27
+ const testConfigArg = process.env.TEST_GEN_TOKEN;
28
+ const testGenConfig = (0, scenarios_1.loadTestConfigs)(testConfigArg);
29
+ (0, reporter_1.setReporterConfig)({
30
+ projectRepoName: testGenConfig.options?.metadata.projectRepoName,
31
+ testSessionId: testGenConfig.options?.metadata.testSessionId,
32
+ generationId: testGenConfig.options?.metadata.generationId,
33
+ });
34
+ (0, session_1.setSessionDetails)({
35
+ sessionId: testGenConfig.options?.metadata.testSessionId,
36
+ generationId: testGenConfig.options?.metadata.generationId,
37
+ testCaseId: testGenConfig.testCase.id,
38
+ projectRepoName: testGenConfig.options?.metadata.projectRepoName,
39
+ });
40
+ const fileService = new client_1.default();
41
+ const { testCase, specPath } = testGenConfig;
42
+ const { code, importPaths } = await (0, run_1.createTestUsingMasterAgent)({
43
+ testCase,
44
+ specPath,
45
+ page,
46
+ task,
47
+ options: {
48
+ ...testGenConfig.options,
49
+ },
50
+ scopeVars: scope,
51
+ });
52
+ await fileService.updateTest({
53
+ task,
54
+ generatedCode: code,
55
+ importPaths,
56
+ });
57
+ // skip the rest of the test once generation is over
58
+ await (0, pw_test_1.skipTest)();
59
+ }
60
+ finally {
61
+ // Ensure listeners are removed even if an error occurs
62
+ removeListeners();
63
+ // Flush events one final time before removing listeners
64
+ await flushEvents();
65
+ }
54
66
  }
55
67
  exports.createTest = createTest;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@empiricalrun/test-gen",
3
- "version": "0.51.0",
3
+ "version": "0.51.1",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"
@@ -73,10 +73,10 @@
73
73
  "tsx": "^4.16.2",
74
74
  "typescript": "^5.3.3",
75
75
  "zod": "^3.23.8",
76
- "@empiricalrun/llm": "^0.11.0",
76
+ "@empiricalrun/llm": "^0.11.1",
77
77
  "@empiricalrun/r2-uploader": "^0.3.8",
78
78
  "@empiricalrun/reporter": "^0.23.2",
79
- "@empiricalrun/test-run": "^0.7.5"
79
+ "@empiricalrun/test-run": "^0.7.6"
80
80
  },
81
81
  "devDependencies": {
82
82
  "@playwright/test": "1.47.1",