@empiricalrun/test-gen 0.62.0 → 0.64.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 (54) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/agent/browsing/run.d.ts.map +1 -1
  3. package/dist/agent/browsing/run.js +10 -5
  4. package/dist/agent/browsing/utils.d.ts +1 -1
  5. package/dist/agent/browsing/utils.d.ts.map +1 -1
  6. package/dist/agent/browsing/utils.js +5 -4
  7. package/dist/agent/chat/index.d.ts.map +1 -1
  8. package/dist/agent/chat/index.js +8 -2
  9. package/dist/agent/cua/computer.d.ts.map +1 -1
  10. package/dist/agent/cua/computer.js +40 -23
  11. package/dist/agent/cua/pw-codegen/element-from-point.d.ts +3 -1
  12. package/dist/agent/cua/pw-codegen/element-from-point.d.ts.map +1 -1
  13. package/dist/agent/cua/pw-codegen/element-from-point.js +19 -14
  14. package/dist/agent/cua/pw-codegen/types.d.ts +2 -1
  15. package/dist/agent/cua/pw-codegen/types.d.ts.map +1 -1
  16. package/dist/artifacts/index.d.ts +9 -0
  17. package/dist/artifacts/index.d.ts.map +1 -1
  18. package/dist/artifacts/index.js +28 -0
  19. package/dist/file/server.js +1 -1
  20. package/dist/tool-call-service/index.d.ts.map +1 -1
  21. package/dist/tool-call-service/index.js +24 -3
  22. package/dist/tools/commit-and-create-pr.d.ts.map +1 -1
  23. package/dist/tools/commit-and-create-pr.js +11 -4
  24. package/dist/tools/diagnosis-fetcher.d.ts.map +1 -1
  25. package/dist/tools/diagnosis-fetcher.js +4 -3
  26. package/dist/tools/download-build.d.ts.map +1 -1
  27. package/dist/tools/download-build.js +1 -1
  28. package/dist/tools/environment-crud.d.ts.map +1 -1
  29. package/dist/tools/environment-crud.js +6 -4
  30. package/dist/tools/grep/index.d.ts.map +1 -1
  31. package/dist/tools/grep/index.js +9 -9
  32. package/dist/tools/str_replace_editor.d.ts +4 -1
  33. package/dist/tools/str_replace_editor.d.ts.map +1 -1
  34. package/dist/tools/str_replace_editor.js +50 -35
  35. package/dist/tools/test-gen-browser.d.ts.map +1 -1
  36. package/dist/tools/test-gen-browser.js +20 -12
  37. package/dist/tools/test-run-fetcher/index.d.ts.map +1 -1
  38. package/dist/tools/test-run-fetcher/index.js +2 -1
  39. package/dist/tools/test-run.d.ts.map +1 -1
  40. package/dist/tools/test-run.js +3 -4
  41. package/dist/tools/utils/index.d.ts +4 -2
  42. package/dist/tools/utils/index.d.ts.map +1 -1
  43. package/dist/tools/utils/index.js +4 -7
  44. package/dist/utils/checkpoint.d.ts +5 -1
  45. package/dist/utils/checkpoint.d.ts.map +1 -1
  46. package/dist/utils/checkpoint.js +8 -3
  47. package/dist/utils/git.d.ts +12 -7
  48. package/dist/utils/git.d.ts.map +1 -1
  49. package/dist/utils/git.js +27 -17
  50. package/package.json +4 -4
  51. package/tsconfig.tsbuildinfo +1 -1
  52. package/dist/tools/codegen-agent.d.ts +0 -3
  53. package/dist/tools/codegen-agent.d.ts.map +0 -1
  54. package/dist/tools/codegen-agent.js +0 -40
