@empiricalrun/test-gen 0.56.2 → 0.56.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @empiricalrun/test-gen
2
2
 
3
+ ## 0.56.4
4
+
5
+ ### Patch Changes
6
+
7
+ - 0d53865: fix: browser agent tool call has different exit code on linux
8
+ - 8e5dcd2: feat: move to ripgrep for platform independent grep tool calls
9
+
10
+ ## 0.56.3
11
+
12
+ ### Patch Changes
13
+
14
+ - bf87a3a: fix: grep tool should not return error if no results are found
15
+ - 607ec6d: fix: normalize old_str for newlines before running text editor tools
16
+ - a7f2e24: fix: downgrade tsx logs to warn instead of errors
17
+ - 1728128: feat: nesting of toolCall span under llm generation
18
+ - Updated dependencies [a7f2e24]
19
+ - @empiricalrun/test-run@0.8.4
20
+
3
21
  ## 0.56.2
4
22
 
5
23
  ### Patch Changes
@@ -307,11 +307,11 @@ async function readPlaywrightConfig(repoDir) {
307
307
  tsxImport = module;
308
308
  })
309
309
  .catch((err) => {
310
- console.error("Failed to import tsx: --->", err.message);
310
+ console.warn("Failed to import tsx: --->", err.message);
311
311
  });
312
312
  }
313
313
  if (!tsxImport) {
314
- console.error("tsx module not available");
314
+ console.warn("tsx module not available");
315
315
  return {};
316
316
  }
317
317
  const [lastDir] = repoDir.split("/").reverse();
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/chat/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAoB,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAiBhE,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,iBAsFA;AAuBD,wBAAsB,wBAAwB,CAAC,EAC7C,aAAa,EACb,aAAa,GACd,EAAE;IACD,aAAa,EAAE,mBAAmB,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;CACvB,iBA2CA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/agent/chat/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAoB,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAiBhE,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,iBAsFA;AA0BD,wBAAsB,wBAAwB,CAAC,EAC7C,aAAa,EACb,aAAa,GACd,EAAE;IACD,aAAa,EAAE,mBAAmB,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;CACvB,iBA2CA"}
@@ -112,6 +112,9 @@ async function getChatSessionFromDashboard(chatSessionId) {
112
112
  Authorization: `Bearer ${process.env.EMPIRICALRUN_API_KEY}`,
113
113
  },
114
114
  });
115
+ if (!response.ok) {
116
+ throw new Error(`Failed to get chat session: ${response.statusText}`);
117
+ }
115
118
  const data = await response.json();
116
119
  return data.data.chat_session;
117
120
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tool-call-service/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAE3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAa1D,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAEpC,KAAK,aAAa,GAAG;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;CACpD,CAAC;AA4BF,qBAAa,eAAe;IAC1B,KAAK,EAAE,IAAI,EAAE,CAAM;IACnB,aAAa,EAAE,aAAa,CAAM;IAClC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAE,mBAAmB,CAAC;gBAGjC,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,aAAa,EAAE,mBAAmB;IAgB9B,QAAQ;;;IAaR,OAAO,CACX,SAAS,EAAE,eAAe,EAAE,EAC5B,QAAQ,EAAE,OAAO,EACjB,KAAK,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,UAAU,EAAE,CAAC;CAgDzB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tool-call-service/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAE3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAa1D,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAEpC,KAAK,aAAa,GAAG;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;CACpD,CAAC;AA4BF,qBAAa,eAAe;IAC1B,KAAK,EAAE,IAAI,EAAE,CAAM;IACnB,aAAa,EAAE,aAAa,CAAM;IAClC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAE,mBAAmB,CAAC;gBAGjC,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,aAAa,EAAE,mBAAmB;IAgB9B,QAAQ;;;IAaR,OAAO,CACX,SAAS,EAAE,eAAe,EAAE,EAC5B,QAAQ,EAAE,OAAO,EACjB,KAAK,CAAC,EAAE,WAAW,GAClB,OAAO,CAAC,UAAU,EAAE,CAAC;CAuDzB"}
@@ -75,9 +75,13 @@ class ToolCallService {
75
75
  }));
