@empiricalrun/test-gen 0.64.3 → 0.66.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 (91) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/dist/agent/browsing/run.d.ts +6 -4
  3. package/dist/agent/browsing/run.d.ts.map +1 -1
  4. package/dist/agent/browsing/run.js +10 -9
  5. package/dist/agent/chat/agent-loop.d.ts +2 -1
  6. package/dist/agent/chat/agent-loop.d.ts.map +1 -1
  7. package/dist/agent/chat/exports.d.ts +2 -2
  8. package/dist/agent/chat/exports.d.ts.map +1 -1
  9. package/dist/agent/chat/index.d.ts +2 -3
  10. package/dist/agent/chat/index.d.ts.map +1 -1
  11. package/dist/agent/chat/index.js +23 -5
  12. package/dist/agent/chat/models.d.ts +1 -1
  13. package/dist/agent/chat/models.d.ts.map +1 -1
  14. package/dist/agent/chat/state.d.ts +2 -2
  15. package/dist/agent/chat/state.d.ts.map +1 -1
  16. package/dist/agent/chat/utils.d.ts +2 -1
  17. package/dist/agent/chat/utils.d.ts.map +1 -1
  18. package/dist/agent/cua/computer.js +1 -1
  19. package/dist/agent/cua/index.d.ts +10 -3
  20. package/dist/agent/cua/index.d.ts.map +1 -1
  21. package/dist/agent/cua/index.js +71 -34
  22. package/dist/agent/cua/model.d.ts +7 -0
  23. package/dist/agent/cua/model.d.ts.map +1 -1
  24. package/dist/agent/cua/model.js +10 -0
  25. package/dist/agent/cua/pw-codegen/pw-pause/index.d.ts +7 -5
  26. package/dist/agent/cua/pw-codegen/pw-pause/index.d.ts.map +1 -1
  27. package/dist/agent/cua/pw-codegen/pw-pause/index.js +57 -29
  28. package/dist/agent/cua/pw-codegen/pw-pause/ipc.d.ts +3 -0
  29. package/dist/agent/cua/pw-codegen/pw-pause/ipc.d.ts.map +1 -0
  30. package/dist/agent/cua/pw-codegen/pw-pause/ipc.js +13 -0
  31. package/dist/agent/cua/pw-codegen/pw-pause/{utils.d.ts → patch.d.ts} +4 -11
  32. package/dist/agent/cua/pw-codegen/pw-pause/patch.d.ts.map +1 -0
  33. package/dist/agent/cua/pw-codegen/pw-pause/{utils.js → patch.js} +49 -3
  34. package/dist/bin/index.js +3 -5
  35. package/dist/bin/utils/index.d.ts +1 -2
  36. package/dist/bin/utils/index.d.ts.map +1 -1
  37. package/dist/bin/utils/index.js +5 -3
  38. package/dist/file/client.d.ts +2 -8
  39. package/dist/file/client.d.ts.map +1 -1
  40. package/dist/file/client.js +2 -23
  41. package/dist/file/server.d.ts +15 -3
  42. package/dist/file/server.d.ts.map +1 -1
  43. package/dist/file/server.js +17 -28
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +6 -13
  46. package/dist/tool-call-service/index.d.ts +3 -3
  47. package/dist/tool-call-service/index.d.ts.map +1 -1
  48. package/dist/tool-call-service/index.js +6 -3
  49. package/dist/tool-call-service/utils.d.ts +4 -10
  50. package/dist/tool-call-service/utils.d.ts.map +1 -1
  51. package/dist/tool-call-service/utils.js +28 -5
  52. package/dist/tools/commit-and-create-pr.d.ts +0 -6
  53. package/dist/tools/commit-and-create-pr.d.ts.map +1 -1
  54. package/dist/tools/commit-and-create-pr.js +21 -40
  55. package/dist/tools/diagnosis-fetcher.d.ts.map +1 -1
  56. package/dist/tools/diagnosis-fetcher.js +1 -0
  57. package/dist/tools/download-build.d.ts.map +1 -1
  58. package/dist/tools/download-build.js +1 -0
  59. package/dist/tools/grep/index.d.ts.map +1 -1
  60. package/dist/tools/grep/index.js +1 -0
  61. package/dist/tools/list-environments.d.ts +3 -0
  62. package/dist/tools/list-environments.d.ts.map +1 -0
  63. package/dist/tools/list-environments.js +49 -0
  64. package/dist/tools/str_replace_editor.d.ts +3 -2
  65. package/dist/tools/str_replace_editor.d.ts.map +1 -1
  66. package/dist/tools/str_replace_editor.js +48 -7
  67. package/dist/tools/test-gen-browser.d.ts +1 -1
  68. package/dist/tools/test-gen-browser.d.ts.map +1 -1
  69. package/dist/tools/test-gen-browser.js +58 -12
  70. package/dist/tools/test-run-fetcher/index.d.ts.map +1 -1
  71. package/dist/tools/test-run-fetcher/index.js +1 -0
  72. package/dist/tools/test-run.d.ts.map +1 -1
  73. package/dist/tools/test-run.js +1 -0
  74. package/dist/tools/upgrade-packages/index.d.ts +3 -0
  75. package/dist/tools/upgrade-packages/index.d.ts.map +1 -0
  76. package/dist/tools/upgrade-packages/index.js +124 -0
  77. package/dist/tools/upgrade-packages/utils.d.ts +13 -0
  78. package/dist/tools/upgrade-packages/utils.d.ts.map +1 -0
  79. package/dist/tools/upgrade-packages/utils.js +106 -0
  80. package/dist/tools/utils/index.d.ts +50 -2
  81. package/dist/tools/utils/index.d.ts.map +1 -1
  82. package/dist/tools/utils/index.js +87 -0
  83. package/dist/utils/git.d.ts +12 -1
  84. package/dist/utils/git.d.ts.map +1 -1
  85. package/dist/utils/git.js +66 -1
  86. package/package.json +4 -4
  87. package/tsconfig.tsbuildinfo +1 -1
  88. package/dist/agent/cua/pw-codegen/pw-pause/utils.d.ts.map +0 -1
  89. package/dist/tools/environment-crud.d.ts +0 -4
  90. package/dist/tools/environment-crud.d.ts.map +0 -1
  91. package/dist/tools/environment-crud.js +0 -100
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/tool-call-service/utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,sBAMjD;AAED,wBAAsB,4BAA4B,CAChD,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE;IACP,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,mBAAmB,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;CACpB,iBAiBF"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/tool-call-service/utils.ts"],"names":[],"mappings":"AACA,OAAO,EACL,eAAe,EACf,cAAc,EACd,IAAI,EACL,MAAM,4BAA4B,CAAC;AAEpC,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,MAAM,CAOR;AAYD,wBAAgB,WAAW,CACzB,SAAS,EAAE,eAAe,EAAE,EAC5B,KAAK,EAAE,IAAI,EAAE,GACZ,MAAM,CAeR;AAED,wBAAsB,4BAA4B,CAChD,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,cAAc,iBAiBxB"}
@@ -1,14 +1,37 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.appendBranchNameToQueueUrl = appendBranchNameToQueueUrl;
3
4
  exports.getQueueUrl = getQueueUrl;