@@ -55,11 +55,13 @@ Don't ask the user for this information, just come up with it yourself.
55
55
  `,
56
56
  parameters: createPullRequestSchema,
57
57
  },
58
- execute: async (input) => {
58
+ execute: async ({ input, repoPath, apiKey, }) => {
59
59
  try {
60
60
  const { pullRequestTitle, pullRequestDescription } = input;
61
- const branchName = await (0, git_1.getCurrentBranchName)();
62
- const repoUrl = (0, child_process_1.execSync)("git config --get remote.origin.url")
61
+ const branchName = await (0, git_1.getCurrentBranchName)(repoPath);
62
+ const repoUrl = (0, child_process_1.execSync)("git config --get remote.origin.url", {
63
+ cwd: repoPath,
64
+ })
63
65
  .toString()
64
66
  .trim();
65
67
  const { owner, repo } = parseGitHubUrl(repoUrl);
@@ -70,8 +72,11 @@ Don't ask the user for this information, just come up with it yourself.
70
72
  head: `${owner}:${branchName}`,
71
73
  state: "open",
72
74
  },
75
+ apiKey,
73
76
  }));
74
- (0, child_process_1.execSync)(`git push origin ${branchName} --set-upstream`);
77
+ (0, child_process_1.execSync)(`git push origin ${branchName} --set-upstream`, {
78
+ cwd: repoPath,
79
+ });
75
80
  const existingPR = existingPRs?.find((pr) => pr.head.ref === branchName);
76
81
  if (existingPR) {
77
82
  // Append the new description to the existing PR description
@@ -82,6 +87,7 @@ Don't ask the user for this information, just come up with it yourself.
82
87
  body: {
83
88
  body: updatedDescription,
84
89
  },
90
+ apiKey,
85
91
  });
86
92
  return {
87
93
  isError: false,
@@ -98,6 +104,7 @@ Don't ask the user for this information, just come up with it yourself.
98
104
  base: "main",
99
105
  body: initialDescription,
100
106
  },
107
+ apiKey,
101
108
  }));
102
109
  return {
103
110
  isError: false,
@@ -1 +1 @@
1
- {"version":3,"file":"diagnosis-fetcher.d.ts","sourceRoot":"","sources":["../../src/tools/diagnosis-fetcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAenD,eAAO,MAAM,wBAAwB,EAAE,IAgFtC,CAAC"}
1
+ {"version":3,"file":"diagnosis-fetcher.d.ts","sourceRoot":"","sources":["../../src/tools/diagnosis-fetcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAenD,eAAO,MAAM,wBAAwB,EAAE,IAyFtC,CAAC"}
@@ -19,7 +19,7 @@ exports.fetchDiagnosisReportTool = {
19
19
  description: "Fetch details about a test case diagnosis using its URL or slug",
20
20
  parameters: DiagnosisSchema,
21
21
  },
22
- execute: async (input) => {
22
+ execute: async ({ input, repoPath, apiKey, }) => {
23
23
  const { diagnosisUrl } = input;
24
24
  // Extract the slug from the URL - it's the part after the last '--'
25
25
  const slug = diagnosisUrl.split("--").pop();
@@ -33,6 +33,7 @@ exports.fetchDiagnosisReportTool = {
33
33
  try {
34
34
  data = await (0, utils_1.makeDashboardRequest)({
35
35
  path: `/api/diagnosis/${slug}/detailed`,
36
+ apiKey,
36
37
  });
37
38
  }
38
39
  catch (error) {
@@ -43,8 +44,8 @@ exports.fetchDiagnosisReportTool = {
43
44
  }
44
45
  const { test_case, diagnosis } = data.data;
45
46
  const project = diagnosis?.test_project || "unknown";
46
- const sourceContext = await promises_1.default.readFile(path_1.default.join("tests", test_case.file_path), "utf-8");
47
- const repoName = path_1.default.basename(process.cwd());
47
+ const sourceContext = await promises_1.default.readFile(path_1.default.join(repoPath, "tests", test_case.file_path), "utf-8");
48
+ const repoName = path_1.default.basename(repoPath);
48
49
  const cleanErrorStack = diagnosis?.failed_run_metadata?.stack?.replace(`"/runner/_work/${repoName}/${repoName}/source-repo/"`, "");
49
50
  // Format the response as markdown
50
51
  const markdownResponse = `
