@empiricalrun/test-gen 0.59.0 → 0.61.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.
Files changed (41) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/agent/browsing/run.d.ts +7 -2
  3. package/dist/agent/browsing/run.d.ts.map +1 -1
  4. package/dist/agent/browsing/run.js +12 -9
  5. package/dist/agent/chat/agent-loop.d.ts.map +1 -1
  6. package/dist/agent/chat/agent-loop.js +19 -28
  7. package/dist/agent/chat/exports.d.ts +3 -3
  8. package/dist/agent/chat/exports.d.ts.map +1 -1
  9. package/dist/agent/chat/exports.js +2 -1
  10. package/dist/agent/chat/index.d.ts +2 -1
  11. package/dist/agent/chat/index.d.ts.map +1 -1
  12. package/dist/agent/chat/index.js +15 -6
  13. package/dist/agent/chat/prompt.d.ts.map +1 -1
  14. package/dist/agent/chat/prompt.js +58 -0
  15. package/dist/agent/chat/state.d.ts +23 -11
  16. package/dist/agent/chat/state.d.ts.map +1 -1
  17. package/dist/agent/chat/state.js +54 -12
  18. package/dist/agent/chat/types.d.ts +2 -2
  19. package/dist/agent/chat/types.d.ts.map +1 -1
  20. package/dist/agent/chat/utils.d.ts +14 -0
  21. package/dist/agent/chat/utils.d.ts.map +1 -0
  22. package/dist/agent/chat/utils.js +50 -0
  23. package/dist/bin/index.js +10 -4
  24. package/dist/bin/utils/index.d.ts +1 -1
  25. package/dist/bin/utils/index.d.ts.map +1 -1
  26. package/dist/bin/utils/platform/web/index.d.ts +4 -1
  27. package/dist/bin/utils/platform/web/index.d.ts.map +1 -1
  28. package/dist/bin/utils/platform/web/index.js +23 -8
  29. package/dist/tools/commit-and-create-pr.d.ts.map +1 -1
  30. package/dist/tools/commit-and-create-pr.js +5 -1
  31. package/dist/tools/str_replace_editor.d.ts.map +1 -1
  32. package/dist/tools/str_replace_editor.js +42 -15
  33. package/dist/tools/test-gen-browser.d.ts.map +1 -1
  34. package/dist/tools/test-gen-browser.js +18 -6
  35. package/dist/utils/git.d.ts.map +1 -1
  36. package/dist/utils/git.js +1 -1
  37. package/dist/utils/stripAnsi.d.ts +2 -0
  38. package/dist/utils/stripAnsi.d.ts.map +1 -0
  39. package/dist/utils/stripAnsi.js +9 -0
  40. package/package.json +5 -4
  41. package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,45 @@
1
1
  # @empiricalrun/test-gen
2
2
 
3
+ ## 0.61.0
4
+
5
+ ### Minor Changes
6
+
7
+ - fca6729: feat: implement TypeScript compiler execution and error handling in strReplaceEditor
8
+
9
+ ### Patch Changes
10
+
11
+ - f33bdbf: fix: git changed line should cover untracked also
12
+ - 1b4e3d0: fix: dont wait for fonts when agent needs screenshot
13
+ - bbf735a: chore: remove unused test.only cleaner
14
+ - b7a4821: fix: update pr tool prompt to encourage proactiveness
15
+ - 779dd6e: feat: add email automation recipe to system prompt
16
+ - 05f5184: fix: file create should create parent dir if required
17
+ - Updated dependencies [d71508f]
18
+ - Updated dependencies [79857b3]
19
+ - Updated dependencies [fca6729]
20
+ - @empiricalrun/test-run@0.9.2
21
+ - @empiricalrun/llm@0.16.1
22
+
23
+ ## 0.60.0
24
+
25
+ ### Minor Changes
26
+
27
+ - 296c662: feat: implemented check for tool call existence and tool result non existence for tool execution
28
+ - 255db12: feat: new linear client, Requests api routes, and fetch calls
29
+ - 8544d9d: feat: ChatStateError integration in ChatState for better error handling & retry
30
+
31
+ ### Patch Changes
32
+
33
+ - b183b76: fix: remove tsx config reader in test-gen tool call
34
+ - c4855ff: fix: file view tool does not read binary files
35
+ - f821310: fix: ensure all text editor tools use 1-indexed line numbers
36
+ - 06d3a2a: fix: skippped download build for failed build downloads
37
+ - cff296d: fix: wrap tsx playwright config reader in a try-catch
38
+ - 24d672a: feat: use playwright --list to get project names
39
+ - Updated dependencies [24d672a]
40
+ - @empiricalrun/test-run@0.9.1
41
+ - @empiricalrun/llm@0.16.0
42
+
3
43
  ## 0.59.0
4
44
 
5
45
  ### Minor Changes
@@ -3,13 +3,18 @@ type GenerateTestsType = {
3
3
  testCaseSuites: string[];
4
4
  testFilePath: string;
5
5
  filePathToUpdate: string;
6
- pwProjectsFilter: string[];
6
+ projectName: string;
7
7
  testGenToken: string;
8
8
  repoDir: string;
9
9
  traceId?: string;
10
10
  editFileWithGeneratedCode: boolean;
11
11
  };
12
- export declare function generateTestsUsingMasterAgent({ testCaseName, testCaseSuites, testFilePath, filePathToUpdate, pwProjectsFilter, testGenToken, repoDir, traceId, editFileWithGeneratedCode, }: GenerateTestsType): Promise<{
12
+ export declare function convertProjectsFilterToProject({ pwProjectsFilter, repoDir, testFilePath, }: {
13
+ pwProjectsFilter: string[];
14
+ repoDir: string;
15
+ testFilePath: string;
16
+ }): Promise<string>;
17
+ export declare function generateTestsUsingMasterAgent({ testCaseName, testCaseSuites, testFilePath, filePathToUpdate, projectName, testGenToken, repoDir, traceId, editFileWithGeneratedCode, }: GenerateTestsType): Promise<{
13
18
  isError: boolean;
14
19
  error: string;
15
20
  actionsSummary?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/agent/browsing/run.ts"],"names":[],"mappings":"AAcA,KAAK,iBAAiB,GAAG;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,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;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yBAAyB,EAAE,OAAO,CAAC;CACpC,CAAC;AAEF,wBAAsB,6BAA6B,CAAC,EAClD,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,OAAO,EACP,OAAO,EACP,yBAAyB,GAC1B,EAAE,iBAAiB,GAAG,OAAO,CAAC;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC,CAsFD"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/agent/browsing/run.ts"],"names":[],"mappings":"AAaA,KAAK,iBAAiB,GAAG;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yBAAyB,EAAE,OAAO,CAAC;CACpC,CAAC;AAEF,wBAAsB,8BAA8B,CAAC,EACnD,gBAAgB,EAChB,OAAO,EACP,YAAY,GACb,EAAE;IACD,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC,MAAM,CAAC,CAQlB;AAED,wBAAsB,6BAA6B,CAAC,EAClD,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,OAAO,EACP,OAAO,EACP,yBAAyB,GAC1B,EAAE,iBAAiB,GAAG,OAAO,CAAC;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC,CAkFD"}
@@ -3,6 +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.convertProjectsFilterToProject = convertProjectsFilterToProject;
6
7
  exports.generateTestsUsingMasterAgent = generateTestsUsingMasterAgent;
7
8
  const test_run_1 = require("@empiricalrun/test-run");
8
9
  const detect_port_1 = __importDefault(require("detect-port"));
@@ -11,7 +12,12 @@ const web_1 = require("../../bin/utils/platform/web");
11
12
  const server_1 = require("../../file/server");
12
13
  const exec_1 = require("../../utils/exec");
13
14
  const utils_1 = require("./utils");