4
5
  exports.sendToolRequestToRemoteQueue = sendToolRequestToRemoteQueue;
5
6
  const client_sqs_1 = require("@aws-sdk/client-sqs");
6
- function getQueueUrl(featureFlags) {
7
- const useToolExecutionOnEcs = featureFlags.includes("useToolExecutionOnEcs");
8
- if (useToolExecutionOnEcs) {
9
- return process.env.TOOL_EXECUTION_SQS_URL_ECS;
7
+ function appendBranchNameToQueueUrl(queueUrl, branchName) {
8
+ const cleanBranchName = branchName.replace(/[/.]/g, "-");
9
+ const suffix = cleanBranchName.slice(0, 50);
10
+ const parts = queueUrl.split("/");
11
+ const queueName = parts.pop();
12
+ const queueNameWithoutFifo = queueName?.replace(/\.fifo$/, "");
13
+ return `${parts.join("/")}/${queueNameWithoutFifo}-${suffix}.fifo`;
14
+ }
15
+ function buildQueueUrlsForPreview(baseQueueUrl) {
16
+ const branch = process.env.VERCEL_GIT_COMMIT_REF;
17
+ if (!branch) {
18
+ throw new Error("VERCEL_GIT_COMMIT_REF is not set");
19
+ }
20
+ const queueUrl = appendBranchNameToQueueUrl(baseQueueUrl, branch);
21
+ console.log("queueUrl for preview", queueUrl);
22
+ return queueUrl;
23
+ }
24
+ function getQueueUrl(toolCalls, tools) {
25
+ const needsBrowser = toolCalls.some((toolCall) => tools.find((t) => t.schema.name === toolCall.name)?.needsBrowser);
26
+ const baseQueueUrl = needsBrowser
27
+ ? process.env.TOOL_EXECUTION_SQS_URL_BROWSER
28
+ : process.env.TOOL_EXECUTION_SQS_URL;
29
+ if (process.env.VERCEL_ENV !== "preview") {
30
+ return baseQueueUrl;
31
+ }
32
+ else {
33
+ return buildQueueUrlsForPreview(baseQueueUrl);
10
34
  }
11
- return process.env.TOOL_EXECUTION_SQS_URL;
12
35
  }
13
36
  async function sendToolRequestToRemoteQueue(queueUrl, payload) {
14
37
  const sqs = new client_sqs_1.SQSClient({
@@ -1,9 +1,3 @@
1
1
  import type { Tool } from "@empiricalrun/shared-types";
2
- interface GitHubRepoInfo {
3
- owner: string;
4
- repo: string;
5
- }
6
- export declare function parseGitHubUrl(url: string): GitHubRepoInfo;
7
2
  export declare const createPullRequestTool: Tool;
8
- export {};
9
3
  //# sourceMappingURL=commit-and-create-pr.d.ts.map
@@ -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,EAEV,IAAI,EAEL,MAAM,4BAA4B,CAAC;AAOpC,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAiB1D;AAiCD,eAAO,MAAM,qBAAqB,EAAE,IAkFnC,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,EAEV,IAAI,EAEL,MAAM,4BAA4B,CAAC;AAoCpC,eAAO,MAAM,qBAAqB,EAAE,IAkFnC,CAAC"}
@@ -1,25 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createPullRequestTool = void 0;
4
- exports.parseGitHubUrl = parseGitHubUrl;
5
4
  const child_process_1 = require("child_process");
6
5
  const zod_1 = require("zod");
7
6
  const git_1 = require("../utils/git");
8
7
  const utils_1 = require("./utils");
9
- function parseGitHubUrl(url) {
10
- const githubIndex = url.indexOf("github.com");
11
- if (githubIndex === -1) {
12
- throw new Error("Invalid GitHub repository URL");
13
- }
14
- const [owner, repo] = url
15
- .substring(githubIndex + "github.com/".length)
16
- .replace(".git", "")
17
- .split("/");
18
- if (!owner || !repo) {
19
- throw new Error("Invalid GitHub repository URL format - missing owner or repo");
20
- }
21
- return { owner, repo };
22
- }
23
8
  const createPullRequestSchema = zod_1.z.object({
24
9
  pullRequestTitle: zod_1.z
25
10
  .string()
@@ -51,6 +36,7 @@ Don't ask the user for this information, just come up with it yourself.
51
36
  `,
52
37
  parameters: createPullRequestSchema,
53
38
  },
39
+ needsBrowser: false,
54
40
  execute: async ({ input, repoPath, apiKey, }) => {
55
41
  try {
56
42
  const { pullRequestTitle, pullRequestDescription } = input;
@@ -60,25 +46,22 @@ Don't ask the user for this information, just come up with it yourself.
60
46
  })
61
47
  .toString()
62
48
  .trim();
63
- const { owner, repo } = parseGitHubUrl(repoUrl);
64
- const existingPRs = (await (0, utils_1.callGitHubProxy)({
65
- method: "GET",
66
- url: `https://api.github.com/repos/${owner}/${repo}/pulls`,
67
- body: {
68
- head: `${owner}:${branchName}`,
69
- state: "open",
70
- },
71
- apiKey,
72
- }));
49
+ const { owner, repo } = (0, utils_1.parseGitHubUrl)(repoUrl);
73
50
  (0, child_process_1.execSync)(`git push origin ${branchName} --set-upstream`, {
74
51
  cwd: repoPath,
75
52
  });
76
- const existingPR = existingPRs?.find((pr) => pr.head.ref === branchName);
53
+ const existingPR = await (0, utils_1.findExistingPR)({
54
+ owner,
55
+ repo,
56
+ branchName,
57
+ apiKey,
58
+ });
77
59
  if (existingPR) {
78
- await (0, utils_1.callGitHubProxy)({
79
- method: "PATCH",
80
- url: `https://api.github.com/repos/${owner}/${repo}/pulls/${existingPR.number}`,
81
- body: { body: descriptionWithTimestamp(pullRequestDescription) },
60
+ await (0, utils_1.updatePullRequest)({
61
+ owner,
62
+ repo,
63
+ prNumber: existingPR.number,
64
+ body: descriptionWithTimestamp(pullRequestDescription),
82
65
  apiKey,
83
66
  });
84
67
  return {
@@ -86,17 +69,15 @@ Don't ask the user for this information, just come up with it yourself.
86
69
  result: `Committed and pushed changes to existing PR: ${existingPR.html_url}`,
87
70
  };
88
71
  }
89
- const pr = (await (0, utils_1.callGitHubProxy)({
90
- method: "POST",
91
- url: `https://api.github.com/repos/${owner}/${repo}/pulls`,
92
- body: {
93
- title: pullRequestTitle,
94
- head: branchName,
95
- base: "main",
96
- body: descriptionWithTimestamp(pullRequestDescription),
97
- },
72
+ const pr = await (0, utils_1.createPullRequest)({
73
+ owner,
74
+ repo,
75
+ title: pullRequestTitle,
76
+ head: branchName,
77
+ base: "main",
78
+ body: descriptionWithTimestamp(pullRequestDescription),
98
79
  apiKey,
99
- }));
80
+ });
100
81
  return {
101
82
  isError: false,
102
83
  result: `Committed and pushed changes to new PR: ${pr.html_url}`,
@@ -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,4BAA4B,CAAC;AAepE,eAAO,MAAM,wBAAwB,EAAE,IAqFtC,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,4BAA4B,CAAC;AAepE,eAAO,MAAM,wBAAwB,EAAE,IAsFtC,CAAC"}
@@ -19,6 +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
+ needsBrowser: false,
22
23
  execute: async (params) => {
23
24
  const { input } = params;
24
25
  const { repoPath, apiKey } = params;
@@ -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,4BAA4B,CAAC;AACpE,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,4BAA4B,CAAC;AACpE,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,IAmC/B,CAAC"}
@@ -14,6 +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
+ needsBrowser: false,
17
18
  execute: async (params) => {
18
19
  const { input } = params;
19
20
  const { repoPath, apiKey } = params;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/grep/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,IAAI,EAGL,MAAM,4BAA4B,CAAC;AA8HpC,eAAO,MAAM,QAAQ,EAAE,IA2BtB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/grep/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,IAAI,EAGL,MAAM,4BAA4B,CAAC;AA8HpC,eAAO,MAAM,QAAQ,EAAE,IA4BtB,CAAC"}
@@ -124,6 +124,7 @@ If ripgrep is not available, it will fall back to using system grep.
124
124
  Search is case insensitive and regex patterns are not supported.`,
125
125
  parameters: GrepInputSchema,
126
126
  },
127
+ needsBrowser: false,
127
128
  execute: async ({ input, repoPath, }) => {
128
129
  if ((0, ripgrep_1.isRgAvailable)()) {
129
130
  return usingRipgrep(input, repoPath);
@@ -0,0 +1,3 @@
1
+ import type { Tool } from "@empiricalrun/shared-types";
2
+ export declare const listEnvironmentsTool: Tool;
3
+ //# sourceMappingURL=list-environments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-environments.d.ts","sourceRoot":"","sources":["../../src/tools/list-environments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,IAAI,EAEL,MAAM,4BAA4B,CAAC;AAKpC,eAAO,MAAM,oBAAoB,EAAE,IAsDlC,CAAC"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listEnvironmentsTool = void 0;
4
+ const zod_1 = require("zod");
5
+ const utils_1 = require("./utils");
6
+ exports.listEnvironmentsTool = {
7
+ schema: {
8
+ name: "listEnvironments",
9
+ description: "List all environments and their latest builds for this repository.",
10
+ parameters: zod_1.z.object({}),
11
+ },
12
+ needsBrowser: false,
13
+ execute: async ({ apiKey, }) => {
14
+ let response;
15
+ try {
16
+ response = await (0, utils_1.makeDashboardRequest)({
17
+ path: `/api/environments/list`,
18
+ method: "GET",
19
+ apiKey,
20
+ });
21
+ }
22
+ catch (error) {
23
+ return {
24
+ isError: true,
25
+ result: `Failed to make API request to fetch environments: ${error instanceof Error ? error.message : String(error)}`,
26
+ };
27
+ }
28
+ try {
29
+ const data = response;
30
+ if (data.error) {
31
+ return {
32
+ isError: true,
33
+ result: `API error while fetching environments: ${data.error.message}`,
34
+ data: data.error,
35
+ };
36
+ }
37
+ return {
38
+ result: JSON.stringify(data.data),
39
+ isError: false,
40
+ };
41
+ }
42
+ catch (error) {
43
+ return {
44
+ isError: true,
45
+ result: `Failed to parse or validate environment response data: ${error instanceof Error ? error.message : String(error)}`,
46
+ };
47
+ }
48
+ },
49
+ };
@@ -1,4 +1,4 @@
1
- import type { Tool, ToolResult } from "@empiricalrun/shared-types";
1
+ import type { CollectArtifacts, Tool, ToolResult } from "@empiricalrun/shared-types";
2
2
  interface StrReplaceInput {
3
3
  command: string;
4
4
  path: string;
@@ -12,9 +12,10 @@ interface StrReplaceInput {
12
12
  * Our implementation of Claude's built-in text editor tool
13
13
  * https://docs.anthropic.com/en/docs/build-with-claude/tool-use/text-editor-tool
14
14
  */
15
- export declare function strReplaceEditorExecutor({ input, repoPath, }: {
15
+ export declare function strReplaceEditorExecutor({ input, repoPath, collectArtifacts, }: {
16
16
  input: StrReplaceInput;
17
17
  repoPath: string;
18
+ collectArtifacts?: CollectArtifacts;
18
19
  }): Promise<ToolResult>;
19
20
  export declare const textEditorTools: Tool[];
20
21
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"str_replace_editor.d.ts","sourceRoot":"","sources":["../../src/tools/str_replace_editor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAe,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAOhF,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;AA6UD;;;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,CA2CtB;AA8HD,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":"AAAA,OAAO,KAAK,EAEV,gBAAgB,EAChB,IAAI,EAEJ,UAAU,EACX,MAAM,4BAA4B,CAAC;AAsCpC,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;AAiWD;;;GAGG;AACH,wBAAsB,wBAAwB,CAAC,EAC7C,KAAK,EACL,QAAQ,EACR,gBAAgB,GACjB,EAAE;IACD,KAAK,EAAE,eAAe,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;CACrC,GAAG,OAAO,CAAC,UAAU,CAAC,CA8CtB;AAqID,eAAO,MAAM,eAAe,EAAE,IAAI,EAKjC,CAAC"}
@@ -9,6 +9,31 @@ const fs_1 = __importDefault(require("fs"));
9
9
  const path_1 = __importDefault(require("path"));
10
10
  const zod_1 = require("zod");
11
11
  const web_1 = require("../bin/utils/platform/web");
12
+ const git_1 = require("../utils/git");
13
+ /**
14
+ * Helper function to collect git patch artifacts for file modifications
15
+ */
16
+ async function collectGitPatchArtifact(filePath, repoDir, operation, collectArtifacts) {
17
+ if (!collectArtifacts)
18
+ return;
19
+ try {
20
+ const gitPatch = operation === "create"
21
+ ? (0, git_1.getGitDiffForNewFile)(filePath, repoDir)
22
+ : (0, git_1.getGitDiff)(filePath, repoDir);
23
+ if (gitPatch.trim()) {
24
+ const patchArtifact = {
25
+ name: `${path_1.default.basename(filePath, path_1.default.extname(filePath))}_${operation}.patch`,
26
+ contentType: "text/plain",
27
+ data: Buffer.from(gitPatch, "utf-8"),
28
+ };
29
+ collectArtifacts([patchArtifact]);
30
+ }
31
+ }
32
+ catch (error) {
33
+ // Ignore git diff errors, don't fail the operation
34
+ console.warn(`Failed to generate git patch for ${filePath}:`, error);
35
+ }
36
+ }
12
37
  /**
13
38
  * While running str_replace command, we've seen LLM can struggle to send unique old_str.
14
39
  * This function tries to find unique contexts for each occurrence of old_str, so that the error
@@ -115,7 +140,7 @@ async function fileViewExecutor({ input, filePath, absoluteFilePath, }) {
115
140
  isError: false,
116
141
  };
117
142
  }
118
- async function fileCreateExecutor({ input, filePath, absoluteFilePath, repoDir, }) {
143
+ async function fileCreateExecutor({ input, filePath, absoluteFilePath, repoDir, collectArtifacts, }) {
119
144
  if (input.file_text === undefined || input.file_text === null) {
120
145
  return {
121
146
  result: "Error: file_text is required for create command",
@@ -149,6 +174,8 @@ the required directories recursively for the new file.`,
149
174
  fs_1.default.mkdirSync(parentDir, { recursive: true });
150
175
  }
151
176
  fs_1.default.writeFileSync(absoluteFilePath, input.file_text);
177
+ // Collect git patch artifact
178
+ await collectGitPatchArtifact(filePath, repoDir, "create", collectArtifacts);
152
179
  let createTypescriptResult = await (0, web_1.runTypescriptCompiler)(repoDir);
153
180
  if (!createTypescriptResult.success) {
154
181
  return {
@@ -163,7 +190,7 @@ the required directories recursively for the new file.`,
163
190
  };
164
191
  }
165
192
  }
166
- async function fileStrReplaceExecutor({ input, filePath, absoluteFilePath, repoDir, }) {
193
+ async function fileStrReplaceExecutor({ input, filePath, absoluteFilePath, repoDir, collectArtifacts, }) {
167
194
  if (!fs_1.default.existsSync(absoluteFilePath)) {
168
195
  return {
169
196
  result: `Error: File ${filePath} not found. Please provide relative file path to the Repository.`,
@@ -216,6 +243,8 @@ async function fileStrReplaceExecutor({ input, filePath, absoluteFilePath, repoD
216
243
  }
217
244
  const newContent = normalizedContent.replace(normalizedOldStr, input.new_str);
218
245
  fs_1.default.writeFileSync(absoluteFilePath, newContent);
246
+ // Collect git patch artifact
247
+ await collectGitPatchArtifact(filePath, repoDir, "replace", collectArtifacts);
219
248
  let strReplaceTypescriptResult = await (0, web_1.runTypescriptCompiler)(repoDir);
220
249
  if (!strReplaceTypescriptResult.success) {
221
250
  return {
@@ -231,7 +260,7 @@ async function fileStrReplaceExecutor({ input, filePath, absoluteFilePath, repoD
231
260
  }
232
261
  }
233
262
  }
234
- async function fileInsertExecutor({ input, filePath, absoluteFilePath, repoDir, }) {
263
+ async function fileInsertExecutor({ input, filePath, absoluteFilePath, repoDir, collectArtifacts, }) {
235
264
  if (!fs_1.default.existsSync(absoluteFilePath)) {
236
265
  return {
237
266
  result: `Error: File ${filePath} not found. Please provide relative file path to the Repository.`,
@@ -260,6 +289,8 @@ async function fileInsertExecutor({ input, filePath, absoluteFilePath, repoDir,
260
289
  }
261
290
  lines.splice(input.insert_line - 1, 0, input.new_str);
262
291
  fs_1.default.writeFileSync(absoluteFilePath, lines.join("\n"));
292
+ // Collect git patch artifact
293
+ await collectGitPatchArtifact(filePath, repoDir, "insert", collectArtifacts);
263
294
  let insertTypescriptResult = await (0, web_1.runTypescriptCompiler)(repoDir);
264
295
  if (!insertTypescriptResult.success) {
265
296
  return {
@@ -278,7 +309,7 @@ async function fileInsertExecutor({ input, filePath, absoluteFilePath, repoDir,
278
309
  * Our implementation of Claude's built-in text editor tool
279
310
  * https://docs.anthropic.com/en/docs/build-with-claude/tool-use/text-editor-tool
280
311
  */
281
- async function strReplaceEditorExecutor({ input, repoPath, }) {
312
+ async function strReplaceEditorExecutor({ input, repoPath, collectArtifacts, }) {
282
313
  const repoDir = repoPath;
283
314
  const { path: filePath } = input;
284
315
  const absoluteFilePath = path_1.default.join(repoDir, filePath);
@@ -292,6 +323,7 @@ async function strReplaceEditorExecutor({ input, repoPath, }) {
292
323
  filePath,
293
324
  absoluteFilePath,
294
325
  repoDir,
326
+ collectArtifacts,
295
327
  });
296
328
  case "str_replace":
297
329
  return fileStrReplaceExecutor({
@@ -299,6 +331,7 @@ async function strReplaceEditorExecutor({ input, repoPath, }) {
299
331
  filePath,
300
332
  absoluteFilePath,
301
333
  repoDir,
334
+ collectArtifacts,
302
335
  });
303
336
  case "insert":
304
337
  return fileInsertExecutor({
@@ -306,6 +339,7 @@ async function strReplaceEditorExecutor({ input, repoPath, }) {
306
339
  filePath,
307
340
  absoluteFilePath,
308
341
  repoDir,
342
+ collectArtifacts,
309
343
  });
310
344
  case "undo_edit":
311
345
  return {
@@ -340,6 +374,7 @@ File contents are returned with line numbers, starting from 1.
340
374
  path: zod_1.z.string().describe("The path to the file or directory to view."),
341
375
  }),
342
376
  },
377
+ needsBrowser: false,
343
378
  execute: async (params) => {
344
379
  const { input } = params;
345
380
  const { repoPath } = params;
@@ -364,9 +399,10 @@ directories "tests", "tests/example", and "tests/example/foo.spec.ts".`,
364
399
  file_text: zod_1.z.string().describe("The contents of the new file."),
365
400
  }),
366
401
  },
402
+ needsBrowser: false,
367
403
  execute: async (params) => {
368
404
  const { input } = params;
369
- const { repoPath } = params;
405
+ const { repoPath, collectArtifacts } = params;
370
406
  return strReplaceEditorExecutor({
371
407
  input: {
372
408
  command: "create",
@@ -374,6 +410,7 @@ directories "tests", "tests/example", and "tests/example/foo.spec.ts".`,
374
410
  file_text: input.file_text,
375
411
  },
376
412
  repoPath,
413
+ collectArtifacts,
377
414
  });
378
415
  },
379
416
  };
@@ -388,9 +425,10 @@ in the file. If old_str is not unique, the tool will return an error.`,
388
425
  new_str: zod_1.z.string().describe("The string to replace old_str with."),
389
426
  }),
390
427
  },
428
+ needsBrowser: false,
391
429
  execute: async (params) => {
392
430
  const { input } = params;
393
- const { repoPath } = params;
431
+ const { repoPath, collectArtifacts } = params;
394
432
  return strReplaceEditorExecutor({
395
433
  input: {
396
434
  command: "str_replace",
@@ -399,6 +437,7 @@ in the file. If old_str is not unique, the tool will return an error.`,
399
437
  new_str: input.new_str,
400
438
  },
401
439
  repoPath,
440
+ collectArtifacts,
402
441
  });
403
442
  },
404
443
  };
@@ -418,9 +457,10 @@ To insert a string at the end of the file, you should use insert_line = (total l
418
457
  new_str: zod_1.z.string().describe("The string to insert."),
419
458
  }),
420
459
  },
460
+ needsBrowser: false,
421
461
  execute: async (params) => {
422
462
  const { input } = params;
423
- const { repoPath } = params;
463
+ const { repoPath, collectArtifacts } = params;
424
464
  return strReplaceEditorExecutor({
425
465
  input: {
426
466
  command: "insert",
@@ -429,6 +469,7 @@ To insert a string at the end of the file, you should use insert_line = (total l
429
469
  new_str: input.new_str,
430
470
  },
431
471
  repoPath,
472
+ collectArtifacts,
432
473
  });
433
474
  },
434
475
  };
@@ -1,3 +1,3 @@
1
- import { Tool } from "@empiricalrun/shared-types";
1
+ import type { Tool } from "@empiricalrun/shared-types";
2
2
  export declare const generateTestWithBrowserAgent: Tool;
3
3
  //# sourceMappingURL=test-gen-browser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"test-gen-browser.d.ts","sourceRoot":"","sources":["../../src/tools/test-gen-browser.ts"],"names":[],"mappings":"AACA,OAAO,EAAoB,IAAI,EAAE,MAAM,4BAA4B,CAAC;AAmGpE,eAAO,MAAM,4BAA4B,EAAE,IA0I1C,CAAC"}
1
+ {"version":3,"file":"test-gen-browser.d.ts","sourceRoot":"","sources":["../../src/tools/test-gen-browser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,IAAI,EAGL,MAAM,4BAA4B,CAAC;AAoGpC,eAAO,MAAM,4BAA4B,EAAE,IAoM1C,CAAC"}
@@ -95,7 +95,8 @@ exports.generateTestWithBrowserAgent = {
95
95
  description: BROWSER_AGENT_DESCRIPTION,
96
96
  parameters: BrowserAgentSchema,
97
97
  },
98
- execute: async ({ input, repoPath, trace, collectArtifacts, environmentOverrides = {}, }) => {
98
+ needsBrowser: true,
99
+ execute: async ({ input, repoPath, trace, collectArtifacts, environmentOverrides = {}, featureFlags, }) => {
99
100
  const { filePath, project } = input;
100
101
  const absoluteFilePath = path_1.default.join(repoPath, filePath);
101
102
  if (!fs_1.default.existsSync(absoluteFilePath)) {
@@ -159,9 +160,17 @@ exports.generateTestWithBrowserAgent = {
159
160
  BUILD_URL: input.buildUrl,
160
161
  };
161
162
  }
163
+ if (featureFlags.includes("headed_codegen_in_browser_agent")) {
164
+ // Running browser agent in headed implies using page.pause method for codegen
165
+ // which improves codegen quality when script injection fails (iframes, etc.)
166
+ envOverrides = {
167
+ ...envOverrides,
168
+ RUN_PLAYWRIGHT_HEADED: "true",
169
+ };
170
+ }
162
171
  const testGenToken = (0, scenarios_1.buildTokenFromOptions)({ name: testName, file: filePath, prompt: input.changeToMake }, { useComputerUseAgent: true });
163
172
  console.log("[generateTestWithBrowserAgent] Validations passed, starting agent");
164
- const toolResult = await (0, run_1.generateTestsUsingMasterAgent)({
173
+ const agentResult = await (0, run_1.runBrowsingAgent)({
165
174
  testCaseName: testName,
166
175
  testCaseSuites: testSuites,
167
176
  testFilePath: filePath,
@@ -176,27 +185,64 @@ exports.generateTestWithBrowserAgent = {
176
185
  // Cleanup: Undo the TODO -> createTest changes
177
186
  await (0, pw_pause_1.revertToOriginalPwCode)(repoPath);
178
187
  fs_1.default.writeFileSync(absoluteFilePath, fileBackup, "utf-8");
179
- const { isError, error, actionsSummary, artifacts } = toolResult;
188
+ const { isError, error, result: toolResult, artifacts, usage, } = agentResult;
180
189
  if (artifacts) {
181
190
  void collectArtifacts?.(artifacts);
182
191
  }
183
- if (!isError) {
192
+ if (isError || !toolResult) {
184
193
  return {
185
194
  isError,
186
- result: `Browser agent has finished running. Here is the summary of actions it took
187
- and the generated Playwright code:
188
-
189
- ${actionsSummary}
195
+ result: `Browser agent failed to run successfully. Here is the error:
196
+ ${error}
190
197
  `,
191
198
  };
192
199
  }
200
+ let result = [
201
+ {
202
+ type: "text",
203
+ text: "Browser agent has finished running. Here is the summary of actions it took, and the generated Playwright code:",
204
+ },
205
+ ...toolResult.map((item) => {
206
+ if (item.type === "text") {
207
+ return {
208
+ type: "text",
209
+ text: item.text,
210
+ };
211
+ }
212
+ else if (item.type === "screenshot") {
213
+ const bufferData = Buffer.isBuffer(item.screenshot.data)
214
+ ? item.screenshot.data
215
+ : Buffer.from(item.screenshot.data);
216
+ return {
217
+ type: "image/png",
218
+ base64Data: `${bufferData.toString("base64")}`,
219
+ };
220
+ }
221
+ else {
222
+ return {
223
+ type: "text",
224
+ text: `Unknown item type: ${item}`,
225
+ };
226
+ }
227
+ }),
228
+ ];
229
+ const isMultiModalEnabled = featureFlags.includes("multi_modal_tool_result_from_browser_agent");
230
+ if (isMultiModalEnabled) {
231
+ return {
232
+ isError,
233
+ result,
234
+ usage,
235
+ };
236
+ }
193
237
  else {
238
+ const textOnlyResult = result
239
+ .filter((item) => item.type === "text")
240
+ .map((item) => item.text)
241
+ .join("\n");
194
242
  return {
195
243
  isError,
196
- result: `Browser agent failed to run successfully. Here is the error:
197
-
198
- ${error}
199
- `,
244
+ result: textOnlyResult,
245
+ usage,
200
246
  };
201
247
  }
202
248
  },
@@ -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,4BAA4B,CAAC;AAcvD,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOnE;AAED,eAAO,MAAM,sBAAsB,EAAE,IA+HpC,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,4BAA4B,CAAC;AAcvD,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAOnE;AAED,eAAO,MAAM,sBAAsB,EAAE,IAgIpC,CAAC"}
@@ -24,6 +24,7 @@ exports.fetchTestRunReportTool = {
24
24
  description: "Fetch details about a test run using its URL",
25
25
  parameters: TestRunSchema,
26
26
  },
27
+ needsBrowser: false,
27
28
  execute: async ({ input, apiKey, }) => {
28
29
  const { testRunUrl } = input;
29
30
  // Remove query parameters if they exist
@@ -1 +1 @@
1
- {"version":3,"file":"test-run.d.ts","sourceRoot":"","sources":["../../src/tools/test-run.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,4BAA4B,CAAC;AAwDnE,eAAO,MAAM,WAAW,EAAE,IAoFzB,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,4BAA4B,CAAC;AAwDnE,eAAO,MAAM,WAAW,EAAE,IAqFzB,CAAC"}
@@ -47,6 +47,7 @@ exports.runTestTool = {
47
47
  description: "Run a test",
48
48
  parameters: RunTestSchema,
49
49
  },
50
+ needsBrowser: true,
50
51
  execute: async ({ input, repoPath, collectArtifacts, environmentOverrides = {}, }) => {
51
52
  let reportUrl = undefined;
52
53
  let envOverrides = { ...environmentOverrides };
@@ -0,0 +1,3 @@
1
+ import type { Tool } from "@empiricalrun/shared-types";
2
+ export declare const upgradePackagesTool: Tool;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/upgrade-packages/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,4BAA4B,CAAC;AA+BvD,eAAO,MAAM,mBAAmB,EAAE,IA+GjC,CAAC"}