@@ -1 +1 @@
1
- {"version":3,"file":"download-build.d.ts","sourceRoot":"","sources":["../../src/tools/download-build.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,uBAAuB;;;;;;EAElC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAE7E,eAAO,MAAM,iBAAiB,EAAE,IAkC/B,CAAC"}
1
+ {"version":3,"file":"download-build.d.ts","sourceRoot":"","sources":["../../src/tools/download-build.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,uBAAuB;;;;;;EAElC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAE7E,eAAO,MAAM,iBAAiB,EAAE,IAsC/B,CAAC"}
@@ -14,7 +14,7 @@ have a build URL, you can try getting the environment details with the getEnviro
14
14
  Environment details will include the build URL.`,
15
15
  parameters: exports.downloadBuildToolSchema,
16
16
  },
17
- execute: async (input, repoPath, apiKey) => {
17
+ execute: async ({ input, repoPath, apiKey, }) => {
18
18
  if (!(await (0, test_build_1.hasDownloadScript)(repoPath))) {
19
19
  return {
20
20
  isError: true,
@@ -1 +1 @@
1
- {"version":3,"file":"environment-crud.d.ts","sourceRoot":"","sources":["../../src/tools/environment-crud.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAyDnD,eAAO,MAAM,kBAAkB,EAAE,IAwEhC,CAAC;AAGF,eAAO,MAAM,gBAAgB,EAAE,IAAI,EAAyB,CAAC"}
1
+ {"version":3,"file":"environment-crud.d.ts","sourceRoot":"","sources":["../../src/tools/environment-crud.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AA6DnD,eAAO,MAAM,kBAAkB,EAAE,IAiFhC,CAAC;AAGF,eAAO,MAAM,gBAAgB,EAAE,IAAI,EAAyB,CAAC"}
@@ -5,10 +5,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.environmentTools = exports.getEnvironmentTool = void 0;
7
7
  const fs_1 = __importDefault(require("fs"));
8
+ const path_1 = __importDefault(require("path"));
8
9
  const zod_1 = require("zod");
9
10
  const utils_1 = require("./utils");
10
- const getProjectRepoName = () => {
11
- const packageJson = fs_1.default.readFileSync("package.json", "utf8");
11
+ const getProjectRepoName = (repoPath) => {
12
+ const packageJson = fs_1.default.readFileSync(path_1.default.join(repoPath, "package.json"), "utf8");
12
13
  if (!packageJson) {
13
14
  throw new Error("Could not find or read package.json file");
14
15
  }
@@ -30,11 +31,11 @@ exports.getEnvironmentTool = {
30
31
  description: "Fetch details of an existing environment",
31
32
  parameters: GetEnvironmentSchema,
32
33
  },
33
- execute: async (input) => {
34
+ execute: async ({ input, repoPath, apiKey, }) => {
34
35
  // Get project repo name
35
36
  let projectRepoName;
36
37
  try {
37
- projectRepoName = getProjectRepoName();
38
+ projectRepoName = getProjectRepoName(repoPath);
38
39
  }
39
40
  catch (error) {
40
41
  return {
@@ -52,6 +53,7 @@ exports.getEnvironmentTool = {
52
53
  response = await (0, utils_1.makeDashboardRequest)({
53
54
  path: `/api/environments?${queryParams.toString()}`,
54
55
  method: "GET",
56
+ apiKey,
55
57
  });
56
58
  }
57
59
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/grep/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,wBAAwB,CAAC;AA2H/D,eAAO,MAAM,QAAQ,EAAE,IAmBtB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/grep/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,wBAAwB,CAAC;AA6H/D,eAAO,MAAM,QAAQ,EAAE,IAuBtB,CAAC"}
@@ -23,9 +23,9 @@ const GrepInputSchema = zod_1.z.object({
23
23
  .optional()
24
24
  .describe("File pattern to search in (e.g., '*.ts' for TypeScript files)"),
25
25
  });
26
- async function usingSystemGrep(input) {
26
+ async function usingSystemGrep(input, repoPath) {
27
27
  try {
28
- const dir = input.directory || process.cwd();
28
+ const dir = path_1.default.join(repoPath, input.directory || "");
29
29
  // Create exclude pattern for grep
30
30
  const excludePatterns = repo_tree_1.DEFAULT_EXCLUDE.map((pattern) => typeof pattern === "string" ? pattern : pattern.source)
31
31
  .map((pattern) => `--exclude-dir="${pattern}"`)
@@ -71,9 +71,9 @@ async function usingSystemGrep(input) {
71
71
  };
72
72
  }
73
73
  }
74
- async function usingRipgrep(input) {
74
+ async function usingRipgrep(input, repoPath) {
75
75
  try {
76
- const dir = path_1.default.join(process.cwd(), input.directory || "");
76
+ const dir = path_1.default.join(repoPath, input.directory || "");
77
77
  const escapedPattern = input.pattern
78
78
  .replace(/\s+/g, "\\ ")
79
79
  .replace(/([[\]()])/g, "\\$1");
@@ -86,7 +86,7 @@ async function usingRipgrep(input) {
86
86
  // Can add submatches and offset info to the summary if needed
87
87
  return {
88
88
  lines: result.lines.text,
89
- path: path_1.default.relative(process.cwd(), result.path.text),
89
+ path: path_1.default.relative(repoPath, result.path.text),
90
90
  // line number is 1-indexed
91
91
  line_number: result.line_number,
92
92
  };
@@ -98,7 +98,7 @@ ${result.path}:${result.line_number}
98
98
  ${result.lines}\`\`\`
99
99
  `;
100
100
  });
101
- const relDir = path_1.default.relative(process.cwd(), dir);
101
+ const relDir = path_1.default.relative(repoPath, dir);
102
102
  const header = `Found ${resultsSummary.length} results for "${input.pattern}" in "${relDir}".
103
103
  All paths are relative to the current working directory.`;