14
- async function generateTestsUsingMasterAgent({ testCaseName, testCaseSuites, testFilePath, filePathToUpdate, pwProjectsFilter, testGenToken, repoDir, traceId, editFileWithGeneratedCode, }) {
15
+ async function convertProjectsFilterToProject({ pwProjectsFilter, repoDir, testFilePath, }) {
16
+ const playwrightConfig = await (0, utils_1.readPlaywrightConfig)(repoDir);
17
+ const project = await (0, utils_1.detectProjectName)(testFilePath, playwrightConfig, pwProjectsFilter);
18
+ return project;
19
+ }
20
+ async function generateTestsUsingMasterAgent({ testCaseName, testCaseSuites, testFilePath, filePathToUpdate, projectName, testGenToken, repoDir, traceId, editFileWithGeneratedCode, }) {
15
21
  if (!fs_1.default.existsSync(testFilePath)) {
16
22
  throw new Error(`File for master agent to run not found: ${testFilePath}`);
17
23
  }
@@ -27,12 +33,7 @@ async function generateTestsUsingMasterAgent({ testCaseName, testCaseSuites, tes
27
33
  });
28
34
  await fileServer.startFileService();
29
35
  fileServer.setFilePath(filePathToUpdate);
30
- // read playwright config from ./playwright.config.ts of source repo
31
- const playwrightConfig = await (0, utils_1.readPlaywrightConfig)(repoDir);
32
- // detect the playwright project name for the given test file and playwright config
33
- const project = await (0, utils_1.detectProjectName)(testFilePath, playwrightConfig, pwProjectsFilter);
34
36
  const pageVar = await (0, web_1.getPageVariableNameFromCreateTest)(filePathToUpdate);
35
- console.log(`Detected playwright project name: ${project}`);
36
37
  const testsDir = "tests";
37
38
  const cmd = await (0, test_run_1.runSpecificTestsCmd)({
38
39
  tests: [
@@ -43,13 +44,17 @@ async function generateTestsUsingMasterAgent({ testCaseName, testCaseSuites, tes
43
44
  suites: testCaseSuites,
44
45
  },
45
46
  ],
46
- projects: [project],
47
+ projects: [projectName],
47
48
  passthroughArgs: "--retries 0 --timeout 0",
49
+ envOverrides: {
50
+ PW_TEST_SCREENSHOT_NO_FONTS_READY: "1",
51
+ },
48
52
  //@ts-ignore
49
53
  platform: "web",
50
54
  });
51
55
  let error = undefined;
52
56
  try {
57
+ console.log(`[generateTestsUsingMasterAgent] Running command: ${cmd.command} ${cmd.args.join(" ")}`);
53
58
  await pm.execute(cmd.command, cmd.args, {
54
59
  env: {
55
60
  IPC_FILE_SERVICE_PORT: availablePort.toString(),
@@ -77,8 +82,6 @@ async function generateTestsUsingMasterAgent({ testCaseName, testCaseSuites, tes
77
82
  console.error("Failed to remove extra scripts from files post test gen error", e);
78
83
  }
79
84
  }
80
- // remove the test only from the file
81
- await (0, web_1.removeTestOnly)(testFilePath);
82
85
  await fileServer.stop();
83
86
  return {
84
87
  isError: !!error,
@@ -1 +1 @@
1
- {"version":3,"file":"agent-loop.d.ts","sourceRoot":"","sources":["../../../src/agent/chat/agent-loop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAEL,UAAU,EACV,mBAAmB,EAEpB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AA0B3C,wBAAsB,aAAa,CAAC,EAClC,SAAS,EACT,aAAa,EACb,QAAQ,EACR,KAAK,EACL,eAAe,EACf,QAAQ,EACR,qBAAqB,GACtB,EAAE;IACD,SAAS,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;IAC3B,aAAa,EAAE,mBAAmB,CAAC;IACnC,eAAe,EAAE,eAAe,CAAC;IACjC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC;IACnB,qBAAqB,EAAE,OAAO,CAAC;CAChC,iBAuCA"}
1
+ {"version":3,"file":"agent-loop.d.ts","sourceRoot":"","sources":["../../../src/agent/chat/agent-loop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EACL,UAAU,EACV,mBAAmB,EAEpB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAG3C,wBAAsB,aAAa,CAAC,EAClC,SAAS,EACT,aAAa,EACb,QAAQ,EACR,KAAK,EACL,eAAe,EACf,QAAQ,EACR,qBAAqB,GACtB,EAAE;IACD,SAAS,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;IAC3B,aAAa,EAAE,mBAAmB,CAAC;IACnC,eAAe,EAAE,eAAe,CAAC;IACjC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC;IACnB,qBAAqB,EAAE,OAAO,CAAC;CAChC,iBAqDA"}
@@ -2,30 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.chatAgentLoop = chatAgentLoop;
4
4
  const chat_1 = require("@empiricalrun/llm/chat");
5
- const picocolors_1 = require("picocolors");
6
5
  const prompt_1 = require("./prompt");
7
6
  const state_1 = require("./state");
8
- function getModelName(model) {
9
- const provider = (0, chat_1.getProviderForModel)(model);
10
- if (provider === "claude")
11
- return "Claude";
12
- if (provider === "google")
13
- return "Gemini";
14
- if (provider === "openai")
15
- return "o4";
16
- return "AI";
17
- }
18
- const log = (...args) => {
19
- console.log((0, picocolors_1.gray)(args.join(" ")));
20
- };
21
- function logError(context, error, trace) {
22
- console.error((0, picocolors_1.gray)(`[Error in ${context}]:`), error instanceof Error ? error.stack || error.message : error);
23
- trace?.update({
24
- output: {
25
- error: error instanceof Error ? error.message : String(error),
26
- },
27
- });
28
- }
7
+ const utils_1 = require("./utils");
29
8
  async function chatAgentLoop({ chatModel, selectedModel, reporter, trace, toolCallService, fileInfo, isToolExecutionRemote, }) {
30
9
  const systemPrompt = await (0, prompt_1.buildSystemPrompt)(fileInfo);
31
10
  trace?.update({ input: { systemPrompt } });
@@ -36,7 +15,7 @@ async function chatAgentLoop({ chatModel, selectedModel, reporter, trace, toolCa
36
15
  if (toolCalls.length) {
37
16
  if (isToolExecutionRemote) {
38
17
  await toolCallService.sendToQueue(toolCalls);
39
- log(`Tool call remote execution in progress`);
18
+ (0, utils_1.log)(`Tool call remote execution in progress`);
40
19
  break;
41
20
  }
42
21
  else {
@@ -44,22 +23,34 @@ async function chatAgentLoop({ chatModel, selectedModel, reporter, trace, toolCa
44
23
  chatModel.pushToolResultsMessage(toolCalls, toolResults);
45
24
  }
46
25
  }
47
- log(`${getModelName(selectedModel)} is working...`);
48
- const response = await chatModel.getLLMResponse({
26
+ (0, utils_1.log)(`${(0, utils_1.getModelName)(selectedModel)} is working...`);
27
+ let response = null;
28
+ response = await chatModel.getLLMResponse({
49
29
  systemPrompt,
50
30
  tools: tools.map((tool) => (0, chat_1.zodToOpenAITool)(tool.schema)),
51
31
  selectedModel,
52
32
  trace,
53
33
  });
54
34
  if (!response) {
55
- throw new Error("No response from LLM");
35
+ throw new Error("Error getting response from LLM");
56
36
  }
57
37
  chatModel.pushMessage(response);
58
38
  const latest = chatModel.getHumanReadableLatestMessage();
59
- await reporter((0, state_1.chatStateFromModel)(chatModel, selectedModel), latest);
39
+ await reporter((0, state_1.chatStateFromModel)({
40
+ chatModel,
41
+ selectedModel,
42
+ error: null,
43
+ }), latest);
60
44
  }
61
45
  catch (error) {
62
- logError("chatAgentLoop", error, trace);
46
+ await (0, utils_1.handleAgentError)({
47
+ context: "chatAgentLoop",
48
+ error,
49
+ chatModel,
50
+ selectedModel,
51
+ reporter,
52
+ trace,
53
+ });
63
54
  throw error;
64
55
  }
65
56
  }
@@ -2,8 +2,8 @@ import { createChatModel, IChatModel } from "@empiricalrun/llm/chat";
2
2
  import { FileInfo } from "../../types";
3
3
  import { chatAgentLoop } from "./agent-loop";
4
4
  import { defaultModel, SUPPORTED_CHAT_MODELS, SupportedChatModels } from "./models";
5
- import { CHAT_STATE_VERSIONS_MIGRATIONS_MAP, chatStateFromModel, ChatStateOnDisk, createChatState, createChatStateForMessages, getLatestDownloadBuildUrl, LATEST_CHAT_STATE_VERSION, migrateChatState } from "./state";
5
+ import { CHAT_STATE_VERSIONS_MIGRATIONS_MAP, chatStateFromModel, createChatState, createChatStateForMessages, fetchToolCallAvailability, getLatestDownloadBuildUrl, LATEST_CHAT_STATE_VERSION, migrateChatState } from "./state";
6
6
  import { ReporterFunction } from "./types";
7
- export { CHAT_STATE_VERSIONS_MIGRATIONS_MAP, chatAgentLoop, chatStateFromModel, createChatModel, createChatState, createChatStateForMessages, defaultModel, getLatestDownloadBuildUrl, LATEST_CHAT_STATE_VERSION, migrateChatState, SUPPORTED_CHAT_MODELS, };
8
- export type { ChatStateOnDisk, FileInfo, IChatModel, ReporterFunction, SupportedChatModels, };
7
+ export { CHAT_STATE_VERSIONS_MIGRATIONS_MAP, chatAgentLoop, chatStateFromModel, createChatModel, createChatState, createChatStateForMessages, defaultModel, fetchToolCallAvailability, getLatestDownloadBuildUrl, LATEST_CHAT_STATE_VERSION, migrateChatState, SUPPORTED_CHAT_MODELS, };
8
+ export type { FileInfo, IChatModel, ReporterFunction, SupportedChatModels };
9
9
  //# sourceMappingURL=exports.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"exports.d.ts","sourceRoot":"","sources":["../../../src/agent/chat/exports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAErE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EACL,YAAY,EACZ,qBAAqB,EACrB,mBAAmB,EACpB,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,kCAAkC,EAClC,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,0BAA0B,EAC1B,yBAAyB,EACzB,yBAAyB,EACzB,gBAAgB,EACjB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE3C,OAAO,EACL,kCAAkC,EAClC,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,0BAA0B,EAC1B,YAAY,EACZ,yBAAyB,EACzB,yBAAyB,EACzB,gBAAgB,EAChB,qBAAqB,GACtB,CAAC;AAEF,YAAY,EACV,eAAe,EACf,QAAQ,EACR,UAAU,EACV,gBAAgB,EAChB,mBAAmB,GACpB,CAAC"}
1
+ {"version":3,"file":"exports.d.ts","sourceRoot":"","sources":["../../../src/agent/chat/exports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAErE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EACL,YAAY,EACZ,qBAAqB,EACrB,mBAAmB,EACpB,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,kCAAkC,EAClC,kBAAkB,EAClB,eAAe,EACf,0BAA0B,EAC1B,yBAAyB,EACzB,yBAAyB,EACzB,yBAAyB,EACzB,gBAAgB,EACjB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE3C,OAAO,EACL,kCAAkC,EAClC,aAAa,EACb,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,0BAA0B,EAC1B,YAAY,EACZ,yBAAyB,EACzB,yBAAyB,EACzB,yBAAyB,EACzB,gBAAgB,EAChB,qBAAqB,GACtB,CAAC;AAEF,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,CAAC"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SUPPORTED_CHAT_MODELS = exports.migrateChatState = exports.LATEST_CHAT_STATE_VERSION = exports.getLatestDownloadBuildUrl = exports.defaultModel = exports.createChatStateForMessages = exports.createChatState = exports.createChatModel = exports.chatStateFromModel = exports.chatAgentLoop = exports.CHAT_STATE_VERSIONS_MIGRATIONS_MAP = void 0;
3
+ exports.SUPPORTED_CHAT_MODELS = exports.migrateChatState = exports.LATEST_CHAT_STATE_VERSION = exports.getLatestDownloadBuildUrl = exports.fetchToolCallAvailability = exports.defaultModel = exports.createChatStateForMessages = exports.createChatState = exports.createChatModel = exports.chatStateFromModel = exports.chatAgentLoop = exports.CHAT_STATE_VERSIONS_MIGRATIONS_MAP = void 0;
4
4
  const chat_1 = require("@empiricalrun/llm/chat");
5
5
  Object.defineProperty(exports, "createChatModel", { enumerable: true, get: function () { return chat_1.createChatModel; } });
6
6
  const agent_loop_1 = require("./agent-loop");
@@ -13,6 +13,7 @@ Object.defineProperty(exports, "CHAT_STATE_VERSIONS_MIGRATIONS_MAP", { enumerabl
13
13
  Object.defineProperty(exports, "chatStateFromModel", { enumerable: true, get: function () { return state_1.chatStateFromModel; } });
14
14
  Object.defineProperty(exports, "createChatState", { enumerable: true, get: function () { return state_1.createChatState; } });
15
15
  Object.defineProperty(exports, "createChatStateForMessages", { enumerable: true, get: function () { return state_1.createChatStateForMessages; } });
16
+ Object.defineProperty(exports, "fetchToolCallAvailability", { enumerable: true, get: function () { return state_1.fetchToolCallAvailability; } });
16
17
  Object.defineProperty(exports, "getLatestDownloadBuildUrl", { enumerable: true, get: function () { return state_1.getLatestDownloadBuildUrl; } });
17
18
  Object.defineProperty(exports, "LATEST_CHAT_STATE_VERSION", { enumerable: true, get: function () { return state_1.LATEST_CHAT_STATE_VERSION; } });
18
19
  Object.defineProperty(exports, "migrateChatState", { enumerable: true, get: function () { return state_1.migrateChatState; } });
@@ -1,8 +1,9 @@
1
1
  import { SupportedChatModels } from "@empiricalrun/llm/chat";
2
- export declare function runChatAgentForCLI({ useDiskForChatState, selectedModel, initialPromptContent, }: {
2
+ export declare function runChatAgentForCLI({ useDiskForChatState, selectedModel, initialPromptContent, withRetry, }: {
3
3
  selectedModel: SupportedChatModels;
4
4
  useDiskForChatState: boolean;
5
5
  initialPromptContent: string | undefined;
6
+ withRetry?: boolean;
6
7
  }): Promise<void>;
7
8
  export declare function runChatAgentForDashboard({ chatSessionId, selectedModel, }: {
8
9
  selectedModel: SupportedChatModels;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/chat/index.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,mBAAmB,EACpB,MAAM,wBAAwB,CAAC;AAmChC,wBAAsB,kBAAkB,CAAC,EACvC,mBAAmB,EACnB,aAAa,EACb,oBAAoB,GACrB,EAAE;IACD,aAAa,EAAE,mBAAmB,CAAC;IACnC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,oBAAoB,EAAE,MAAM,GAAG,SAAS,CAAC;CAC1C,iBAiGA;AAuBD,wBAAsB,wBAAwB,CAAC,EAC7C,aAAa,EACb,aAAa,GACd,EAAE;IACD,aAAa,EAAE,mBAAmB,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;CACvB,iBAsDA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/chat/index.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,mBAAmB,EACpB,MAAM,wBAAwB,CAAC;AAyChC,wBAAsB,kBAAkB,CAAC,EACvC,mBAAmB,EACnB,aAAa,EACb,oBAAoB,EACpB,SAAS,GACV,EAAE;IACD,aAAa,EAAE,mBAAmB,CAAC;IACnC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,oBAAoB,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,iBAgHA;AAuBD,wBAAsB,wBAAwB,CAAC,EAC7C,aAAa,EACb,aAAa,GACd,EAAE;IACD,aAAa,EAAE,mBAAmB,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;CACvB,iBAsDA"}
@@ -15,13 +15,13 @@ const DASHBOARD_DOMAIN = process.env.DASHBOARD_DOMAIN || "https://dash.empirical
15
15
  function stopCriteria(userPrompt) {
16
16
  return userPrompt?.toLowerCase() === "stop";
17
17
  }
18
- function concludeAgent(chatModel, useDiskForChatState, selectedModel) {
18
+ function concludeAgent(chatModel, useDiskForChatState, selectedModel, error) {
19
19
  console.log(`\n${(0, picocolors_1.gray)("Usage summary -> " + chatModel.getUsageSummary())}`);
20
20
  if (useDiskForChatState) {
21
- (0, state_1.saveToDisk)(chatModel.messages, selectedModel, chatModel.askUserForInput);
21
+ (0, state_1.saveToDisk)(chatModel.messages, selectedModel, chatModel.askUserForInput, error);
22
22
  }
23
23
  }
24
- async function runChatAgentForCLI({ useDiskForChatState, selectedModel, initialPromptContent, }) {
24
+ async function runChatAgentForCLI({ useDiskForChatState, selectedModel, initialPromptContent, withRetry, }) {
25
25
  let chatState;
26
26
  if (useDiskForChatState) {
27
27
  chatState = (0, state_1.loadChatState)();
@@ -46,8 +46,12 @@ async function runChatAgentForCLI({ useDiskForChatState, selectedModel, initialP
46
46
  console.log(`${(0, picocolors_1.blue)(latest.role)}: ${latest.textMessage}`);
47
47
  }
48
48
  }
49
+ // if withRetry set the chatState error null
50
+ if (withRetry && chatState) {
51
+ chatState.error = null;
52
+ }
49
53
  const handleSigInt = () => {
50
- concludeAgent(chatModel, useDiskForChatState, selectedModel);
54
+ concludeAgent(chatModel, useDiskForChatState, selectedModel, null);
51
55
  process.exit(0);
52
56
  };
53
57
  process.once("SIGINT", handleSigInt);
@@ -55,7 +59,7 @@ async function runChatAgentForCLI({ useDiskForChatState, selectedModel, initialP
55
59
  let userPrompt;
56
60
  let reporterFunc = async (chatState, latest) => {
57
61
  if (useDiskForChatState) {
58
- (0, state_1.saveToDisk)(chatState.messages, selectedModel, chatState.askUserForInput);
62
+ (0, state_1.saveToDisk)(chatState.messages, selectedModel, chatState.askUserForInput, chatState.error);
59
63
  }
60
64
  if (latest) {
61
65
  console.log(`${(0, picocolors_1.blue)(latest.role)}: ${latest.textMessage}`);
@@ -80,9 +84,14 @@ async function runChatAgentForCLI({ useDiskForChatState, selectedModel, initialP
80
84
  catch (e) {
81
85
  // https://github.com/SBoudrias/Inquirer.js/issues/1502#issuecomment-2275991680
82
86
  if (e instanceof Error && e.name === "ExitPromptError") {
83
- concludeAgent(chatModel, useDiskForChatState, selectedModel);
87
+ concludeAgent(chatModel, useDiskForChatState, selectedModel, null);
84
88
  process.exit(0);
85
89
  }
90
+ concludeAgent(chatModel, useDiskForChatState, selectedModel, {
91
+ message: e.message,
92
+ stack: e.stack || "Stack trace not available",
93
+ timestamp: new Date().toISOString(),
94
+ });
86
95
  throw e;
87
96
  }
88
97
  if (!stopCriteria(userPrompt)) {
@@ -1 +1 @@
1
- {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../../src/agent/chat/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,mBAiGzD"}
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../../src/agent/chat/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAuDvC,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,mBAwGzD"}
@@ -2,6 +2,57 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildSystemPrompt = buildSystemPrompt;
4
4
  const repo_1 = require("./repo");
5
+ const emailRecipe = `
6
+ # Email automation
7
+
8
+ ## Example usage
9
+
10
+ ### Dynamic email
11
+
12
+ This dynamically generates a random email address that can
13
+ be used for the test (e.g. invite a new user).
14
+
15
+ \`\`\`ts
16
+ import { EmailClient } from "@empiricalrun/playwright-utils";
17
+ import { expect } from "@playwright/test";
18
+
19
+ const client = new EmailClient();
20
+ const address = client.getAddress();
21
+
22
+ // Input the \`address\` in the application
23
+ // that sends the email.
24
+
25
+ // Get email received on the \`address\`
26
+ const email = await client.waitForEmail();
27
+ expect(
28
+ email.links.find((l) => l.text === "Join your team")
29
+ ).toBeTruthy();
30
+ \`\`\`
31
+
32
+ ### Static email
33
+
34
+ This uses a known (static) email that can be used to login
35
+ into an application.
36
+
37
+ This needs an email id (e.g. \`test-login-user\`). The email id
38
+ is appended with the domain (managed internally) to get the full
39
+ email address.
40
+
41
+ \`\`\`ts
42
+ import { EmailClient } from "@empiricalrun/playwright-utils";
43
+
44
+ const emailId = \`test-login-user\`;
45
+
46
+ const client = new EmailClient({ emailId });
47
+ const address = client.getAddress(); // Returns full address with domain
48
+
49
+ // Get email received on the \`address\`
50
+ const email = await client.waitForEmail();
51
+
52
+ // Get login OTP
53
+ const loginCode = email.codes[0];
54
+ \`\`\`
55
+ `;
5
56
  async function buildSystemPrompt(fileInfo) {
6
57
  const repoContext = await (0, repo_1.getRepoInfoPrompt)(fileInfo);
7
58
  return `
@@ -96,6 +147,13 @@ if (await saveButton.isVisible()) {
96
147
  }
97
148
  \`\`\`
98
149
 
150
+ # Recipes
151
+ You can refer to the following recipes to learn how to write tests for different scenarios.
152
+
153
+ <email-automation>
154
+ ${emailRecipe}
155
+ </email-automation>
156
+
99
157
  # Repo context
100
158
  ${repoContext}
101
159
  `;
@@ -1,23 +1,35 @@
1
1
  import { IChatModel, SupportedChatModels } from "@empiricalrun/llm/chat";
2
- import { CanonicalMessage, ChatState } from "@empiricalrun/shared-types";
2
+ import { CanonicalMessage, ChatState, ChatStateError } from "@empiricalrun/shared-types";
3
3
  export declare const CHAT_STATE_VERSIONS_MIGRATIONS_MAP: Record<string, (state: any) => any>;
4
4
  export declare const LATEST_CHAT_STATE_VERSION = "0.1";
5
5
  export declare const CHAT_STATE_PATH: string;
6
- export type ChatStateOnDisk<T> = {
7
- version: string;
8
- model: SupportedChatModels;
9
- messages: T[];
6
+ export declare function createChatState({ userPrompt, existingState, selectedModel, error, }: {
7
+ userPrompt: string | undefined;
8
+ existingState: ChatState | undefined;
9
+ selectedModel: SupportedChatModels;
10
+ error: ChatStateError | null;
11
+ }): ChatState;
12
+ export declare function createChatStateForMessages({ messages, selectedModel, askUserForInput, error, }: {
13
+ messages: any;
14
+ selectedModel: SupportedChatModels;
10
15
  askUserForInput: boolean;
11
- };
12
- export declare function createChatState(userPrompt: string | undefined, existingState: ChatStateOnDisk<any> | undefined, selectedModel: SupportedChatModels): ChatStateOnDisk<unknown>;
13
- export declare function createChatStateForMessages<T>(messages: any, selectedModel: SupportedChatModels, askUserForInput: boolean): ChatStateOnDisk<T>;
14
- export declare function chatStateFromModel<T>(chatModel: IChatModel<T>, selectedModel: SupportedChatModels): ChatStateOnDisk<unknown>;
16
+ error: ChatStateError | null;
17
+ }): ChatState;
18
+ export declare function chatStateFromModel<T>({ chatModel, selectedModel, error, }: {
19
+ chatModel: IChatModel<T>;
20
+ selectedModel: SupportedChatModels;
21
+ error: ChatStateError | null;
22
+ }): ChatState;
15
23
  export declare function loadChatState(): ChatState | undefined;
16
24
  /**
17
25
  * Migrates a chat state object from an old version to the latest version.
18
26
  * Add migration logic for each version as needed.
19
27
  */
20
- export declare function migrateChatState<T = any>(oldState: any): ChatStateOnDisk<T>;
21
- export declare function saveToDisk<T>(messages: Array<T>, selectedModel: SupportedChatModels, askUserForInput: boolean): void;
28
+ export declare function migrateChatState(oldState: any): ChatState;
29
+ export declare function saveToDisk<T>(messages: Array<T>, selectedModel: SupportedChatModels, askUserForInput: boolean, error: ChatStateError | null): void;
22
30
  export declare function getLatestDownloadBuildUrl(messages: CanonicalMessage[]): string | null;
31
+ export declare function fetchToolCallAvailability(toolRequestId: String, messages: CanonicalMessage[]): {
32
+ hasToolRequest: boolean;
33
+ hasToolResponse: boolean;
34
+ };
23
35
  //# sourceMappingURL=state.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/agent/chat/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,UAAU,EACV,mBAAmB,EACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AA+BzE,eAAO,MAAM,kCAAkC,EAAE,MAAM,CACrD,MAAM,EACN,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,CAIpB,CAAC;AAEF,eAAO,MAAM,yBAAyB,QAAQ,CAAC;AAE/C,eAAO,MAAM,eAAe,QAI3B,CAAC;AAEF,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,mBAAmB,CAAC;IAC3B,QAAQ,EAAE,CAAC,EAAE,CAAC;IACd,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,aAAa,EAAE,eAAe,CAAC,GAAG,CAAC,GAAG,SAAS,EAC/C,aAAa,EAAE,mBAAmB,4BAYnC;AAED,wBAAgB,0BAA0B,CAAC,CAAC,EAC1C,QAAQ,EAAE,GAAG,EACb,aAAa,EAAE,mBAAmB,EAClC,eAAe,EAAE,OAAO,GACvB,eAAe,CAAC,CAAC,CAAC,CAQpB;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,EACxB,aAAa,EAAE,mBAAmB,4BAOnC;AAED,wBAAgB,aAAa,IAAI,SAAS,GAAG,SAAS,CAarD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,GAAG,GAAG,EAAE,QAAQ,EAAE,GAAG,GAAG,eAAe,CAAC,CAAC,CAAC,CAqB3E;AAED,wBAAgB,UAAU,CAAC,CAAC,EAC1B,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,EAClB,aAAa,EAAE,mBAAmB,EAClC,eAAe,EAAE,OAAO,QAezB;AAED,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,gBAAgB,EAAE,GAC3B,MAAM,GAAG,IAAI,CAqBf"}
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../src/agent/chat/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,UAAU,EACV,mBAAmB,EACpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,gBAAgB,EAChB,SAAS,EACT,cAAc,EACf,MAAM,4BAA4B,CAAC;AA+BpC,eAAO,MAAM,kCAAkC,EAAE,MAAM,CACrD,MAAM,EACN,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,CAIpB,CAAC;AAEF,eAAO,MAAM,yBAAyB,QAAQ,CAAC;AAE/C,eAAO,MAAM,eAAe,QAI3B,CAAC;AAEF,wBAAgB,eAAe,CAAC,EAC9B,UAAU,EACV,aAAa,EACb,aAAa,EACb,KAAK,GACN,EAAE;IACD,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,aAAa,EAAE,SAAS,GAAG,SAAS,CAAC;IACrC,aAAa,EAAE,mBAAmB,CAAC;IACnC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;CAC9B,aAYA;AAED,wBAAgB,0BAA0B,CAAC,EACzC,QAAQ,EACR,aAAa,EACb,eAAe,EACf,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,GAAG,CAAC;IACd,aAAa,EAAE,mBAAmB,CAAC;IACnC,eAAe,EAAE,OAAO,CAAC;IACzB,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;CAC9B,GAAG,SAAS,CASZ;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,EACpC,SAAS,EACT,aAAa,EACb,KAAK,GACN,EAAE;IACD,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IACzB,aAAa,EAAE,mBAAmB,CAAC;IACnC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;CAC9B,aAOA;AAED,wBAAgB,aAAa,IAAI,SAAS,GAAG,SAAS,CAarD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,GAAG,GAAG,SAAS,CAqBzD;AAED,wBAAgB,UAAU,CAAC,CAAC,EAC1B,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,EAClB,aAAa,EAAE,mBAAmB,EAClC,eAAe,EAAE,OAAO,EACxB,KAAK,EAAE,cAAc,GAAG,IAAI,QAgB7B;AA2BD,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,gBAAgB,EAAE,GAC3B,MAAM,GAAG,IAAI,CAef;AAED,wBAAgB,yBAAyB,CACvC,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,gBAAgB,EAAE;;;EAe7B"}
@@ -11,6 +11,7 @@ exports.loadChatState = loadChatState;
11
11
  exports.migrateChatState = migrateChatState;
12
12
  exports.saveToDisk = saveToDisk;
13
13
  exports.getLatestDownloadBuildUrl = getLatestDownloadBuildUrl;
14
+ exports.fetchToolCallAvailability = fetchToolCallAvailability;
14
15
  const chat_1 = require("@empiricalrun/llm/chat");
15
16
  const fs_1 = __importDefault(require("fs"));
16
17
  const path_1 = __importDefault(require("path"));
@@ -41,25 +42,36 @@ exports.CHAT_STATE_VERSIONS_MIGRATIONS_MAP = {
41
42
  };
42
43
  exports.LATEST_CHAT_STATE_VERSION = "0.1";
43
44
  exports.CHAT_STATE_PATH = path_1.default.join(process.cwd(), ".empiricalrun", "last-chat.json");
44
- function createChatState(userPrompt, existingState, selectedModel) {
45
+ function createChatState({ userPrompt, existingState, selectedModel, error, }) {
45
46
  const messages = existingState?.messages || [];
46
47
  const chatModel = (0, chat_1.createChatModel)(messages, selectedModel);
47
48
  if (userPrompt) {
48
49
  chatModel.pushUserMessage(userPrompt);
49
50
  }
50
- return createChatStateForMessages(chatModel.messages, selectedModel, chatModel.askUserForInput);
51
+ return createChatStateForMessages({
52
+ messages: chatModel.messages,
53
+ selectedModel,
54
+ askUserForInput: chatModel.askUserForInput,
55
+ error,
56
+ });
51
57
  }
52
- function createChatStateForMessages(messages, selectedModel, askUserForInput) {
58
+ function createChatStateForMessages({ messages, selectedModel, askUserForInput, error, }) {
53
59
  // TODO: Add better types for messages
54
60
  return {
55
61
  version: exports.LATEST_CHAT_STATE_VERSION,
56
62
  model: selectedModel,
57
63
  messages: messages,
58
64
  askUserForInput: askUserForInput,
65
+ error: error,
59
66
  };
60
67
  }
61
- function chatStateFromModel(chatModel, selectedModel) {
62
- return createChatStateForMessages(chatModel.messages, selectedModel, chatModel.askUserForInput);
68
+ function chatStateFromModel({ chatModel, selectedModel, error, }) {
69
+ return createChatStateForMessages({
70
+ messages: chatModel.messages,
71
+ selectedModel,
72
+ askUserForInput: chatModel.askUserForInput,
73
+ error,
74
+ });
63
75
  }
64
76
  function loadChatState() {
65
77
  if (!fs_1.default.existsSync(exports.CHAT_STATE_PATH)) {
@@ -99,7 +111,7 @@ function migrateChatState(oldState) {
99
111
  ...migrated,
100
112
  };
101
113
  }
102
- function saveToDisk(messages, selectedModel, askUserForInput) {
114
+ function saveToDisk(messages, selectedModel, askUserForInput, error) {
103
115
  const statePath = exports.CHAT_STATE_PATH;
104
116
  // Ensure directory exists before trying to read/write
105
117
  const dirname = path_1.default.dirname(statePath);
@@ -107,23 +119,53 @@ function saveToDisk(messages, selectedModel, askUserForInput) {
107
119
  fs_1.default.mkdirSync(dirname, { recursive: true });
108
120
  }
109
121
  // Use the helper to build the new state
110
- const newState = createChatStateForMessages(messages, selectedModel, askUserForInput);
122
+ const newState = createChatStateForMessages({
123
+ messages,
124
+ selectedModel,
125
+ askUserForInput,
126
+ error,
127
+ });
111
128
  fs_1.default.writeFileSync(statePath, JSON.stringify(newState, null, 2));
112
129
  }
113
- function getLatestDownloadBuildUrl(messages) {
114
- const toolCallMessage = messages
130
+ function findLatestToolCall(messages, toolName) {
131
+ return messages
115
132
  .sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())
116
- .find((p) => p.parts.find((p) => {
117
- if ("toolCall" in p) {
118
- return p.toolCall?.name === "downloadBuild";
133
+ .find((m) => m.parts.some((p) => "toolCall" in p && p.toolCall?.name === toolName));
134
+ }
135
+ function findSuccessfulToolResponse(messages, toolCallId) {
136
+ return messages.find((m) => m.parts.some((p) => {
137
+ if ("toolResult" in p) {
138
+ return p.toolCallId === toolCallId && !p.toolResult.isError;
119
139
  }
120
140
  return false;
121
141
  }));
142
+ }
143
+ function getLatestDownloadBuildUrl(messages) {
144
+ const toolCallMessage = findLatestToolCall(messages, "downloadBuild");
122
145
  if (!toolCallMessage)
123
146
  return null;
124
147
  const toolCallPart = toolCallMessage.parts.find((p) => "toolCall" in p && p.toolCall?.name === "downloadBuild");
125
148
  if (!toolCallPart || !("toolCall" in toolCallPart))
126
149
  return null;
150
+ const toolCallId = toolCallPart.toolCall.id;
151
+ const toolResponseMessage = findSuccessfulToolResponse(messages, toolCallId);
152
+ if (!toolResponseMessage)
153
+ return null;
127
154
  const input = toolCallPart.toolCall.input;
128
155
  return input.buildUrl;
129
156
  }
157
+ function fetchToolCallAvailability(toolRequestId, messages) {
158
+ let hasToolRequest = false;
159
+ let hasToolResponse = false;
160
+ messages.forEach((message) => {
161
+ message.parts.forEach((part) => {
162
+ if ("toolCall" in part && part.toolCall?.id === toolRequestId) {
163
+ hasToolRequest = true;
164
+ }
165
+ if ("toolResult" in part && part.toolCallId === toolRequestId) {
166
+ hasToolResponse = true;
167
+ }
168
+ });
169
+ });
170
+ return { hasToolRequest, hasToolResponse };
171
+ }
@@ -1,8 +1,8 @@
1
- import { ChatStateOnDisk } from "./state";
1
+ import { ChatState } from "@empiricalrun/shared-types";
2
2
  type LatestMessage = {
3
3
  role: string;
4
4
  textMessage: string;
5
5
  };
6
- export type ReporterFunction = (state: ChatStateOnDisk<any>, latestHumanReadableMessage: LatestMessage | undefined) => Promise<void>;
6
+ export type ReporterFunction = (state: ChatState, latestHumanReadableMessage: LatestMessage | undefined) => Promise<void>;
7
7
  export {};
8
8
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/agent/chat/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE1C,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,CAC7B,KAAK,EAAE,eAAe,CAAC,GAAG,CAAC,EAC3B,0BAA0B,EAAE,aAAa,GAAG,SAAS,KAClD,OAAO,CAAC,IAAI,CAAC,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/agent/chat/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAEvD,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,CAC7B,KAAK,EAAE,SAAS,EAChB,0BAA0B,EAAE,aAAa,GAAG,SAAS,KAClD,OAAO,CAAC,IAAI,CAAC,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { TraceClient } from "@empiricalrun/llm";
2
+ import { IChatModel, SupportedChatModels } from "@empiricalrun/llm/chat";
3
+ import { ReporterFunction } from "./types";
4
+ export declare const log: (...args: any[]) => void;
5
+ export declare function getModelName(model: string): string;
6
+ export declare function handleAgentError({ context, error, chatModel, selectedModel, reporter, trace, }: {
7
+ context: string;
8
+ error: unknown;
9
+ chatModel: IChatModel<any>;
10
+ selectedModel: SupportedChatModels;
11
+ reporter: ReporterFunction;
12
+ trace?: TraceClient;
13
+ }): Promise<void>;
14
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/agent/chat/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAEL,UAAU,EACV,mBAAmB,EACpB,MAAM,wBAAwB,CAAC;AAKhC,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE3C,eAAO,MAAM,GAAG,GAAI,GAAG,MAAM,GAAG,EAAE,SAEjC,CAAC;AAcF,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMlD;AAED,wBAAsB,gBAAgB,CAAC,EACrC,OAAO,EACP,KAAK,EACL,SAAS,EACT,aAAa,EACb,QAAQ,EACR,KAAK,GACN,EAAE;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;IAC3B,aAAa,EAAE,mBAAmB,CAAC;IACnC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB,iBAsBA"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.log = void 0;
4
+ exports.getModelName = getModelName;
5
+ exports.handleAgentError = handleAgentError;
6
+ const chat_1 = require("@empiricalrun/llm/chat");
7
+ const picocolors_1 = require("picocolors");
8
+ const state_1 = require("./state");
9
+ const log = (...args) => {
10
+ console.log((0, picocolors_1.gray)(args.join(" ")));
11
+ };
12
+ exports.log = log;
13
+ function logError(context, error, trace) {
14
+ console.error((0, picocolors_1.gray)(`[Error in ${context}]:`), error instanceof Error ? error.stack || error.message : error);
15
+ trace?.update({
16
+ output: {
17
+ error: error instanceof Error ? error.message : String(error),
18
+ },
19
+ });
20
+ }
21
+ function getModelName(model) {
22
+ const provider = (0, chat_1.getProviderForModel)(model);
23
+ if (provider === "claude")
24
+ return "Claude";
25
+ if (provider === "google")
26
+ return "Gemini";
27
+ if (provider === "openai")
28
+ return "o4";
29
+ return "AI";
30
+ }
31
+ async function handleAgentError({ context, error, chatModel, selectedModel, reporter, trace, }) {
32
+ const errorObject = {
33
+ message: error.message,
34
+ stack: error.stack || "Stack trace not available",
35
+ timestamp: new Date().toISOString(),
36
+ };
37
+ await reporter((0, state_1.chatStateFromModel)({
38
+ chatModel,
39
+ selectedModel,
40
+ error: errorObject,
41
+ }), chatModel.getHumanReadableLatestMessage());
42
+ trace?.update({
43
+ output: {
44
+ error: errorObject,
45
+ },
46
+ });
47
+ if (context) {
48
+ logError(context, error, trace);
49
+ }
50
+ }
package/dist/bin/index.js CHANGED
@@ -35,7 +35,7 @@ function setupProcessListeners(cleanup) {
35
35
  events.forEach((event) => process.removeListener(event, cleanup));
36
36
  };
37
37
  }
38
- async function runChatAgent({ modelInput, chatSessionId, useDiskForChatState, initialPromptPath, }) {
38
+ async function runChatAgent({ modelInput, chatSessionId, useDiskForChatState, initialPromptPath, withRetry, }) {
39
39
  const MODEL_MAPPING = {
40
40
  "claude-3-7": "claude-3-7-sonnet-20250219",
41
41
  "claude-3-5": "claude-3-5-sonnet-20241022",
@@ -71,6 +71,7 @@ async function runChatAgent({ modelInput, chatSessionId, useDiskForChatState, in
71
71
  selectedModel: specifiedModel || defaultModel,
72
72
  useDiskForChatState: useDiskForChatState || false,
73
73
  initialPromptContent,
74
+ withRetry,
74
75
  });
75
76
  }
76
77
  async function runAgentsWorkflow(testGenConfig, testGenToken) {
@@ -184,12 +185,17 @@ async function runAgentsWorkflow(testGenConfig, testGenToken) {
184
185
  void (0, session_1.updateSessionStatus)(testGenConfig.options?.metadata.testSessionId, {
185
186
  status: "agent_live_session_started",
186
187
  });
188
+ const projectName = await (0, run_1.convertProjectsFilterToProject)({
189
+ pwProjectsFilter: testGenConfig.environment?.playwrightProjects,
190
+ repoDir: process.cwd(),
191
+ testFilePath: specPath,
192
+ });
187
193
  const { isError, error } = await (0, run_1.generateTestsUsingMasterAgent)({
188
194
  testCaseName: testCase.name,
189
195
  testCaseSuites: testCase.suites,
190
196
  testFilePath: specPath,
191
197
  filePathToUpdate,
192
- pwProjectsFilter: testGenConfig.environment?.playwrightProjects,
198
+ projectName,
193
199
  testGenToken,
194
200
  repoDir: process.cwd(),
195
201
  editFileWithGeneratedCode: true,
@@ -215,7 +221,7 @@ async function main() {
215
221
  .option("--use-disk-for-chat-state", "Save and load chat state from disk")
216
222
  .option("--chat-model <model>", "Chat model to use (claude-3-7-sonnet-20250219 or claude-3-5-sonnet-20241022 or gemini-2.5-pro-preview-03-25)")
217
223
  .option("--initial-prompt <path>", "Path to an initial prompt file (e.g. prompt.md)")
218
- .option("--use-transform", "Use the new message transform strategy")
224
+ .option("--with-retry", "Use the retry strategy")
219
225
  .parse(process.argv);
220
226
  const options = program.opts();
221
227
  const completedOptions = await (0, utils_2.validateAndCompleteCliOptions)(options);
@@ -246,7 +252,7 @@ async function main() {
246
252
  modelInput: completedOptions.chatModel,
247
253
  useDiskForChatState: completedOptions.useDiskForChatState,
248
254
  initialPromptPath: completedOptions.initialPrompt,
249
- useTransform: completedOptions.useTransform,
255
+ withRetry: completedOptions.withRetry,
250
256
  });
251
257
  return;
252
258
  }
@@ -9,7 +9,7 @@ export interface CliOptions {
9
9
  initialPrompt?: string;
10
10
  chatSessionId?: string;
11
11
  chatModel?: "claude-3-7" | "claude-3-5" | "claude-3-7-sonnet-20250219" | "claude-3-5-sonnet-20241022" | "gemini-2.5-pro" | "gemini-2.5-pro-preview-03-25" | "o4-mini" | "o4-mini-2025-04-16";
12
- useTransform?: boolean;
12
+ withRetry?: boolean;
13
13
  }
14
14
  export declare function validateAndCompleteCliOptions(options: CliOptions): Promise<CliOptions>;
15
15
  export declare function printBanner(): void;
@@ -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,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EACN,YAAY,GACZ,YAAY,GACZ,4BAA4B,GAC5B,4BAA4B,GAC5B,gBAAgB,GAChB,8BAA8B,GAC9B,SAAS,GACT,oBAAoB,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAQD,wBAAsB,6BAA6B,CACjD,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,UAAU,CAAC,CAyDrB;AAED,wBAAgB,WAAW,SAgC1B"}
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,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EACN,YAAY,GACZ,YAAY,GACZ,4BAA4B,GAC5B,4BAA4B,GAC5B,gBAAgB,GAChB,8BAA8B,GAC9B,SAAS,GACT,oBAAoB,CAAC;IACzB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAQD,wBAAsB,6BAA6B,CACjD,OAAO,EAAE,UAAU,GAClB,OAAO,CAAC,UAAU,CAAC,CAyDrB;AAED,wBAAgB,WAAW,SAgC1B"}
@@ -49,12 +49,15 @@ export declare function hasTopLevelDescribeConfigureWithSerialMode(filePath: str
49
49
  */
50
50
  export declare function findFirstSerialDescribeBlock(node: Node | undefined): Node | undefined;
51
51
  export declare function appendToTestBlock(testBlock: string, content: string): string;
52
+ export declare function runTypescriptCompiler(): Promise<{
53
+ success: boolean;
54
+ errors: string[];
55
+ }>;
52
56
  export declare function validateTypescript(filePath: string): string[];
53
57
  export declare function stripAndPrependImports(content: string, testName: string): Promise<(string | undefined)[]>;
54
58
  export declare function lintErrors(filePath: string): Promise<void>;
55
59
  export declare function formatCode(filePath: string, trace?: TraceClient): Promise<void>;
56
60
  export declare function addNewImport(contents: string, modules: string[], pkg: string): string;
57
- export declare function removeTestOnly(filePath: string): Promise<void>;
58
61
  export declare function getFixtureImportPath(filePath: string): string;
59
62
  export declare function getPageVariableNameFromCreateTest(filePath: string): Promise<string | undefined>;
60
63
  export declare function replaceCreateTestWithNewCode(filePath: string, contents: string, generatedCode: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/bin/utils/platform/web/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/bin/utils/platform/web/index.ts"],"names":[],"mappings":"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"}
@@ -9,12 +9,12 @@ exports.hasTestBlock = hasTestBlock;
9
9
  exports.hasTopLevelDescribeConfigureWithSerialMode = hasTopLevelDescribeConfigureWithSerialMode;
10
10
  exports.findFirstSerialDescribeBlock = findFirstSerialDescribeBlock;
11
11
  exports.appendToTestBlock = appendToTestBlock;
12
+ exports.runTypescriptCompiler = runTypescriptCompiler;
12
13
  exports.validateTypescript = validateTypescript;
13
14
  exports.stripAndPrependImports = stripAndPrependImports;
14
15
  exports.lintErrors = lintErrors;
15
16
  exports.formatCode = formatCode;
16
17
  exports.addNewImport = addNewImport;
17
- exports.removeTestOnly = removeTestOnly;
18
18
  exports.getFixtureImportPath = getFixtureImportPath;
19
19
  exports.getPageVariableNameFromCreateTest = getPageVariableNameFromCreateTest;
20
20
  exports.replaceCreateTestWithNewCode = replaceCreateTestWithNewCode;
@@ -25,6 +25,7 @@ exports.buildTestNamePrompt = buildTestNamePrompt;
25
25
  exports.getVariableDeclarationsFromCode = getVariableDeclarationsFromCode;
26
26
  exports.isSyntaxValid = isSyntaxValid;
27
27
  const parser_1 = require("@babel/parser");
28
+ const test_run_1 = require("@empiricalrun/test-run");
28
29
  const eslint_1 = require("eslint");
29
30
  const fs_1 = __importDefault(require("fs"));
30
31
  const path_1 = __importDefault(require("path"));
@@ -32,6 +33,7 @@ const prettier_1 = __importDefault(require("prettier"));
32
33
  const ts_morph_1 = require("ts-morph");
33
34
  const typescript_1 = __importDefault(require("typescript"));
34
35
  const util_1 = require("util");
36
+ const stripAnsi_1 = require("../../../../utils/stripAnsi");
35
37
  const getTestModuleAliasFromSourceFile = (sourceFile) => {
36
38
  return (sourceFile
37
39
  .getImportDeclarations()
@@ -200,6 +202,26 @@ function appendToTestBlock(testBlock, content) {
200
202
  const updateTestBlock = testBlock.replace(/\}\)$/, `\n\n${content}\n\n })`);
201
203
  return updateTestBlock;
202
204
  }
205
+ async function runTypescriptCompiler() {
206
+ let { code, output } = await (0, test_run_1.spawnCmd)("npx", ["tsc", "--noEmit", "--pretty"], {
207
+ env: {},
208
+ captureOutput: true,
209
+ throwOnError: false,
210
+ });
211
+ if (code === 0) {
212
+ return {
213
+ success: true,
214
+ errors: [],
215
+ };
216
+ }
217
+ if (!output) {
218
+ throw new Error("No output from typescript compiler");
219
+ }
220
+ return {
221
+ success: false,
222
+ errors: (0, stripAnsi_1.stripAnsiEscapes)(output).split("\n"),
223
+ };
224
+ }
203
225
  function validateTypescript(filePath) {
204
226
  // Create a compiler host to read files
205
227
  const compilerHost = typescript_1.default.createCompilerHost({});
@@ -281,13 +303,6 @@ async function formatCode(filePath, trace) {
281
303
  function addNewImport(contents, modules, pkg) {
282
304
  return `import { ${modules.join(", ")} } from "${pkg}";\n${contents}`;
283
305
  }
284
- async function removeTestOnly(filePath) {
285
- const contents = fs_1.default.readFileSync(filePath, "utf8");
286
- const updatedContent = contents
287
- .replace("test.only(", "test(")
288
- .replace("test.describe.only(", "test.describe(");
289
- fs_1.default.writeFileSync(filePath, updatedContent);
290
- }
291
306
  function getFixtureImportPath(filePath) {
292
307
  // get the depth from the tests folder
293
308
  // assumption fixtures are always int the folder tests/fixtures
@@ -1 +1 @@
1
- {"version":3,"file":"commit-and-create-pr.d.ts","sourceRoot":"","sources":["../../src/tools/commit-and-create-pr.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAOnD,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAiB1D;AA2CD,eAAO,MAAM,qBAAqB,EAAE,IAuEnC,CAAC"}
1
+ {"version":3,"file":"commit-and-create-pr.d.ts","sourceRoot":"","sources":["../../src/tools/commit-and-create-pr.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAOnD,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAiB1D;AA2CD,eAAO,MAAM,qBAAqB,EAAE,IA2EnC,CAAC"}
@@ -48,7 +48,11 @@ exports.createPullRequestTool = {
48
48
  description: `Creates a new Pull Request on GitHub.
49
49
  If the current branch already has an open PR, commits and pushes changes to that PR.
50
50
  Uses the empiricalrun[bot] credentials for git operations.
51
- Returns the URL of the created or updated pull request.`,
51
+ Returns the URL of the created or updated pull request.
52
+
53
+ You must come up with a title and description for the pull request, based on the changes made.
54
+ Don't ask the user for this information, just come up with it yourself.
55
+ `,
52
56
  parameters: createPullRequestSchema,
53
57
  },
54
58
  execute: async (input) => {
@@ -1 +1 @@
1
- {"version":3,"file":"str_replace_editor.d.ts","sourceRoot":"","sources":["../../src/tools/str_replace_editor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AA2B1D,UAAU,eAAe;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAqED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAwC1D;AAMD;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC,UAAU,CAAC,CA0KrB;AA+FD,eAAO,MAAM,eAAe,EAAE,IAAI,EAKjC,CAAC"}
1
+ {"version":3,"file":"str_replace_editor.d.ts","sourceRoot":"","sources":["../../src/tools/str_replace_editor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AA2B1D,UAAU,eAAe;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAqED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAwC1D;AAMD;;;GAGG;AACH,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC,UAAU,CAAC,CAuMrB;AAiGD,eAAO,MAAM,eAAe,EAAE,IAAI,EAKjC,CAAC"}
@@ -145,10 +145,8 @@ async function strReplaceEditorExecutor(input) {
145
145
  let content;
146
146
  let lines;
147
147
  let newContent;
148
- let typeCheckErrors;
149
148
  switch (input.command) {
150
149
  case "view":
151
- // TODO: This assumes repoDir is process.cwd()
152
150
  if (!fs_1.default.existsSync(filePath)) {
153
151
  return {
154
152
  result: "Error: File not found",
@@ -163,6 +161,17 @@ async function strReplaceEditorExecutor(input) {
163
161
  isError: false,
164
162
  };
165
163
  }
164
+ else {
165
+ // Check if file is binary, which is not supported
166
+ const { isBinary } = await import("istextorbinary");
167
+ const binary = isBinary(filePath);
168
+ if (binary) {
169
+ return {
170
+ result: "Error: File is binary, which is not supported",
171
+ isError: true,
172
+ };
173
+ }
174
+ }
166
175
  // Handle file view
167
176
  content = fs_1.default.readFileSync(filePath, "utf8");
168
177
  lines = content.split("\n");
@@ -185,8 +194,19 @@ async function strReplaceEditorExecutor(input) {
185
194
  if (input.file_text === undefined || input.file_text === null) {
186
195
  throw new Error("file_text is required for create command");
187
196
  }
197
+ const parentDir = path_1.default.dirname(filePath);
198
+ if (parentDir !== "." && !fs_1.default.existsSync(parentDir)) {
199
+ // Ensure parent directory exists
200
+ fs_1.default.mkdirSync(parentDir, { recursive: true });
201
+ }
188
202
  fs_1.default.writeFileSync(filePath, input.file_text);
189
- // TODO: Add type checking
203
+ let createTypescriptResult = await (0, web_1.runTypescriptCompiler)();
204
+ if (!createTypescriptResult.success) {
205
+ return {
206
+ result: `File ${filePath} has been created. However, type checks are failing with errors:\n${createTypescriptResult.errors.join("\n")}`,
207
+ isError: true,
208
+ };
209
+ }
190
210
  return {
191
211
  result: `Successfully created file ${filePath}`,
192
212
  isError: false,
@@ -233,10 +253,10 @@ async function strReplaceEditorExecutor(input) {
233
253
  }
234
254
  newContent = normalizedContent.replace(normalizedOldStr, input.new_str);
235
255
  fs_1.default.writeFileSync(filePath, newContent);
236
- typeCheckErrors = (0, web_1.validateTypescript)(filePath);
237
- if (typeCheckErrors.length > 0) {
256
+ let strReplaceTypescriptResult = await (0, web_1.runTypescriptCompiler)();
257
+ if (!strReplaceTypescriptResult.success) {
238
258
  return {
239
- result: `Edits to file ${filePath} have been applied. However, type checks are failing with errors:\n${typeCheckErrors.join("\n")}`,
259
+ result: `Edits to file ${filePath} have been applied. However, type checks are failing with errors:\n${strReplaceTypescriptResult.errors.join("\n")}`,
240
260
  isError: true,
241
261
  };
242
262
  }
@@ -254,12 +274,18 @@ async function strReplaceEditorExecutor(input) {
254
274
  createBackup(filePath);
255
275
  content = fs_1.default.readFileSync(filePath, "utf8");
256
276
  lines = content.split("\n");
257
- lines.splice(input.insert_line, 0, input.new_str);
277
+ if (input.insert_line < 1) {
278
+ throw new Error("insert_line must be greater than or equal to 1 (line numbers are 1-indexed).");
279
+ }
280
+ if (input.insert_line > lines.length + 1) {
281
+ throw new Error(`The file at ${filePath} has only ${lines.length} lines, so insert_line must be less than or equal to ${lines.length + 1}. At the maximum value of ${lines.length + 1}, you can insert at the end of the file.`);
282
+ }
283
+ lines.splice(input.insert_line - 1, 0, input.new_str);
258
284
  fs_1.default.writeFileSync(filePath, lines.join("\n"));
259
- typeCheckErrors = (0, web_1.validateTypescript)(filePath);
260
- if (typeCheckErrors.length > 0) {
285
+ let insertTypescriptResult = await (0, web_1.runTypescriptCompiler)();
286
+ if (!insertTypescriptResult.success) {
261
287
  return {
262
- result: `Insertion in file ${filePath} was applied. However, type checks are failing with errors:\n${typeCheckErrors.join("\n")}`,
288
+ result: `Insertion in file ${filePath} was applied. However, type checks are failing with errors:\n${insertTypescriptResult.errors.join("\n")}`,
263
289
  isError: true,
264
290
  };
265
291
  }
@@ -297,8 +323,9 @@ const fileViewTool = {
297
323
  name: "fileViewTool",
298
324
  description: `A tool to view the content of a file or directory. If the path points
299
325
  to a directory, the tool will return a list of files in the directory, separated by line breaks.
300
- If the path points to a file, the tool will return the content of the file. File contents
301
- are returned with line numbers, starting from 1.
326
+ If the path points to a file, the tool will return the content of the file.
327
+
328
+ File contents are returned with line numbers, starting from 1.
302
329
 
303
330
  1: line 1
304
331
  2: line 2
@@ -355,14 +382,14 @@ in the file. If old_str is not unique, the tool will return an error.`,
355
382
  const stringInsertTool = {
356
383
  schema: {
357
384
  name: "stringInsertTool",
358
- description: "A tool to insert a string at a specific line in a file.",
385
+ description: "A tool to insert a string at a specific line in a file. Line numbers are 1-indexed, just like the file view tool.",
359
386
  parameters: zod_1.z.object({
360
387
  path: zod_1.z.string().describe("The path to the file."),
361
388
  insert_line: zod_1.z
362
389
  .number()
363
390
  .int()
364
- .min(0)
365
- .describe("The line number after which to insert the text (0 for beginning of file)."),
391
+ .min(1)
392
+ .describe("The line number after which to insert the text (1 for beginning of file)."),
366
393
  new_str: zod_1.z.string().describe("The string to insert."),
367
394
  }),
368
395
  },
@@ -1 +1 @@
1
- {"version":3,"file":"test-gen-browser.d.ts","sourceRoot":"","sources":["../../src/tools/test-gen-browser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAyFnD,eAAO,MAAM,4BAA4B,EAAE,IAyE1C,CAAC"}
1
+ {"version":3,"file":"test-gen-browser.d.ts","sourceRoot":"","sources":["../../src/tools/test-gen-browser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAsFnD,eAAO,MAAM,4BAA4B,EAAE,IAqF1C,CAAC"}
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.generateTestWithBrowserAgent = void 0;
7
+ const test_run_1 = require("@empiricalrun/test-run");
7
8
  const promises_1 = __importDefault(require("fs/promises"));
8
9
  const zod_1 = require("zod");
9
10
  const run_1 = require("../agent/browsing/run");
@@ -87,13 +88,23 @@ exports.generateTestWithBrowserAgent = {
87
88
  parameters: BrowserAgentSchema,
88
89
  },
89
90
  execute: async (input, trace) => {
91
+ const repoDir = process.cwd();
90
92
  const { testName, testSuites, fileName, changeToMake, project } = input;
91
- const playwrightConfig = await (0, utils_1.readPlaywrightConfig)(process.cwd());
92
- const validProjectNames = await (0, utils_1.getValidProjectNames)(playwrightConfig);
93
- if (!validProjectNames.includes(project)) {
93
+ try {
94
+ const { projects } = await (0, test_run_1.getAllPlaywrightProjects)(repoDir);
95
+ // TODO: Check that file path is valid for this project
96
+ if (!projects.includes(project)) {
97
+ return {
98
+ isError: true,
99
+ result: `Invalid project name: ${project}. Valid project names are: ${projects.join(", ")}`,
100
+ };
101
+ }
102
+ }
103
+ catch (error) {
104
+ console.error("Error reading playwright config:", error);
94
105
  return {
95
106
  isError: true,
96
- result: `Invalid project name: ${project}. Valid project names are: ${validProjectNames.join(", ")}`,
107
+ result: `Error reading playwright config: ${error}`,
97
108
  };
98
109
  }
99
110
  if (!(0, web_1.hasTestBlock)({ testName, testSuites, filePath: fileName })) {
@@ -115,15 +126,16 @@ exports.generateTestWithBrowserAgent = {
115
126
  };
116
127
  }
117
128
  const testGenToken = (0, scenarios_1.buildTokenFromOptions)({ name: testName, file: fileName, prompt: changeToMake }, { useComputerUseAgent: true });
129
+ console.log("[generateTestWithBrowserAgent] Validations passed, starting agent");
118
130
  const toolResult = await (0, run_1.generateTestsUsingMasterAgent)({
119
131
  testCaseName: testName,
120
132
  testCaseSuites: testSuites,
121
133
  testFilePath: fileName,
122
134
  filePathToUpdate: fileName,
123
- pwProjectsFilter: [project],
135
+ projectName: project,
124
136
  traceId: trace?.id,
125
137
  testGenToken,
126
- repoDir: process.cwd(),
138
+ repoDir,
127
139
  editFileWithGeneratedCode: false,
128
140
  });
129
141
  // Undo the TODO -> createTest changes
@@ -1 +1 @@
1
- {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAKA,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,iBAQtD;AAED,wBAAsB,eAAe,CAAC,aAAa,EAAE,MAAM,iBAS1D;AAED,wBAAsB,oBAAoB,oBAGzC;AAED,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,iBAElD;AAED,wBAAsB,wBAAwB,CAC5C,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EAAE,iBAKhB;AAED,wBAAsB,eAAe,sBAQpC"}
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAKA,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,iBAQtD;AAED,wBAAsB,eAAe,CAAC,aAAa,EAAE,MAAM,iBAS1D;AAED,wBAAsB,oBAAoB,oBAGzC;AAED,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,iBAElD;AAED,wBAAsB,wBAAwB,CAC5C,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EAAE,iBAKhB;AAED,wBAAsB,eAAe,sBAUpC"}
package/dist/utils/git.js CHANGED
@@ -47,7 +47,7 @@ async function commitFilesAndPushBranch(commitMessage, branchName, files) {
47
47
  (0, child_process_1.execSync)(`git push origin ${branchName}`);
48
48
  }
49
49
  async function getFilesChanged() {
50
- const output = (0, child_process_1.execSync)("git status --porcelain").toString();
50
+ const output = (0, child_process_1.execSync)("git status --porcelain --untracked-files").toString();
51
51
  let filesChanged = output
52
52
  .split("\n")
53
53
  .map((line) => line.trim().split(" ").pop())
@@ -0,0 +1,2 @@
1
+ export declare function stripAnsiEscapes(str: string): string;
2
+ //# sourceMappingURL=stripAnsi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stripAnsi.d.ts","sourceRoot":"","sources":["../../src/utils/stripAnsi.ts"],"names":[],"mappings":"AAMA,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpD"}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.stripAnsiEscapes = stripAnsiEscapes;
4
+ const ansiRegex = new RegExp(
5
+ // eslint-disable-next-line no-control-regex
6
+ "([\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~])))", "g");
7
+ function stripAnsiEscapes(str) {
8
+ return str.replace(ansiRegex, "");
9
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@empiricalrun/test-gen",
3
- "version": "0.59.0",
3
+ "version": "0.61.0",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"
@@ -48,6 +48,7 @@
48
48
  "express": "^4.19.2",
49
49
  "ignore": "^5.3.1",
50
50
  "inquirer": "^12.4.2",
51
+ "istextorbinary": "^9.5.0",
51
52
  "jsdom": "^26.0.0",
52
53
  "minimatch": "^10.0.1",
53
54
  "nanoid": "^5.0.7",
@@ -60,9 +61,9 @@
60
61
  "tsx": "^4.16.2",
61
62
  "typescript": "^5.3.3",
62
63
  "zod": "^3.23.8",
63
- "@empiricalrun/llm": "^0.16.0",
64
+ "@empiricalrun/llm": "^0.16.1",
64
65
  "@empiricalrun/r2-uploader": "^0.3.9",
65
- "@empiricalrun/test-run": "^0.9.0"
66
+ "@empiricalrun/test-run": "^0.9.2"
66
67
  },
67
68
  "devDependencies": {
68
69
  "@playwright/test": "1.47.1",
@@ -76,7 +77,7 @@
76
77
  "playwright": "1.47.1",
77
78
  "serve-handler": "^6.1.6",
78
79
  "ts-patch": "^3.3.0",
79
- "@empiricalrun/shared-types": "0.1.0"
80
+ "@empiricalrun/shared-types": "0.2.0"
80
81
  },
81
82
  "scripts": {
82
83
  "dev": "tspc --build --watch",
@@ -1 +1 @@
1
- {"root":["./src/index.ts","./src/actions/assert.ts","./src/actions/click.ts","./src/actions/done.ts","./src/actions/fill.ts","./src/actions/goto.ts","./src/actions/hover.ts","./src/actions/index.ts","./src/actions/next-task.ts","./src/actions/press.ts","./src/actions/skill.ts","./src/actions/text-content.ts","./src/actions/constants/index.ts","./src/actions/utils/index.ts","./src/agent/browsing/index.ts","./src/agent/browsing/run.ts","./src/agent/browsing/utils.ts","./src/agent/chat/agent-loop.ts","./src/agent/chat/exports.ts","./src/agent/chat/index.ts","./src/agent/chat/models.ts","./src/agent/chat/prompt.ts","./src/agent/chat/repo.ts","./src/agent/chat/state.ts","./src/agent/chat/types.ts","./src/agent/codegen/create-test-block.ts","./src/agent/codegen/fix-ts-errors.ts","./src/agent/codegen/generate-code-apply-changes.ts","./src/agent/codegen/lexical-scoped-vars.ts","./src/agent/codegen/repo-edit.ts","./src/agent/codegen/run.ts","./src/agent/codegen/skills-retriever.ts","./src/agent/codegen/test-update-feedback.ts","./src/agent/codegen/types.ts","./src/agent/codegen/update-flow.ts","./src/agent/codegen/use-skill.ts","./src/agent/codegen/utils.ts","./src/agent/cua/computer.ts","./src/agent/cua/index.ts","./src/agent/cua/model.ts","./src/agent/diagnosis-agent/index.ts","./src/agent/diagnosis-agent/strict-mode-violation.ts","./src/agent/enrich-prompt/index.ts","./src/agent/enrich-prompt/utils.ts","./src/agent/infer-agent/index.ts","./src/agent/master/action-tool-calls.ts","./src/agent/master/element-annotation.ts","./src/agent/master/execute-browser-action.ts","./src/agent/master/execute-skill-action.ts","./src/agent/master/next-action.ts","./src/agent/master/planner.ts","./src/agent/master/run.ts","./src/agent/master/scroller.ts","./src/agent/master/with-hints.ts","./src/agent/master/browser-tests/cua.spec.ts","./src/agent/master/browser-tests/fixtures.ts","./src/agent/master/browser-tests/index.spec.ts","./src/agent/master/browser-tests/skills.spec.ts","./src/agent/master/icon-descriptor/index.ts","./src/agent/master/icon-descriptor/normalize-svg.ts","./src/agent/planner/run-time-planner.ts","./src/agent/planner/run.ts","./src/bin/index.ts","./src/bin/logger/index.ts","./src/bin/utils/context.ts","./src/bin/utils/index.ts","./src/bin/utils/fs/index.ts","./src/bin/utils/platform/web/index.ts","./src/bin/utils/platform/web/test-files/ts-path-import-validate.ts","./src/bin/utils/scenarios/index.ts","./src/browser-injected-scripts/annotate-elements.spec.ts","./src/constants/index.ts","./src/errors/index.ts","./src/evals/add-scenario-agent.evals.ts","./src/evals/append-create-test-agent.evals.ts","./src/evals/fetch-pom-skills-agent.evals.ts","./src/evals/infer-master-or-code-agent.evals.ts","./src/evals/master-agent.evals.ts","./src/evals/type.ts","./src/evals/update-scenario-agent.evals.ts","./src/file/client.ts","./src/file/server.ts","./src/human-in-the-loop/cli.ts","./src/human-in-the-loop/index.ts","./src/human-in-the-loop/ipc.ts","./src/page/index.ts","./src/prompts/lib/ts-transformer.ts","./src/reporter/index.ts","./src/reporter/lib.ts","./src/session/index.ts","./src/test-build/index.ts","./src/tool-call-service/index.ts","./src/tool-call-service/utils.ts","./src/tools/codegen-agent.ts","./src/tools/commit-and-create-pr.ts","./src/tools/diagnosis-fetcher.ts","./src/tools/download-build.ts","./src/tools/environment-crud.ts","./src/tools/str_replace_editor.ts","./src/tools/test-gen-browser.ts","./src/tools/test-run.ts","./src/tools/grep/index.ts","./src/tools/grep/ripgrep/index.ts","./src/tools/grep/ripgrep/types.ts","./src/tools/test-run-fetcher/index.ts","./src/tools/test-run-fetcher/types.ts","./src/tools/utils/index.ts","./src/types/handlebars.d.ts","./src/types/index.ts","./src/uploader/index.ts","./src/uploader/utils.ts","./src/utils/checkpoint.ts","./src/utils/env.ts","./src/utils/exec.ts","./src/utils/file-tree.ts","./src/utils/file.ts","./src/utils/git.ts","./src/utils/html.ts","./src/utils/index.ts","./src/utils/pw-test.ts","./src/utils/repo-tree.ts","./src/utils/slug.ts","./src/utils/string.ts"],"version":"5.8.3"}
1
+ {"root":["./src/index.ts","./src/actions/assert.ts","./src/actions/click.ts","./src/actions/done.ts","./src/actions/fill.ts","./src/actions/goto.ts","./src/actions/hover.ts","./src/actions/index.ts","./src/actions/next-task.ts","./src/actions/press.ts","./src/actions/skill.ts","./src/actions/text-content.ts","./src/actions/constants/index.ts","./src/actions/utils/index.ts","./src/agent/browsing/index.ts","./src/agent/browsing/run.ts","./src/agent/browsing/utils.ts","./src/agent/chat/agent-loop.ts","./src/agent/chat/exports.ts","./src/agent/chat/index.ts","./src/agent/chat/models.ts","./src/agent/chat/prompt.ts","./src/agent/chat/repo.ts","./src/agent/chat/state.ts","./src/agent/chat/types.ts","./src/agent/chat/utils.ts","./src/agent/codegen/create-test-block.ts","./src/agent/codegen/fix-ts-errors.ts","./src/agent/codegen/generate-code-apply-changes.ts","./src/agent/codegen/lexical-scoped-vars.ts","./src/agent/codegen/repo-edit.ts","./src/agent/codegen/run.ts","./src/agent/codegen/skills-retriever.ts","./src/agent/codegen/test-update-feedback.ts","./src/agent/codegen/types.ts","./src/agent/codegen/update-flow.ts","./src/agent/codegen/use-skill.ts","./src/agent/codegen/utils.ts","./src/agent/cua/computer.ts","./src/agent/cua/index.ts","./src/agent/cua/model.ts","./src/agent/diagnosis-agent/index.ts","./src/agent/diagnosis-agent/strict-mode-violation.ts","./src/agent/enrich-prompt/index.ts","./src/agent/enrich-prompt/utils.ts","./src/agent/infer-agent/index.ts","./src/agent/master/action-tool-calls.ts","./src/agent/master/element-annotation.ts","./src/agent/master/execute-browser-action.ts","./src/agent/master/execute-skill-action.ts","./src/agent/master/next-action.ts","./src/agent/master/planner.ts","./src/agent/master/run.ts","./src/agent/master/scroller.ts","./src/agent/master/with-hints.ts","./src/agent/master/browser-tests/cua.spec.ts","./src/agent/master/browser-tests/fixtures.ts","./src/agent/master/browser-tests/index.spec.ts","./src/agent/master/browser-tests/skills.spec.ts","./src/agent/master/icon-descriptor/index.ts","./src/agent/master/icon-descriptor/normalize-svg.ts","./src/agent/planner/run-time-planner.ts","./src/agent/planner/run.ts","./src/bin/index.ts","./src/bin/logger/index.ts","./src/bin/utils/context.ts","./src/bin/utils/index.ts","./src/bin/utils/fs/index.ts","./src/bin/utils/platform/web/index.ts","./src/bin/utils/platform/web/test-files/ts-path-import-validate.ts","./src/bin/utils/scenarios/index.ts","./src/browser-injected-scripts/annotate-elements.spec.ts","./src/constants/index.ts","./src/errors/index.ts","./src/evals/add-scenario-agent.evals.ts","./src/evals/append-create-test-agent.evals.ts","./src/evals/fetch-pom-skills-agent.evals.ts","./src/evals/infer-master-or-code-agent.evals.ts","./src/evals/master-agent.evals.ts","./src/evals/type.ts","./src/evals/update-scenario-agent.evals.ts","./src/file/client.ts","./src/file/server.ts","./src/human-in-the-loop/cli.ts","./src/human-in-the-loop/index.ts","./src/human-in-the-loop/ipc.ts","./src/page/index.ts","./src/prompts/lib/ts-transformer.ts","./src/reporter/index.ts","./src/reporter/lib.ts","./src/session/index.ts","./src/test-build/index.ts","./src/tool-call-service/index.ts","./src/tool-call-service/utils.ts","./src/tools/codegen-agent.ts","./src/tools/commit-and-create-pr.ts","./src/tools/diagnosis-fetcher.ts","./src/tools/download-build.ts","./src/tools/environment-crud.ts","./src/tools/str_replace_editor.ts","./src/tools/test-gen-browser.ts","./src/tools/test-run.ts","./src/tools/grep/index.ts","./src/tools/grep/ripgrep/index.ts","./src/tools/grep/ripgrep/types.ts","./src/tools/test-run-fetcher/index.ts","./src/tools/test-run-fetcher/types.ts","./src/tools/utils/index.ts","./src/types/handlebars.d.ts","./src/types/index.ts","./src/uploader/index.ts","./src/uploader/utils.ts","./src/utils/checkpoint.ts","./src/utils/env.ts","./src/utils/exec.ts","./src/utils/file-tree.ts","./src/utils/file.ts","./src/utils/git.ts","./src/utils/html.ts","./src/utils/index.ts","./src/utils/pw-test.ts","./src/utils/repo-tree.ts","./src/utils/slug.ts","./src/utils/string.ts","./src/utils/stripAnsi.ts"],"version":"5.8.3"}