76
76
  }
77
77
  else {
78
+ const executeSpan = trace?.span({
79
+ name: "execute_tools",
80
+ input: { toolCalls: toolCalls.map((tc) => ({ name: tc.name })) },
81
+ });
78
82
  const toolResults = [];
79
83
  for (const toolCall of toolCalls) {
80
- const span = trace?.span({
84
+ const span = executeSpan?.span({
81
85
  name: `tool: ${toolCall.name}`,
82
86
  input: toolCall.input,
83
87
  });
@@ -105,6 +109,7 @@ class ToolCallService {
105
109
  span?.end({ output: errorResult });
106
110
  }
107
111
  }
112
+ executeSpan?.end({ output: { toolResults } });
108
113
  return toolResults;
109
114
  }
110
115
  }
@@ -1,3 +1,3 @@
1
1
  import type { Tool } from "@empiricalrun/llm/chat";
2
2
  export declare const grepTool: Tool;
3
- //# sourceMappingURL=grep.d.ts.map
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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;AAoH/D,eAAO,MAAM,QAAQ,EAAE,IAkBtB,CAAC"}
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.grepTool = void 0;
7
+ const child_process_1 = require("child_process");
8
+ const path_1 = __importDefault(require("path"));
9
+ const util_1 = require("util");
10
+ const zod_1 = require("zod");
11
+ const repo_tree_1 = require("../../utils/repo-tree");
12
+ const ripgrep_1 = require("./ripgrep");
13
+ const GrepInputSchema = zod_1.z.object({
14
+ pattern: zod_1.z.string().describe("The pattern to search for"),
15
+ directory: zod_1.z
16
+ .string()
17
+ .optional()
18
+ .describe("The directory to search in (defaults to current directory)"),
19
+ filePattern: zod_1.z
20
+ .string()
21
+ .optional()
22
+ .describe("File pattern to search in (e.g., '*.ts' for TypeScript files)"),
23
+ });
24
+ async function usingSystemGrep(input) {
25
+ try {
26
+ const dir = input.directory || process.cwd();
27
+ // Create exclude pattern for grep
28
+ const excludePatterns = repo_tree_1.DEFAULT_EXCLUDE.map((pattern) => typeof pattern === "string" ? pattern : pattern.source)
29
+ .map((pattern) => `--exclude-dir="${pattern}"`)
30
+ .join(" ");
31
+ // Using -n to show line numbers in output
32
+ let cmd = `grep -rin ${excludePatterns} "${input.pattern}" ${dir}`;
33
+ if (input.filePattern) {
34
+ // For file pattern searches, we'll use find with exclusions
35
+ const excludeFind = repo_tree_1.DEFAULT_EXCLUDE.map((pattern) => typeof pattern === "string" ? pattern : pattern.source)
36
+ .map((pattern) => `-not -path "*/${pattern}/*"`)
37
+ .join(" ");
38
+ // Modified command to ensure filepath is included in the output
39
+ // Using grep with -H to always show filename and the filepath as part of the output
40
+ cmd = `find ${dir} ${excludeFind} -name "${input.filePattern}" | xargs grep -Hn "${input.pattern}"`;
41
+ }
42
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
43
+ const { stdout, stderr } = await execAsync(cmd);
44
+ if (stdout) {
45
+ return {
46
+ isError: false,
47
+ result: stdout,
48
+ };
49
+ }
50
+ else if (!stdout && stderr) {
51
+ return {
52
+ isError: true,
53
+ result: stderr,
54
+ };
55
+ }
56
+ else {
57
+ // Both are empty, which means no results were found
58
+ return {
59
+ isError: false,
60
+ result: "No results found.",
61
+ };
62
+ }
63
+ }
64
+ catch (error) {
65
+ console.error("Error executing grep", error);
66
+ return {
67
+ isError: true,
68
+ result: error instanceof Error ? error.message : String(error),
69
+ };
70
+ }
71
+ }
72
+ async function usingRipgrep(input) {
73
+ try {
74
+ const dir = path_1.default.join(process.cwd(), input.directory || "");
75
+ const results = await (0, ripgrep_1.ripgrep)(dir, {
76
+ string: input.pattern,
77
+ globs: input.filePattern ? [input.filePattern] : undefined,
78
+ });
79
+ const resultsSummary = results
80
+ .map((result) => {
81
+ // Can add submatches and offset info to the summary if needed
82
+ return {
83
+ lines: result.lines.text,
84
+ path: path_1.default.relative(process.cwd(), result.path.text),
85
+ // line number is 1-indexed
86
+ line_number: result.line_number,
87
+ };
88
+ })
89
+ .map((result) => {
90
+ return `
91
+ ${result.path}:${result.line_number}
92
+ \`\`\`
93
+ ${result.lines}\`\`\`
94
+ `;
95
+ });
96
+ const relDir = path_1.default.relative(process.cwd(), dir);
97
+ const header = `Found ${resultsSummary.length} results for "${input.pattern}" in "${relDir}".
98
+ All paths are relative to the current working directory.`;
99
+ return {
100
+ isError: false,
101
+ result: `${header}\n${resultsSummary.join("\n")}`,
102
+ };
103
+ }
104
+ catch (error) {
105
+ console.error("Error executing ripgrep", error);
106
+ return {
107
+ isError: true,
108
+ result: error instanceof Error ? error.message : String(error),
109
+ };
110
+ }
111
+ }
112
+ exports.grepTool = {
113
+ schema: {
114
+ name: "grep",
115
+ description: "Search for a pattern in files using grep (case insensitive)",
116
+ parameters: GrepInputSchema,
117
+ },
118
+ execute: async (input) => {
119
+ const isAvailable = await (0, ripgrep_1.isRgAvailable)();
120
+ if (isAvailable) {
121
+ return usingRipgrep(input);
122
+ }
123
+ else {
124
+ console.warn("ripgrep is not available, falling back to system grep.");
125
+ return usingSystemGrep(input);
126
+ }
127
+ },
128
+ };
@@ -0,0 +1,5 @@
1
+ import { Match, Options } from "./types";
2
+ export * from "./types";
3
+ export declare function isRgAvailable(): Promise<unknown>;
4
+ export declare function ripgrep(cwd: string, options: Options): Promise<Array<Match>>;
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/tools/grep/ripgrep/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAgB,MAAM,SAAS,CAAC;AAEvD,cAAc,SAAS,CAAC;AAcxB,wBAAgB,aAAa,qBAY5B;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CA8C5E"}
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.ripgrep = exports.isRgAvailable = void 0;
18
+ const child_process_1 = require("child_process");
19
+ const types_1 = require("./types");
20
+ __exportStar(require("./types"), exports);
21
+ function formatResults(stdout) {
22
+ stdout = stdout.trim();
23
+ if (!stdout) {
24
+ return [];
25
+ }
26
+ return stdout
27
+ .split("\n")
28
+ .map((line) => JSON.parse(line))
29
+ .filter((jsonLine) => jsonLine.type === "match")
30
+ .map((jsonLine) => jsonLine.data);
31
+ }
32
+ function isRgAvailable() {
33
+ return new Promise((resolve) => {
34
+ // Use 'where' on Windows and 'which' on Unix-like systems
35
+ const command = process.platform === "win32" ? "where rg" : "which rg";
36
+ (0, child_process_1.exec)(command, (error) => {
37
+ if (error) {
38
+ resolve(false);
39
+ }
40
+ else {
41
+ resolve(true);
42
+ }
43
+ });
44
+ });
45
+ }
46
+ exports.isRgAvailable = isRgAvailable;
47
+ function ripgrep(cwd, options) {
48
+ if (!cwd) {
49
+ return Promise.reject(new Error("No `cwd` provided"));
50
+ }
51
+ if (arguments.length === 1) {
52
+ return Promise.reject(new Error("No search term provided"));
53
+ }
54
+ let execString = "rg --json";
55
+ if ("regex" in options) {
56
+ execString = `${execString} -e ${options.regex}`;
57
+ }
58
+ else if ("string" in options) {
59
+ execString = `${execString} -F ${options.string}`;
60
+ }
61
+ if (options.fileType) {
62
+ if (!Array.isArray(options.fileType)) {
63
+ options.fileType = [options.fileType];
64
+ }
65
+ for (const fileType of options.fileType) {
66
+ execString = `${execString} -t ${fileType}`;
67
+ }
68
+ }
69
+ if (options.globs) {
70
+ execString = options.globs.reduce((command, glob) => {
71
+ return `${command} -g '${glob}'`;
72
+ }, execString);
73
+ }
74
+ if (options.multiline) {
75
+ execString = `${execString} --multiline`;
76
+ }
77
+ // https://github.com/alexlafroscia/ripgrep-js/pull/175/files
78
+ execString += ` -- ${cwd}`;
79
+ return new Promise(function (resolve, reject) {
80
+ (0, child_process_1.exec)(execString, { cwd }, (error, stdout, stderr) => {
81
+ if (!error || (error && stderr === "")) {
82
+ resolve(formatResults(stdout));
83
+ }
84
+ else {
85
+ reject(new types_1.RipGrepError(error, stderr));
86
+ }
87
+ });
88
+ });
89
+ }
90
+ exports.ripgrep = ripgrep;
@@ -0,0 +1,45 @@
1
+ /// <reference types=".pnpm/@types+node@20.14.11/node_modules/@types/node/child_process" />
2
+ /// <reference types=".pnpm/@types+node@20.16.10/node_modules/@types/node/child_process" />
3
+ import { ExecException } from "child_process";
4
+ type StringSearchOptions = {
5
+ string: string;
6
+ };
7
+ type RegexSearchOptions = {
8
+ regex: string;
9
+ };
10
+ type LocatorOptions = StringSearchOptions | RegexSearchOptions;
11
+ export type Options = LocatorOptions & {
12
+ globs?: Array<string>;
13
+ fileType?: string | Array<string>;
14
+ multiline?: boolean;
15
+ };
16
+ export type RipgrepJsonSubmatch = {
17
+ match: {
18
+ text: string;
19
+ };
20
+ start: number;
21
+ end: number;
22
+ };
23
+ export type RipGrepJsonMatch = {
24
+ type: "match";
25
+ data: {
26
+ path: {
27
+ text: string;
28
+ };
29
+ lines: {
30
+ text: string;
31
+ };
32
+ line_number: number;
33
+ absolute_offset: number;
34
+ submatches: Array<RipgrepJsonSubmatch>;
35
+ };
36
+ };
37
+ export type Match = RipGrepJsonMatch["data"];
38
+ export declare class RipGrepError {
39
+ private error;
40
+ stderr: string;
41
+ constructor(error: ExecException, stderr: string);
42
+ get message(): string;
43
+ }
44
+ export {};
45
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/tools/grep/ripgrep/types.ts"],"names":[],"mappings":";;AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9C,KAAK,mBAAmB,GAAG;IACzB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,KAAK,kBAAkB,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,cAAc,GAAG,mBAAmB,GAAG,kBAAkB,CAAC;AAE/D,MAAM,MAAM,OAAO,GAAG,cAAc,GAAG;IACrC,KAAK,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IAClC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE;QACJ,IAAI,EAAE;YACJ,IAAI,EAAE,MAAM,CAAC;SACd,CAAC;QACF,KAAK,EAAE;YACL,IAAI,EAAE,MAAM,CAAC;SACd,CAAC;QACF,WAAW,EAAE,MAAM,CAAC;QACpB,eAAe,EAAE,MAAM,CAAC;QACxB,UAAU,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;KACxC,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;AAE7C,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAAgB;IAE7B,MAAM,EAAE,MAAM,CAAC;gBAEH,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM;IAKhD,IAAI,OAAO,IAAI,MAAM,CAEpB;CACF"}
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RipGrepError = void 0;
4
+ class RipGrepError {
5
+ error;
6
+ stderr;
7
+ constructor(error, stderr) {
8
+ this.error = error;
9
+ this.stderr = stderr;
10
+ }
11
+ get message() {
12
+ return this.error.message;
13
+ }
14
+ }
15
+ exports.RipGrepError = RipGrepError;
@@ -1 +1 @@
1
- {"version":3,"file":"str_replace_editor.d.ts","sourceRoot":"","sources":["../../src/tools/str_replace_editor.ts"],"names":[],"mappings":"AAAA,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;AAED;;;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,CAmJrB;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;AAED;;;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,CA6JrB;AA+FD,eAAO,MAAM,eAAe,EAAE,IAAI,EAKjC,CAAC"}
@@ -141,15 +141,20 @@ async function strReplaceEditorExecutor(input) {
141
141
  }
142
142
  createBackup(filePath);
143
143
  content = fs_1.default.readFileSync(filePath, "utf8");
144
- if (!content.includes(input.old_str)) {
144
+ // Normalize newlines in both the content and search string
145
+ const normalizedContent = content.replace(/\r\n/g, "\n");
146
+ const normalizedOldStr = input.old_str
147
+ .replace(/\\n/g, "\n")
148
+ .replace(/\r\n/g, "\n");
149
+ if (!normalizedContent.includes(normalizedOldStr)) {
145
150
  return {
146
151
  result: `old_str not found in file: ${filePath}`,
147
152
  isError: true,
148
153
  };
149
154
  }
150
155
  else {
151
- const escapedOldStr = escapeRegExp(input.old_str);
152
- const occurences = content.match(new RegExp(escapedOldStr, "g"));
156
+ const escapedOldStr = escapeRegExp(normalizedOldStr);
157
+ const occurences = normalizedContent.match(new RegExp(escapedOldStr, "g"));
153
158
  if (occurences && occurences.length > 1) {
154
159
  // TODO: Help find unique matches
155
160
  return {
@@ -157,7 +162,7 @@ async function strReplaceEditorExecutor(input) {
157
162
  isError: true,
158
163
  };
159
164
  }
160
- newContent = content.replace(input.old_str, input.new_str);
165
+ newContent = normalizedContent.replace(normalizedOldStr, input.new_str);
161
166
  fs_1.default.writeFileSync(filePath, newContent);
162
167
  typeCheckErrors = (0, web_1.validateTypescript)(filePath);
163
168
  if (typeCheckErrors.length > 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../src/utils/exec.ts"],"names":[],"mappings":"AAQA,qBAAa,cAAc;IACzB,OAAO,CAAC,YAAY,CAA6B;IAE3C,OAAO,CACX,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GACxC,OAAO,CAAC,MAAM,CAAC;IAkDlB,SAAS,IAAI,IAAI;IASjB,SAAS,IAAI,OAAO;CAGrB;AAED,wBAAsB,GAAG,CACvB,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GACxC,OAAO,CAAC,MAAM,CAAC,CAGjB"}
1
+ {"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../src/utils/exec.ts"],"names":[],"mappings":"AAmBA,qBAAa,cAAc;IACzB,OAAO,CAAC,YAAY,CAA6B;IAE3C,OAAO,CACX,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,GACxC,OAAO,CAAC,MAAM,CAAC;IAkDlB,SAAS,IAAI,IAAI;IASjB,SAAS,IAAI,OAAO;CAGrB;AAED,wBAAsB,GAAG,CACvB,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GACxC,OAAO,CAAC,MAAM,CAAC,CAGjB"}
@@ -6,10 +6,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.cmd = exports.ProcessManager = void 0;
7
7
  const child_process_1 = require("child_process");
8
8
  const process_1 = __importDefault(require("process"));
9
- const acceptableExitCodes = [
10
- 0, // Implies successful execution (no errors)
11
- 130, // Implies user interrupted the process (for SIGINT)
12
- ];
9
+ function isAcceptableExit(exitCode, signal) {
10
+ // On Linux, code is null and signal is SIGINT
11
+ if (signal === "SIGINT") {
12
+ return true;
13
+ }
14
+ // On macOS, signal is null and exit code is 130
15
+ const acceptableExitCodes = [
16
+ 0, // Implies successful execution (no errors)
17
+ 130, // Implies user interrupted the process (for SIGINT)
18
+ ];
19
+ return acceptableExitCodes.includes(exitCode ?? 1);
20
+ }
13
21
  class ProcessManager {
14
22
  childProcess = null;
15
23
  async execute(command, options) {
@@ -43,14 +51,14 @@ class ProcessManager {
43
51
  this.childProcess = null;
44
52
  rejectFunc(err);
45
53
  });
46
- p.on("exit", async (code) => {
54
+ p.on("exit", async (code, signal) => {
47
55
  this.childProcess = null;
48
- if (!acceptableExitCodes.includes(code ?? 1)) {
56
+ if (!isAcceptableExit(code, signal)) {
49
57
  const errorMessage = errorLogs.slice(-3).join("\n");
50
58
  rejectFunc(new Error(errorMessage));
51
59
  }
52
60
  else {
53
- resolveFunc(code ?? 1);
61
+ resolveFunc(0);
54
62
  }
55
63
  });
56
64
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@empiricalrun/test-gen",
3
- "version": "0.56.2",
3
+ "version": "0.56.4",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"
@@ -62,7 +62,7 @@
62
62
  "zod": "^3.23.8",
63
63
  "@empiricalrun/llm": "^0.15.2",
64
64
  "@empiricalrun/r2-uploader": "^0.3.8",
65
- "@empiricalrun/test-run": "^0.8.3"
65
+ "@empiricalrun/test-run": "^0.8.4"
66
66
  },
67
67
  "devDependencies": {
68
68
  "@playwright/test": "1.47.1",
@@ -1 +0,0 @@
1
- {"version":3,"file":"grep.d.ts","sourceRoot":"","sources":["../../src/tools/grep.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,wBAAwB,CAAC;AAmB/D,eAAO,MAAM,QAAQ,EAAE,IAiDtB,CAAC"}
@@ -1,63 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.grepTool = void 0;
4
- const child_process_1 = require("child_process");
5
- const util_1 = require("util");
6
- const zod_1 = require("zod");
7
- const repo_tree_1 = require("../utils/repo-tree");
8
- const GrepInputSchema = zod_1.z.object({
9
- pattern: zod_1.z.string().describe("The pattern to search for"),
10
- directory: zod_1.z
11
- .string()
12
- .optional()
13
- .describe("The directory to search in (defaults to current directory)"),
14
- filePattern: zod_1.z
15
- .string()
16
- .optional()
17
- .describe("File pattern to search in (e.g., '*.ts' for TypeScript files)"),
18
- });
19
- exports.grepTool = {
20
- schema: {
21
- name: "grep",
22
- description: "Search for a pattern in files using grep (case insensitive)",
23
- parameters: GrepInputSchema,
24
- },
25
- execute: async (input) => {
26
- try {
27
- const dir = input.directory || process.cwd();
28
- // Create exclude pattern for grep
29
- const excludePatterns = repo_tree_1.DEFAULT_EXCLUDE.map((pattern) => typeof pattern === "string" ? pattern : pattern.source)
30
- .map((pattern) => `--exclude-dir="${pattern}"`)
31
- .join(" ");
32
- // Using -n to show line numbers in output
33
- let cmd = `grep -rin ${excludePatterns} "${input.pattern}" ${dir}`;
34
- if (input.filePattern) {
35
- // For file pattern searches, we'll use find with exclusions
36
- const excludeFind = repo_tree_1.DEFAULT_EXCLUDE.map((pattern) => typeof pattern === "string" ? pattern : pattern.source)
37
- .map((pattern) => `-not -path "*/${pattern}/*"`)
38
- .join(" ");
39
- // Using -n to show line numbers and removed -l to show actual matches
40
- cmd = `find ${dir} ${excludeFind} -name "${input.filePattern}" -exec grep -rin "${input.pattern}" {} \\;`;
41
- }
42
- const execAsync = (0, util_1.promisify)(child_process_1.exec);
43
- const { stdout, stderr } = await execAsync(cmd);
44
- if (stdout) {
45
- return {
46
- isError: false,
47
- result: stdout,
48
- };
49
- }
50
- return {
51
- isError: true,
52
- result: stderr,
53
- };
54
- }
55
- catch (error) {
56
- console.error("Error executing grep", error);
57
- return {
58
- isError: true,
59
- result: error instanceof Error ? error.message : String(error),
60
- };
61
- }
62
- },
63
- };