104
104
  return {
@@ -123,13 +123,13 @@ If ripgrep is not available, it will fall back to using system grep.
123
123
  Search is case insensitive and regex patterns are not supported.`,
124
124
  parameters: GrepInputSchema,
125
125
  },
126
- execute: async (input) => {
126
+ execute: async ({ input, repoPath, }) => {
127
127
  if ((0, ripgrep_1.isRgAvailable)()) {
128
- return usingRipgrep(input);
128
+ return usingRipgrep(input, repoPath);
129
129
  }
130
130
  else {
131
131
  console.warn("ripgrep is not available, falling back to system grep.");
132
- return usingSystemGrep(input);
132
+ return usingSystemGrep(input, repoPath);
133
133
  }
134
134
  },
135
135
  };
@@ -17,7 +17,10 @@ export declare function cleanupBackupFiles(repoDir: string): number;
17
17
  * Our implementation of Claude's built-in text editor tool
18
18
  * https://docs.anthropic.com/en/docs/build-with-claude/tool-use/text-editor-tool
19
19
  */
20
- export declare function strReplaceEditorExecutor(input: StrReplaceInput): Promise<ToolResult>;
20
+ export declare function strReplaceEditorExecutor({ input, repoPath, }: {
21
+ input: StrReplaceInput;
22
+ repoPath: string;
23
+ }): Promise<ToolResult>;
21
24
  export declare const textEditorTools: Tool[];
22
25
  export {};
23
26
  //# sourceMappingURL=str_replace_editor.d.ts.map
@@ -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,CAiNrB;AAiGD,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,CAAC,EAC7C,KAAK,EACL,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,eAAe,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC,UAAU,CAAC,CAkNtB;AAmID,eAAO,MAAM,eAAe,EAAE,IAAI,EAKjC,CAAC"}
@@ -139,24 +139,25 @@ function escapeRegExp(text) {
139
139
  * Our implementation of Claude's built-in text editor tool
140
140
  * https://docs.anthropic.com/en/docs/build-with-claude/tool-use/text-editor-tool
141
141
  */
142
- async function strReplaceEditorExecutor(input) {
143
- const repoDir = process.cwd();
142
+ async function strReplaceEditorExecutor({ input, repoPath, }) {
143
+ const repoDir = repoPath;
144
144
  const { path: filePath } = input;
145
+ const absoluteFilePath = path_1.default.join(repoDir, filePath);
145
146
  try {
146
147
  let content;
147
148
  let lines;
148
149
  let newContent;
149
150
  switch (input.command) {
150
151
  case "view":
151
- if (!fs_1.default.existsSync(filePath)) {
152
+ if (!fs_1.default.existsSync(absoluteFilePath)) {
152
153
  return {
153
154
  result: "Error: File not found",
154
155
  isError: true,
155
156
  };
156
157
  }
157
158
  // Handle directory view
158
- if (fs_1.default.statSync(filePath).isDirectory()) {
159
- const files = fs_1.default.readdirSync(filePath);
159
+ if (fs_1.default.statSync(absoluteFilePath).isDirectory()) {
160
+ const files = fs_1.default.readdirSync(absoluteFilePath);
160
161
  return {
161
162
  result: files.join("\n"),
162
163
  isError: false,
@@ -165,7 +166,7 @@ async function strReplaceEditorExecutor(input) {
165
166
  else {
166
167
  // Check if file is binary, which is not supported
167
168
  const { isBinary } = await import("istextorbinary");
168
- const binary = isBinary(filePath);
169
+ const binary = isBinary(absoluteFilePath);
169
170
  if (binary) {
170
171
  return {
171
172
  result: "Error: File is binary, which is not supported",
@@ -174,7 +175,7 @@ async function strReplaceEditorExecutor(input) {
174
175
  }
175
176
  }
176
177
  // Handle file view
177
- content = fs_1.default.readFileSync(filePath, "utf8");
178
+ content = fs_1.default.readFileSync(absoluteFilePath, "utf8");
178
179
  lines = content.split("\n");
179
180
  if (input.view_range) {
180
181
  const [start, end] = input.view_range;
@@ -201,12 +202,12 @@ async function strReplaceEditorExecutor(input) {
201
202
  if (filePath.endsWith("spec.ts") && !filePath.startsWith("tests/")) {
202
203
  throw new Error("Creating spec.ts files is not allowed outside tests/ directory");
203
204
  }
204
- const parentDir = path_1.default.dirname(filePath);
205
+ const parentDir = path_1.default.dirname(absoluteFilePath);
205
206
  if (parentDir !== "." && !fs_1.default.existsSync(parentDir)) {
206
207
  // Ensure parent directory exists
207
208
  fs_1.default.mkdirSync(parentDir, { recursive: true });
208
209
  }
209
- fs_1.default.writeFileSync(filePath, input.file_text);
210
+ fs_1.default.writeFileSync(absoluteFilePath, input.file_text);
210
211
  let createTypescriptResult = await (0, web_1.runTypescriptCompiler)(repoDir);
211
212
  if (!createTypescriptResult.success) {
212
213
  return {
@@ -226,8 +227,8 @@ async function strReplaceEditorExecutor(input) {
226
227
  // "" is valid as new_str, so we check for nullish -- not falsy
227
228
  throw new Error("new_str is required for str_replace command");
228
229
  }
229
- createBackup(filePath);
230
- content = fs_1.default.readFileSync(filePath, "utf8");
230
+ createBackup(absoluteFilePath);
231
+ content = fs_1.default.readFileSync(absoluteFilePath, "utf8");
231
232
  // Normalize newlines in both the content and search string
232
233
  const normalizedContent = content.replace(/\r\n/g, "\n");
233
234
  const normalizedOldStr = input.old_str
@@ -259,7 +260,7 @@ async function strReplaceEditorExecutor(input) {
259
260
  };
260
261
  }
261
262
  newContent = normalizedContent.replace(normalizedOldStr, input.new_str);
262
- fs_1.default.writeFileSync(filePath, newContent);
263
+ fs_1.default.writeFileSync(absoluteFilePath, newContent);
263
264
  let strReplaceTypescriptResult = await (0, web_1.runTypescriptCompiler)(repoDir);
264
265
  if (!strReplaceTypescriptResult.success) {
265
266
  return {
@@ -278,8 +279,8 @@ async function strReplaceEditorExecutor(input) {
278
279
  if (input.insert_line === undefined || !input.new_str) {
279
280
  throw new Error("insert_line and new_str are required for insert command");
280
281
  }
281
- createBackup(filePath);
282
- content = fs_1.default.readFileSync(filePath, "utf8");
282
+ createBackup(absoluteFilePath);
283
+ content = fs_1.default.readFileSync(absoluteFilePath, "utf8");
283
284
  lines = content.split("\n");
284
285
  if (input.insert_line < 1) {
285
286
  throw new Error("insert_line must be greater than or equal to 1 (line numbers are 1-indexed).");
@@ -288,7 +289,7 @@ async function strReplaceEditorExecutor(input) {
288
289
  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.`);
