@empiricalrun/test-gen 0.50.4 → 0.51.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 CHANGED
@@ -1,5 +1,19 @@
1
1
  # @empiricalrun/test-gen
2
2
 
3
+ ## 0.51.0
4
+
5
+ ### Minor Changes
6
+
7
+ - ac754ae: feat: enable disk persistence for chat state
8
+ - 561aa8e: feat: add usage summary (tokens, cost) for chat agent
9
+
10
+ ### Patch Changes
11
+
12
+ - 3e3d937: fix: add some validations for browser agent tool call
13
+ - Updated dependencies [ac754ae]
14
+ - Updated dependencies [561aa8e]
15
+ - @empiricalrun/llm@0.11.0
16
+
3
17
  ## 0.50.4
4
18
 
5
19
  ### Patch Changes
@@ -25,6 +25,7 @@ export declare function injectPwLocatorGenerator(page: Page): Promise<void>;
25
25
  * @return {*} {Promise<PlaywrightTestConfig>}
26
26
  */
27
27
  export declare function readPlaywrightConfig(repoDir: string): Promise<PlaywrightTestConfig>;
28
+ export declare function getValidProjectNames(playwrightConfig: PlaywrightTestConfig): Promise<string[]>;
28
29
  /**
29
30
  * detect the project name for the given file in playwright test repo
30
31
  * if project and test file path for running test don't match, then playwright throws error
@@ -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,iBAkBA;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;;;;;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;IAuBb,SAAS;CAKjB"}
@@ -3,7 +3,7 @@ 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.TeardownManager = exports.detectProjectName = exports.readPlaywrightConfig = exports.injectPwLocatorGenerator = exports.prepareFileForMasterAgent = exports.markTestAsOnly = exports.replaceTodoWithCreateTest = exports.prepareBrowsingAgentTask = exports.isRegExp = void 0;
6
+ exports.TeardownManager = exports.detectProjectName = exports.getValidProjectNames = exports.readPlaywrightConfig = exports.injectPwLocatorGenerator = exports.prepareFileForMasterAgent = exports.markTestAsOnly = exports.replaceTodoWithCreateTest = exports.prepareBrowsingAgentTask = exports.isRegExp = void 0;
7
7
  const fs_extra_1 = __importDefault(require("fs-extra"));
8
8
  const minimatch_1 = require("minimatch");
9
9
  const path_1 = __importDefault(require("path"));
@@ -92,7 +92,12 @@ async function replaceTodoWithCreateTest({ testFilePath, testCaseName, testCaseS
92
92
  // This method is an alternative to prepareFileForUpdateScenario
93
93
  // TODO: Does not support multiple pages, scoped variables, updates in POM files
94
94
  const fileContent = await fs_extra_1.default.readFile(testFilePath, "utf-8");
95
- await fs_extra_1.default.writeFile(testFilePath, fileContent.replace(/\/\/ TODO\(agent\): (.*)/, (_, todoText) => `await createTest("${todoText.replace(/"/g, '\\"')}", page);`));
95
+ const todoRegex = /\/\/ TODO\(agent\): (.*)/;
96
+ const todoMatch = fileContent.match(todoRegex);
97
+ if (!todoMatch) {
98
+ throw new Error(`No "// TODO(agent):" comment found in file: ${testFilePath}`);
99
+ }
100
+ await fs_extra_1.default.writeFile(testFilePath, fileContent.replace(todoRegex, (_, todoText) => `await createTest("${todoText.replace(/"/g, '\\"')}", page);`));
96
101
  await addImportForCreateTest(testFilePath);
97
102
  await markTestAsOnly({
98
103
  testCaseName,
@@ -302,6 +307,16 @@ function matchAgainstPattern(pattern, filePathToTest) {
302
307
  return (0, minimatch_1.minimatch)(filePathToTest, pattern);
303
308
  }
304
309
  }
310
+ async function getValidProjectNames(playwrightConfig) {
311
+ if (!playwrightConfig.projects) {
312
+ return [];
313
+ }
314
+ const filteredProjectNames = playwrightConfig.projects
315
+ .map((p) => p.name)
316
+ .filter((p) => !!p);
317
+ return filteredProjectNames;
318
+ }
319
+ exports.getValidProjectNames = getValidProjectNames;
305
320
  /**
306
321
  * detect the project name for the given file in playwright test repo
307
322
  * if project and test file path for running test don't match, then playwright throws error
@@ -1,8 +1,9 @@
1
- import { TraceClient } from "@empiricalrun/llm";
2
- import type { Anthropic } from "@empiricalrun/llm/claude";
3
- export declare function chatAgent({ prompt, chatModel, }: {
4
- prompt: string;
5
- trace?: TraceClient;
1
+ export declare function chatAgent({ chatModel, useDiskForChatState, }: {
6
2
  chatModel?: "claude-3-7-sonnet-20250219" | "claude-3-5-sonnet-20241022";
7
- }): Promise<Anthropic.Messages.MessageParam[]>;
3
+ useDiskForChatState?: boolean;
4
+ }): Promise<{
5
+ input: number;
6
+ output: number;
7
+ cost: number;
8
+ }>;
8
9
  //# sourceMappingURL=chat.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/agent/chat.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AA8E1D,wBAAsB,SAAS,CAAC,EAC9B,MAAM,EACN,SAAwC,GACzC,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,SAAS,CAAC,EAAE,4BAA4B,GAAG,4BAA4B,CAAC;CACzE,8CAiEA"}
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"}
@@ -71,12 +71,38 @@ const toolExecutors = {
71
71
  ...Object.fromEntries(tools.map((tool) => [tool.schema.name, tool.execute])),
72
72
  str_replace_editor: claude_1.strReplaceEditorTool,
73
73
  };
74
- async function chatAgent({ prompt, chatModel = "claude-3-7-sonnet-20250219", }) {
75
- let userPrompt = prompt;
76
- let chatState = new claude_1.ChatState();
77
- chatState.pushTextMessage({ message: { role: "user", content: userPrompt } });
78
- let shouldAskUserForInput = false;
79
- while (!userPrompt.toLowerCase().includes("stop")) {
74
+ async function chatAgent({ chatModel = "claude-3-7-sonnet-20250219", useDiskForChatState, }) {
75
+ let userPrompt = undefined;
76
+ let chatState = useDiskForChatState ? claude_1.ChatState.load() : new claude_1.ChatState(false);
77
+ if (chatState.askUserForInput) {
78
+ // Show last message to the user for context when we loaded from disk
79
+ const messages = chatState.messages;
80
+ const lastMessage = messages[messages.length - 1];
81
+ if (lastMessage && Array.isArray(lastMessage.content)) {
82
+ const textContent = lastMessage.content.find((b) => b.type === "text");
83
+ if (textContent) {
84
+ const role = lastMessage.role.charAt(0).toUpperCase() + lastMessage.role.slice(1);
85
+ console.log(`${role}: ${textContent.text}`);
86
+ }
87
+ }
88
+ }
89
+ while (!userPrompt?.toLowerCase().includes("stop")) {
90
+ chatState.saveToDisk();
91
+ if (chatState.askUserForInput) {
92
+ userPrompt = await human_in_the_loop_1.humanLoop.getFeedback({
93
+ message: "User:",
94
+ });
95
+ chatState.pushMessage({
96
+ role: "user",
97
+ content: [
98
+ {
99
+ type: "text",
100
+ text: userPrompt,
101
+ },
102
+ ],
103
+ });
104
+ continue;
105
+ }
80
106
  const toolUse = chatState.getPendingToolCall();
81
107
  if (toolUse) {
82
108
  console.log("Executing tool:", toolUse.name, "with args:", toolUse.input);
@@ -85,26 +111,22 @@ async function chatAgent({ prompt, chatModel = "claude-3-7-sonnet-20250219", })
85
111
  throw new Error(`Tool ${toolUse.name} not found`);
86
112
  }
87
113
  const toolResult = await toolExecutor(toolUse.input);
88
- chatState.pushToolResultToMessages({
89
- toolCall: toolUse,
90
- isError: toolResult.isError,
91
- result: toolResult.result,
114
+ chatState.pushMessage({
115
+ role: "user",
116
+ content: [
117
+ {
118
+ type: "tool_result",
119
+ tool_use_id: toolUse.id,
120
+ content: toolResult.result,
121
+ is_error: toolResult.isError,
122
+ },
123
+ ],
92
124
  });
93
125
  continue;
94
126
  }
95
- if (shouldAskUserForInput) {
96
- userPrompt = await human_in_the_loop_1.humanLoop.getFeedback({
97
- message: "Your response?",
98
- });
99
- chatState.pushTextMessage({
100
- message: { role: "user", content: userPrompt },
101
- });
102
- shouldAskUserForInput = false;
103
- continue;
104
- }
105
- const response = await (0, claude_1.createChatCompletion)({
127
+ const response = await (0, claude_1.createClaudeMessage)({
106
128
  systemPrompt,
107
- messages: chatState.getMessages(),
129
+ messages: chatState.getMessagesForCreateCompletion(),
108
130
  tools: tools.map((tool) => (0, claude_1.convertOpenAISchemaToAnthropic)((0, zod_schema_1.zodToOpenAITool)(tool.schema))),
109
131
  model: chatModel,
110
132
  withStrReplaceEditor: true,
@@ -112,19 +134,14 @@ async function chatAgent({ prompt, chatModel = "claude-3-7-sonnet-20250219", })
112
134
  if (!response) {
113
135
  throw new Error("No response from LLM");
114
136
  }
115
- chatState.pushTextMessage({
116
- message: { role: "assistant", content: response.content },
117
- });
137
+ chatState.pushMessage(response);
118
138
  const textBlock = response.content.find((b) => b.type === "text");
119
- const toolUseBlock = response.content.find((b) => b.type === "tool_use");
120
- console.log("Assistant response:", textBlock?.text);
121
- if (toolUseBlock) {
122
- chatState.addPendingToolCall({ toolCall: toolUseBlock });
123
- }
124
- else {
125
- shouldAskUserForInput = true;
139
+ if (textBlock) {
140
+ console.log("Assistant:", textBlock.text);
126
141
  }
127
142
  }
128
- return chatState.getMessages();
143
+ const usageSummary = chatState.getUsageSummary();
144
+ console.log("Usage summary:", usageSummary);
145
+ return usageSummary;
129
146
  }
130
147
  exports.chatAgent = chatAgent;
package/dist/bin/index.js CHANGED
@@ -32,7 +32,7 @@ process.on("beforeExit", async () => await flushEvents());
32
32
  process.on("exit", async () => await flushEvents());
33
33
  process.on("SIGINT", async () => await flushEvents());
34
34
  process.on("SIGTERM", async () => await flushEvents());
35
- async function runChatAgent(prompt, modelInput) {
35
+ async function runChatAgent(modelInput, useDiskForChatState) {
36
36
  const MODEL_MAPPING = {
37
37
  "claude-3-7": "claude-3-7-sonnet-20250219",
38
38
  "3-7": "claude-3-7-sonnet-20250219",
@@ -43,8 +43,8 @@ async function runChatAgent(prompt, modelInput) {
43
43
  throw new Error(`Invalid chat model: ${modelInput}`);
44
44
  }
45
45
  return await (0, chat_1.chatAgent)({
46
- prompt,
47
46
  chatModel: modelInput ? MODEL_MAPPING[modelInput] : undefined,
47
+ useDiskForChatState,
48
48
  });
49
49
  }
50
50
  async function runAgentsWorkflow(testGenConfig, testGenToken) {
@@ -181,6 +181,7 @@ async function runAgentsWorkflow(testGenConfig, testGenToken) {
181
181
  .option("--file <test-file>", "File path of the test case (inside tests dir)")
182
182
  .option("--suites <suites>", "Comma separated list of describe blocks")
183
183
  .option("--use-chat", "Use chat agent (and not the workflow)")
184
+ .option("--use-disk-for-chat-state", "Save and load chat state from disk")
184
185
  .option("--chat-model <model>", "Chat model to use (claude-3-7-sonnet-20250219 or claude-3-5-sonnet-20241022)")
185
186
  .parse(process.argv);
186
187
  const options = program.opts();
@@ -202,18 +203,16 @@ async function runAgentsWorkflow(testGenConfig, testGenToken) {
202
203
  generationId: testGenConfig.options?.metadata.generationId,
203
204
  projectRepoName: testGenConfig.options?.metadata.projectRepoName,
204
205
  });
205
- let testGenFailed = false;
206
- let agentUsed;
207
206
  // Download the build if repo has a download script
208
207
  await (0, test_build_1.downloadBuild)(testGenConfig.build || {});
208
+ if (completedOptions.useChat) {
209
+ await runChatAgent(completedOptions.chatModel, completedOptions.useDiskForChatState);
210
+ return;
211
+ }
212
+ let agentUsed;
213
+ let testGenFailed = false;
209
214
  try {
210
- if (completedOptions.useChat) {
211
- await runChatAgent(completedOptions.prompt, completedOptions.chatModel);
212
- return;
213
- }
214
- else {
215
- agentUsed = await runAgentsWorkflow(testGenConfig, testGenToken);
216
- }
215
+ agentUsed = await runAgentsWorkflow(testGenConfig, testGenToken);
217
216
  }
218
217
  catch (e) {
219
218
  testGenFailed = true;
@@ -5,6 +5,7 @@ export interface CliOptions {
5
5
  prompt?: string;
6
6
  suites?: string;
7
7
  useChat?: boolean;
8
+ useDiskForChatState?: boolean;
8
9
  chatModel?: "claude-3-7" | "3-7" | "claude-3-5" | "3-5" | "claude-3-7-sonnet-20250219" | "claude-3-5-sonnet-20241022";
9
10
  }
10
11
  export declare function validateAndCompleteCliOptions(options: CliOptions): Promise<CliOptions>;
@@ -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;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EACN,YAAY,GACZ,KAAK,GACL,YAAY,GACZ,KAAK,GACL,4BAA4B,GAC5B,4BAA4B,CAAC;CAClC;AAQD,wBAAsB,6BAA6B,CACjD,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,UAAU,CAAC,CAyDrB"}
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;IAClB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,SAAS,CAAC,EACN,YAAY,GACZ,KAAK,GACL,YAAY,GACZ,KAAK,GACL,4BAA4B,GAC5B,4BAA4B,CAAC;CAClC;AAQD,wBAAsB,6BAA6B,CACjD,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,UAAU,CAAC,CAyDrB"}
@@ -12,9 +12,9 @@ async function validateAndCompleteCliOptions(options) {
12
12
  return options;
13
13
  }
14
14
  let requiredFields = ["name", "file", "prompt"];
15
- // For new chat flow in local CLI usage, only prompt is required
16
15
  if (options.useChat) {
17
- requiredFields = ["prompt"];
16
+ // Chat agent can prompt the user directly, nothing is required in CLI args
17
+ requiredFields = [];
18
18
  }
19
19
  const questions = [];
20
20
  if (!options.name && requiredFields.includes("name")) {
@@ -1 +1 @@
1
- {"version":3,"file":"browser-agent.d.ts","sourceRoot":"","sources":["../../src/tools/browser-agent.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAmDpC,eAAO,MAAM,gBAAgB,EAAE,IA6C9B,CAAC"}
1
+ {"version":3,"file":"browser-agent.d.ts","sourceRoot":"","sources":["../../src/tools/browser-agent.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAmDpC,eAAO,MAAM,gBAAgB,EAAE,IA4D9B,CAAC"}
@@ -57,11 +57,27 @@ exports.browserAgentTool = {
57
57
  },
58
58
  execute: async (input) => {
59
59
  const { testName, testSuites, fileName, changeToMake, project } = input;
60
- await (0, utils_1.replaceTodoWithCreateTest)({
61
- testCaseName: testName,
62
- testCaseSuites: testSuites,
63
- testFilePath: fileName,
64
- });
60
+ try {
61
+ await (0, utils_1.replaceTodoWithCreateTest)({
62
+ testCaseName: testName,
63
+ testCaseSuites: testSuites,
64
+ testFilePath: fileName,
65
+ });
66
+ }
67
+ catch (error) {
68
+ return {
69
+ isError: true,
70
+ result: `Error running tool: ${error}`,
71
+ };
72
+ }
73
+ const playwrightConfig = await (0, utils_1.readPlaywrightConfig)(process.cwd());
74
+ const validProjectNames = await (0, utils_1.getValidProjectNames)(playwrightConfig);
75
+ if (!validProjectNames.includes(project)) {
76
+ return {
77
+ isError: true,
78
+ result: `Invalid project name: ${project}. Valid project names are: ${validProjectNames.join(", ")}`,
79
+ };
80
+ }
65
81
  const { isError, error } = await (0, run_1.generateTestsUsingMasterAgent)({
66
82
  testFilePath: fileName,
67
83
  filePathToUpdate: fileName,
@@ -1 +1 @@
1
- {"version":3,"file":"repo-tree.d.ts","sourceRoot":"","sources":["../../src/utils/repo-tree.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,eAAe,qBAO3B,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,UAsE9D"}
1
+ {"version":3,"file":"repo-tree.d.ts","sourceRoot":"","sources":["../../src/utils/repo-tree.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,eAAe,qBAQ3B,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,KAAK,UAsE9D"}
@@ -13,6 +13,7 @@ exports.DEFAULT_EXCLUDE = [
13
13
  /\.git/,
14
14
  ".DS_Store",
15
15
  "playwright-report",
16
+ ".empiricalrun",
16
17
  ];
17
18
  function generateAsciiTree(dirPath, options = {}) {
18
19
  const defaultOptions = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@empiricalrun/test-gen",
3
- "version": "0.50.4",
3
+ "version": "0.51.0",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"
@@ -73,7 +73,7 @@
73
73
  "tsx": "^4.16.2",
74
74
  "typescript": "^5.3.3",
75
75
  "zod": "^3.23.8",
76
- "@empiricalrun/llm": "^0.10.3",
76
+ "@empiricalrun/llm": "^0.11.0",
77
77
  "@empiricalrun/r2-uploader": "^0.3.8",
78
78
  "@empiricalrun/reporter": "^0.23.2",
79
79
  "@empiricalrun/test-run": "^0.7.5"