289
290
  }
290
291
  lines.splice(input.insert_line - 1, 0, input.new_str);
291
- fs_1.default.writeFileSync(filePath, lines.join("\n"));
292
+ fs_1.default.writeFileSync(absoluteFilePath, lines.join("\n"));
292
293
  let insertTypescriptResult = await (0, web_1.runTypescriptCompiler)(repoDir);
293
294
  if (!insertTypescriptResult.success) {
294
295
  return {
@@ -303,8 +304,8 @@ async function strReplaceEditorExecutor(input) {
303
304
  };
304
305
  }
305
306
  case "undo_edit":
306
- if (hasBackup(filePath)) {
307
- restoreBackup(filePath);
307
+ if (hasBackup(absoluteFilePath)) {
308
+ restoreBackup(absoluteFilePath);
308
309
  return {
309
310
  result: `Successfully restored ${filePath} from backup`,
310
311
  isError: false,
@@ -342,10 +343,13 @@ File contents are returned with line numbers, starting from 1.
342
343
  path: zod_1.z.string().describe("The path to the file or directory to view."),
343
344
  }),
344
345
  },
345
- execute: async (input) => {
346
+ execute: async ({ input, repoPath, }) => {
346
347
  return strReplaceEditorExecutor({
347
- command: "view",
348
- path: input.path,
348
+ input: {
349
+ command: "view",
350
+ path: input.path,
351
+ },
352
+ repoPath,
349
353
  });
350
354
  },
351
355
  };
@@ -358,11 +362,14 @@ const fileCreateTool = {
358
362
  file_text: zod_1.z.string().describe("The contents of the new file."),
359
363
  }),
360
364
  },
361
- execute: async (input) => {
365
+ execute: async ({ input, repoPath, }) => {
362
366
  return strReplaceEditorExecutor({
363
- command: "create",
364
- path: input.path,
365
- file_text: input.file_text,
367
+ input: {
368
+ command: "create",
369
+ path: input.path,
370
+ file_text: input.file_text,
371
+ },
372
+ repoPath,
366
373
  });
367
374
  },
368
375
  };
@@ -377,12 +384,15 @@ in the file. If old_str is not unique, the tool will return an error.`,
377
384
  new_str: zod_1.z.string().describe("The string to replace old_str with."),
378
385
  }),
379
386
  },
380
- execute: async (input) => {
387
+ execute: async ({ input, repoPath, }) => {
381
388
  return strReplaceEditorExecutor({
382
- command: "str_replace",
383
- path: input.path,
384
- old_str: input.old_str,
385
- new_str: input.new_str,
389
+ input: {
390
+ command: "str_replace",
391
+ path: input.path,
392
+ old_str: input.old_str,
393
+ new_str: input.new_str,
394
+ },
395
+ repoPath,
386
396
  });
387
397
  },
388
398
  };
@@ -396,16 +406,21 @@ const stringInsertTool = {
396
406
  .number()
397
407
  .int()
398
408
  .min(1)
399
- .describe("The line number after which to insert the text (1 for beginning of file)."),
409
+ .describe(`The line number on which to insert the text (1 for beginning of file).
410
+ To insert a string at the beginning of the file, you should use insert_line = 1.
411
+ To insert a string at the end of the file, you should use insert_line = (total lines + 1).`),
400
412
  new_str: zod_1.z.string().describe("The string to insert."),
401
413
  }),
402
414
  },
403
- execute: async (input) => {
415
+ execute: async ({ input, repoPath, }) => {
404
416
  return strReplaceEditorExecutor({
405
- command: "insert",
406
- path: input.path,
407
- insert_line: input.insert_line,
408
- new_str: input.new_str,
417
+ input: {
418
+ command: "insert",
419
+ path: input.path,
420
+ insert_line: input.insert_line,
421
+ new_str: input.new_str,
422
+ },
423
+ repoPath,
409
424
  });
410
425
  },
411
426
  };
@@ -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;AA4FnD,eAAO,MAAM,4BAA4B,EAAE,IAoH1C,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;AA4FnD,eAAO,MAAM,4BAA4B,EAAE,IA+H1C,CAAC"}
@@ -5,14 +5,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.generateTestWithBrowserAgent = void 0;
7
7
  const test_run_1 = require("@empiricalrun/test-run");
8
- const promises_1 = __importDefault(require("fs/promises"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
9
10
  const zod_1 = require("zod");
10
11
  const run_1 = require("../agent/browsing/run");
11
12
  const utils_1 = require("../agent/browsing/utils");
12
13
  const pw_pause_1 = require("../agent/cua/pw-codegen/pw-pause");
13
14
  const web_1 = require("../bin/utils/platform/web");
14
15
  const scenarios_1 = require("../bin/utils/scenarios");
15
- const slug_1 = require("../utils/slug");
16
16
  const BrowserAgentSchema = zod_1.z.object({
17
17
  testName: zod_1.z.string().describe("The name of the test to create or modify"),
18
18
  testSuites: zod_1.z
@@ -89,12 +89,12 @@ exports.generateTestWithBrowserAgent = {
89
89
  description: BROWSER_AGENT_DESCRIPTION,
90
90
  parameters: BrowserAgentSchema,
91
91
  },
92
- execute: async (input, repoPath, apiKey, trace, collectArtifacts) => {
92
+ execute: async ({ input, repoPath, trace, collectArtifacts, }) => {
93
93
  const repoDir = repoPath;
94
94
  const { testName, testSuites, fileName, changeToMake, project } = input;
95
+ const absoluteFilePath = path_1.default.join(repoDir, fileName);
95
96
  try {
96
97
  const { projects } = await (0, test_run_1.getAllPlaywrightProjects)(repoDir);
97
- // TODO: Check that file path is valid for this project
98
98
  if (!projects.includes(project)) {
99
99
  return {
100
100
  isError: true,
@@ -109,20 +109,30 @@ exports.generateTestWithBrowserAgent = {
109
109
  result: `Error reading playwright config: ${error}`,
110
110
  };
111
111
  }
112
- if (!(0, web_1.hasTestBlock)({ testName, testSuites, filePath: fileName })) {
112
+ if (!fs_1.default.existsSync(absoluteFilePath)) {
113
+ return {
114
+ isError: true,
115
+ result: `Could not find file in repository: ${fileName}. Did you use the full path relative to the root of the repository?`,
116
+ };
117
+ }
118
+ if (!(0, web_1.hasTestBlock)({
119
+ testName,
120
+ testSuites,
121
+ filePath: absoluteFilePath,
122
+ })) {
113
123
  return {
114
124
  isError: true,
115
125
  result: `Test block not found for test name: "${testName}" in file: "${fileName}" with describe blocks: "${testSuites.join(", ")}"`,
116
126
  };
117
127
  }
118
128
  // Prepare the file for the browser agent
119
- const fileBackup = await promises_1.default.readFile(fileName, "utf-8");
129
+ const fileBackup = fs_1.default.readFileSync(absoluteFilePath, "utf-8");
120
130
  try {
121
- await (0, utils_1.replaceTodoWithCreateTest)(fileName);
131
+ await (0, utils_1.replaceTodoWithCreateTest)(fileName, repoDir);
122
132
  }
123
133
  catch (error) {
124
134
  // Undo the TODO -> createTest and test.only changes
125
- await promises_1.default.writeFile(fileName, fileBackup, "utf-8");
135
+ fs_1.default.writeFileSync(absoluteFilePath, fileBackup, "utf-8");
126
136
  return {
127
137
  isError: true,
128
138
  result: `Error running tool: ${error}`,
@@ -151,11 +161,10 @@ exports.generateTestWithBrowserAgent = {
151
161
  });
152
162
  // Cleanup: Undo the TODO -> createTest changes
153
163
  await (0, pw_pause_1.revertToOriginalPwCode)(repoDir);
154
- await promises_1.default.writeFile(fileName, fileBackup, "utf-8");
164
+ fs_1.default.writeFileSync(absoluteFilePath, fileBackup, "utf-8");
155
165
  const { isError, error, actionsSummary, artifacts } = toolResult;
156
- let collectedArtifacts;
157
166
  if (artifacts) {
158
- collectedArtifacts = await collectArtifacts?.(artifacts, repoDir, (0, slug_1.slugify)(testName));
167
+ void collectArtifacts?.(artifacts);
159
168
  }
160
169
  if (!isError) {
161
170
  return {
@@ -165,7 +174,6 @@ and the generated Playwright code:
165
174
 
166
175
  ${actionsSummary}
167
176
  `,
168
- artifacts: collectedArtifacts,
169
177
  };
170
178
  }
171
179
  else {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/test-run-fetcher/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAcnD,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOnE;AAED,eAAO,MAAM,sBAAsB,EAAE,IAwHpC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/test-run-fetcher/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAcnD,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOnE;AAED,eAAO,MAAM,sBAAsB,EAAE,IA+HpC,CAAC"}
@@ -24,7 +24,7 @@ exports.fetchTestRunReportTool = {
24
24
  description: "Fetch details about a test run using its URL",
25
25
  parameters: TestRunSchema,
26
26
  },
27
- execute: async (input) => {
27
+ execute: async ({ input, apiKey, }) => {
28
28
  const { testRunUrl } = input;
29
29
  // Remove query parameters if they exist
30
30
  const urlWithoutParams = testRunUrl.split("?")[0] || testRunUrl;
@@ -42,6 +42,7 @@ exports.fetchTestRunReportTool = {
42
42
  try {
43
43
  data = await (0, utils_1.makeDashboardRequest)({
44
44
  path: `/api/test-runs/${runId}?repo_name=${repoName}`,
45
+ apiKey,
45
46
  });
46
47
  }
47
48
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"test-run.d.ts","sourceRoot":"","sources":["../../src/tools/test-run.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,wBAAwB,CAAC;AA4C/D,eAAO,MAAM,WAAW,EAAE,IAsEzB,CAAC"}
1
+ {"version":3,"file":"test-run.d.ts","sourceRoot":"","sources":["../../src/tools/test-run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,wBAAwB,CAAC;AA4C/D,eAAO,MAAM,WAAW,EAAE,IAmEzB,CAAC"}
@@ -34,7 +34,7 @@ exports.runTestTool = {
34
34
  description: "Run a test",
35
35
  parameters: RunTestSchema,
36
36
  },
37
- execute: async (input, repoPath, apiKey, trace, collectArtifacts) => {
37
+ execute: async ({ input, repoPath, collectArtifacts, }) => {
38
38
  let reportUrl = undefined;
39
39
  let envOverrides = undefined;
40
40
  if ((0, artifacts_1.isArtifactCollectionEnabled)()) {
@@ -50,7 +50,7 @@ exports.runTestTool = {
50
50
  console.warn("R2 credentials not found: report artifacts will not be uploaded");
51
51
  }
52
52
  const { testName, suites, fileName, project } = input;
53
- const repoDir = process.cwd();
53
+ const repoDir = repoPath;
54
54
  try {
55
55
  const result = await (0, test_run_1.runSingleTest)({
56
56
  testName,
@@ -61,7 +61,7 @@ exports.runTestTool = {
61
61
  repoDir,
62
62
  });
63
63
  const attachments = (0, utils_1.extractAttachmentsFromPlaywrightJSONReport)(result.summaryJson);
64
- const artifacts = await collectArtifacts?.(attachments, repoDir, Date.now().toString());
64
+ void collectArtifacts?.(attachments);
65
65
  return {
66
66
  isError: false,
67
67
  result: buildResult({
@@ -69,7 +69,6 @@ exports.runTestTool = {
69
69
  summaryJson: result.summaryJson,
70
70
  reportUrl: reportUrl,
71
71
  }),
72
- artifacts,
73
72
  };
74
73
  }
75
74
  catch (error) {
@@ -1,13 +1,15 @@
1
1
  import { JSONReport as PlaywrightJSONReport } from "@playwright/test/reporter";
2
- export declare function makeDashboardRequest<T>({ path, method, body, }: {
2
+ export declare function makeDashboardRequest<T>({ path, method, body, apiKey, }: {
3
3
  path: string;
4
4
  method?: string;
5
5
  body?: any;
6
+ apiKey: string;
6
7
  }): Promise<T>;
7
- export declare function callGitHubProxy({ method, url, body, }: {
8
+ export declare function callGitHubProxy({ method, url, body, apiKey, }: {
8
9
  method: string;
9
10
  url: string;
10
11
  body?: any;
12
+ apiKey: string;
11
13
  }): Promise<unknown>;
12
14
  type AttachmentInfo = {
13
15
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,IAAI,oBAAoB,EAEnC,MAAM,2BAA2B,CAAC;AAEnC,wBAAsB,oBAAoB,CAAC,CAAC,EAAE,EAC5C,IAAI,EACJ,MAAc,EACd,IAAI,GACL,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ,GAAG,OAAO,CAAC,CAAC,CAAC,CAuBb;AAED,wBAAsB,eAAe,CAAC,EACpC,MAAM,EACN,GAAG,EACH,IAAI,GACL,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ,oBAWA;AAED,KAAK,cAAc,GAAG;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,0CAA0C,CACxD,MAAM,EAAE,oBAAoB,GAC3B,cAAc,EAAE,CA4ClB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,IAAI,oBAAoB,EAEnC,MAAM,2BAA2B,CAAC;AAEnC,wBAAsB,oBAAoB,CAAC,CAAC,EAAE,EAC5C,IAAI,EACJ,MAAc,EACd,IAAI,EACJ,MAAM,GACP,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,CAAC,CAAC,CAmBb;AAED,wBAAsB,eAAe,CAAC,EACpC,MAAM,EACN,GAAG,EACH,IAAI,EACJ,MAAM,GACP,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;CAChB,oBAYA;AAED,KAAK,cAAc,GAAG;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,0CAA0C,CACxD,MAAM,EAAE,oBAAoB,GAC3B,cAAc,EAAE,CA4ClB"}
@@ -3,14 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.makeDashboardRequest = makeDashboardRequest;
4
4
  exports.callGitHubProxy = callGitHubProxy;
5
5
  exports.extractAttachmentsFromPlaywrightJSONReport = extractAttachmentsFromPlaywrightJSONReport;
6
- async function makeDashboardRequest({ path, method = "GET", body, }) {
7
- const API_KEY = process.env.EMPIRICALRUN_API_KEY;
8
- if (!API_KEY) {
9
- throw new Error("EMPIRICALRUN_API_KEY is not found");
10
- }
6
+ async function makeDashboardRequest({ path, method = "GET", body, apiKey, }) {
11
7
  const requestHeaders = {
12
8
  "Content-Type": "application/json",
13
- Authorization: `Bearer ${API_KEY}`,
9
+ Authorization: `Bearer ${apiKey}`,
14
10
  "User-Agent": "empiricalrun/test-gen",
15
11
  };
16
12
  const baseUrl = process.env.DASHBOARD_DOMAIN || "https://dash.empirical.run";
@@ -25,7 +21,7 @@ async function makeDashboardRequest({ path, method = "GET", body, }) {
25
21
  }
26
22
  return await response.json();
27
23
  }
28
- async function callGitHubProxy({ method, url, body, }) {
24
+ async function callGitHubProxy({ method, url, body, apiKey, }) {
29
25
  const githubApiPath = url.replace("https://api.github.com", "");
30
26
  return makeDashboardRequest({
31
27
  path: "/api/github/proxy",
@@ -35,6 +31,7 @@ async function callGitHubProxy({ method, url, body, }) {
35
31
  url: githubApiPath,
36
32
  body,
37
33
  },
34
+ apiKey,
38
35
  });
39
36
  }
40
37
  /**
@@ -1,3 +1,7 @@
1
1
  import { PendingToolCall } from "@empiricalrun/llm/chat";
2
- export declare function createCheckpoint(toolCalls: PendingToolCall[], branchName: string): Promise<void>;
2
+ export declare function createCheckpoint({ toolCalls, branchName, repoPath, }: {
3
+ toolCalls: PendingToolCall[];
4
+ branchName: string;
5
+ repoPath: string;
6
+ }): Promise<void>;
3
7
  //# sourceMappingURL=checkpoint.d.ts.map