@empiricalrun/test-gen 0.71.2 → 0.72.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/dist/agent/chat/agent-loop.d.ts +11 -9
- package/dist/agent/chat/agent-loop.d.ts.map +1 -1
- package/dist/agent/chat/agent-loop.js +20 -10
- package/dist/agent/chat/exports.d.ts +2 -2
- package/dist/agent/chat/exports.d.ts.map +1 -1
- package/dist/agent/chat/exports.js +6 -1
- package/dist/agent/chat/index.d.ts.map +1 -1
- package/dist/agent/chat/index.js +48 -13
- package/dist/agent/chat/prompt/index.d.ts +2 -2
- package/dist/agent/chat/prompt/index.d.ts.map +1 -1
- package/dist/agent/chat/prompt/index.js +2 -2
- package/dist/agent/chat/prompt/repo.d.ts +2 -2
- package/dist/agent/chat/prompt/repo.d.ts.map +1 -1
- package/dist/agent/chat/prompt/repo.js +20 -11
- package/dist/agent/chat/state.d.ts +2 -2
- package/dist/agent/chat/state.d.ts.map +1 -1
- package/dist/agent/chat/types.d.ts +0 -6
- package/dist/agent/chat/types.d.ts.map +1 -1
- package/dist/agent/chat/utils/tool-calls.d.ts +21 -0
- package/dist/agent/chat/utils/tool-calls.d.ts.map +1 -0
- package/dist/agent/chat/utils/tool-calls.js +64 -0
- package/dist/agent/chat/utils.d.ts +2 -4
- package/dist/agent/chat/utils.d.ts.map +1 -1
- package/dist/agent/chat/utils.js +5 -11
- package/dist/agent/master/browser-tests/index.spec.js +1 -1
- package/dist/auth/api-client.d.ts.map +1 -1
- package/dist/auth/api-client.js +6 -2
- package/dist/bin/environments.d.ts +1 -1
- package/dist/bin/environments.d.ts.map +1 -1
- package/dist/bin/environments.js +70 -36
- package/dist/bin/index.js +1 -1
- package/dist/bin/setup.d.ts.map +1 -1
- package/dist/bin/setup.js +10 -10
- package/dist/dashboard/index.d.ts +21 -0
- package/dist/dashboard/index.d.ts.map +1 -0
- package/dist/dashboard/index.js +83 -0
- package/dist/dashboard/totp.d.ts +2 -0
- package/dist/dashboard/totp.d.ts.map +1 -0
- package/dist/dashboard/totp.js +18 -0
- package/dist/file-info/file-system.d.ts +3 -0
- package/dist/file-info/file-system.d.ts.map +1 -0
- package/dist/{utils/file-tree.js → file-info/file-system.js} +2 -8
- package/dist/file-info/github.d.ts +3 -0
- package/dist/file-info/github.d.ts.map +1 -0
- package/dist/file-info/github.js +108 -0
- package/dist/tools/commit-and-create-pr.js +2 -2
- package/dist/tools/definitions/index.d.ts +22 -0
- package/dist/tools/definitions/index.d.ts.map +1 -0
- package/dist/tools/definitions/index.js +61 -0
- package/dist/tools/definitions/run-test.d.ts +23 -0
- package/dist/tools/definitions/run-test.d.ts.map +1 -0
- package/dist/tools/definitions/run-test.js +28 -0
- package/dist/tools/definitions/str_replace_editor.d.ts +3 -0
- package/dist/tools/definitions/str_replace_editor.d.ts.map +1 -0
- package/dist/tools/definitions/str_replace_editor.js +74 -0
- package/dist/tools/definitions/test-gen-browser.d.ts +26 -0
- package/dist/tools/definitions/test-gen-browser.d.ts.map +1 -0
- package/dist/tools/definitions/test-gen-browser.js +88 -0
- package/dist/{tool-call-service/utils.d.ts → tools/definitions/utils/queue.d.ts} +6 -4
- package/dist/tools/definitions/utils/queue.d.ts.map +1 -0
- package/dist/{tool-call-service/utils.js → tools/definitions/utils/queue.js} +20 -19
- package/dist/tools/diagnosis-fetcher.js +1 -1
- package/dist/{tool-call-service → tools/executor}/index.d.ts +2 -7
- package/dist/tools/executor/index.d.ts.map +1 -0
- package/dist/{tool-call-service → tools/executor}/index.js +15 -29
- package/dist/tools/executor/utils/checkpoint.d.ts.map +1 -0
- package/dist/tools/executor/utils/git.d.ts.map +1 -0
- package/dist/{utils → tools/executor/utils}/git.js +5 -5
- package/dist/tools/executor/utils/index.d.ts.map +1 -0
- package/dist/tools/list-environments.js +1 -1
- package/dist/tools/run-test.d.ts.map +1 -1
- package/dist/tools/run-test.js +2 -23
- package/dist/tools/str_replace_editor.d.ts.map +1 -1
- package/dist/tools/str_replace_editor.js +6 -58
- package/dist/tools/test-gen-browser.d.ts.map +1 -1
- package/dist/tools/test-gen-browser.js +2 -83
- package/dist/tools/test-run-fetcher/index.js +1 -1
- package/dist/tools/upgrade-packages/index.js +2 -2
- package/dist/tools/upgrade-packages/utils.js +1 -1
- package/dist/types/index.d.ts +0 -8
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/SQSClient.d.ts +14 -0
- package/dist/utils/SQSClient.d.ts.map +1 -0
- package/dist/utils/SQSClient.js +116 -0
- package/dist/utils/repo-tree.d.ts +1 -1
- package/dist/utils/repo-tree.d.ts.map +1 -1
- package/dist/utils/repo-tree.js +7 -7
- package/package.json +16 -8
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/tool-call-service/index.d.ts.map +0 -1
- package/dist/tool-call-service/utils.d.ts.map +0 -1
- package/dist/tools/utils/index.d.ts.map +0 -1
- package/dist/utils/checkpoint.d.ts.map +0 -1
- package/dist/utils/file-tree.d.ts +0 -3
- package/dist/utils/file-tree.d.ts.map +0 -1
- package/dist/utils/git.d.ts.map +0 -1
- /package/dist/{utils → tools/executor/utils}/checkpoint.d.ts +0 -0
- /package/dist/{utils → tools/executor/utils}/checkpoint.js +0 -0
- /package/dist/{utils → tools/executor/utils}/git.d.ts +0 -0
- /package/dist/tools/{utils → executor/utils}/index.d.ts +0 -0
- /package/dist/tools/{utils → executor/utils}/index.js +0 -0
package/dist/auth/api-client.js
CHANGED
|
@@ -9,6 +9,10 @@ class APIClient {
|
|
|
9
9
|
this.appUrl = process.env.DASHBOARD_DOMAIN || "https://dash.empirical.run";
|
|
10
10
|
}
|
|
11
11
|
async request(endpoint, options = {}) {
|
|
12
|
+
const apiKey = process.env.EMPIRICALRUN_API_KEY;
|
|
13
|
+
if (apiKey) {
|
|
14
|
+
return this.makeRequest(endpoint, options, apiKey);
|
|
15
|
+
}
|
|
12
16
|
await this.ensureAuthenticated();
|
|
13
17
|
const tokens = await (0, token_store_1.getStoredTokens)();
|
|
14
18
|
if (!tokens) {
|
|
@@ -28,13 +32,13 @@ class APIClient {
|
|
|
28
32
|
}
|
|
29
33
|
return response;
|
|
30
34
|
}
|
|
31
|
-
async makeRequest(endpoint, options,
|
|
35
|
+
async makeRequest(endpoint, options, authToken) {
|
|
32
36
|
const url = endpoint.startsWith("http")
|
|
33
37
|
? endpoint
|
|
34
38
|
: `${this.appUrl}${endpoint}`;
|
|
35
39
|
// Don't set Content-Type for FormData (let browser set it automatically)
|
|
36
40
|
const headers = {
|
|
37
|
-
Authorization: `Bearer ${
|
|
41
|
+
Authorization: `Bearer ${authToken}`,
|
|
38
42
|
...options.headers,
|
|
39
43
|
};
|
|
40
44
|
// Only set Content-Type to application/json if body is not FormData
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare function listEnvironments(): Promise<void>;
|
|
1
|
+
export declare function listEnvironments(repoDir: string): Promise<void>;
|
|
2
2
|
//# sourceMappingURL=environments.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environments.d.ts","sourceRoot":"","sources":["../../src/bin/environments.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"environments.d.ts","sourceRoot":"","sources":["../../src/bin/environments.ts"],"names":[],"mappings":"AAkEA,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,MAAM,iBAqDrD"}
|
package/dist/bin/environments.js
CHANGED
|
@@ -1,12 +1,66 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.listEnvironments = listEnvironments;
|
|
4
|
+
const test_run_1 = require("@empiricalrun/test-run");
|
|
4
5
|
const api_client_1 = require("../auth/api-client");
|
|
5
6
|
const validation_1 = require("../recorder/validation");
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
async function getMatchingPlaywrightProjects(patterns, repoDir) {
|
|
8
|
+
if (patterns.length === 0) {
|
|
9
|
+
return [];
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
// Use test-run's existing logic that handles comma-separated values and all patterns
|
|
13
|
+
return await (0, test_run_1.generateProjectFilters)({
|
|
14
|
+
platform: test_run_1.Platform.WEB,
|
|
15
|
+
filteringSets: patterns,
|
|
16
|
+
repoDir,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
console.warn("Warning: Could not match Playwright projects:", error);
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function printLatestBuild(latestBuild) {
|
|
25
|
+
if (!latestBuild) {
|
|
26
|
+
console.log(` └─ No builds available`);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
console.log("");
|
|
30
|
+
const commit = latestBuild.commit
|
|
31
|
+
? latestBuild.commit.substring(0, 7)
|
|
32
|
+
: "N/A";
|
|
33
|
+
const branch = latestBuild.branch || "N/A";
|
|
34
|
+
// Calculate relative time
|
|
35
|
+
const createdAt = new Date(latestBuild.created_at);
|
|
36
|
+
const now = new Date();
|
|
37
|
+
const diffMs = now.getTime() - createdAt.getTime();
|
|
38
|
+
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
39
|
+
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
|
|
40
|
+
const diffMinutes = Math.floor(diffMs / (1000 * 60));
|
|
41
|
+
let timeAgo;
|
|
42
|
+
if (diffDays > 0) {
|
|
43
|
+
timeAgo = `${diffDays} day${diffDays > 1 ? "s" : ""} ago`;
|
|
44
|
+
}
|
|
45
|
+
else if (diffHours > 0) {
|
|
46
|
+
timeAgo = `${diffHours} hour${diffHours > 1 ? "s" : ""} ago`;
|
|
47
|
+
}
|
|
48
|
+
else if (diffMinutes > 0) {
|
|
49
|
+
timeAgo = `${diffMinutes} minute${diffMinutes > 1 ? "s" : ""} ago`;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
timeAgo = "Just now";
|
|
53
|
+
}
|
|
54
|
+
console.log(` ┌─ Latest build`);
|
|
55
|
+
console.log(` │ Commit: ${commit}`);
|
|
56
|
+
console.log(` │ Branch: ${branch}`);
|
|
57
|
+
console.log(` │ Created: ${timeAgo}`);
|
|
58
|
+
console.log(` │ URL: ${latestBuild.build_url}`);
|
|
59
|
+
console.log(` └─`);
|
|
60
|
+
}
|
|
61
|
+
async function listEnvironments(repoDir) {
|
|
8
62
|
try {
|
|
9
|
-
let repoName = await (0, validation_1.validatePackageJson)(
|
|
63
|
+
let repoName = await (0, validation_1.validatePackageJson)(repoDir);
|
|
10
64
|
const response = await api_client_1.apiClient.request(`/api/environments/list?project_repo_name=${encodeURIComponent(repoName)}`);
|
|
11
65
|
if (!response.ok) {
|
|
12
66
|
console.error(`❌ Failed to fetch environments for repo ${repoName}:`, response.statusText);
|
|
@@ -14,47 +68,27 @@ async function listEnvironments() {
|
|
|
14
68
|
}
|
|
15
69
|
const result = await response.json();
|
|
16
70
|
if (result.data?.environments && result.data.environments.length > 0) {
|
|
17
|
-
result.data.environments
|
|
18
|
-
|
|
19
|
-
|
|
71
|
+
for (const env of result.data.environments) {
|
|
72
|
+
const envIndex = result.data.environments.indexOf(env);
|
|
73
|
+
if (envIndex > 0) {
|
|
74
|
+
console.log("");
|
|
20
75
|
}
|
|
21
76
|
console.log(`Environment: ${env.name}`);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
// Calculate relative time
|
|
28
|
-
const createdAt = new Date(env.latest_build.created_at);
|
|
29
|
-
const now = new Date();
|
|
30
|
-
const diffMs = now.getTime() - createdAt.getTime();
|
|
31
|
-
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
32
|
-
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
|
|
33
|
-
const diffMinutes = Math.floor(diffMs / (1000 * 60));
|
|
34
|
-
let timeAgo;
|
|
35
|
-
if (diffDays > 0) {
|
|
36
|
-
timeAgo = `${diffDays} day${diffDays > 1 ? "s" : ""} ago`;
|
|
37
|
-
}
|
|
38
|
-
else if (diffHours > 0) {
|
|
39
|
-
timeAgo = `${diffHours} hour${diffHours > 1 ? "s" : ""} ago`;
|
|
40
|
-
}
|
|
41
|
-
else if (diffMinutes > 0) {
|
|
42
|
-
timeAgo = `${diffMinutes} minute${diffMinutes > 1 ? "s" : ""} ago`;
|
|
77
|
+
console.log(` Slug: ${env.slug}`);
|
|
78
|
+
if (env.playwright_projects && env.playwright_projects.length > 0) {
|
|
79
|
+
const matchingProjects = await getMatchingPlaywrightProjects(env.playwright_projects, repoDir);
|
|
80
|
+
if (matchingProjects.length > 0) {
|
|
81
|
+
console.log(` Playwright Projects: ${matchingProjects.join(", ")}`);
|
|
43
82
|
}
|
|
44
83
|
else {
|
|
45
|
-
|
|
84
|
+
console.log(` Playwright Projects: No matches found for patterns: ${env.playwright_projects.join(", ")}`);
|
|
46
85
|
}
|
|
47
|
-
console.log(` ┌─ Latest build`);
|
|
48
|
-
console.log(` │ Commit: ${commit}`);
|
|
49
|
-
console.log(` │ Branch: ${branch}`);
|
|
50
|
-
console.log(` │ Created: ${timeAgo}`);
|
|
51
|
-
console.log(` │ URL: ${env.latest_build.build_url}`);
|
|
52
|
-
console.log(` └─`);
|
|
53
86
|
}
|
|
54
87
|
else {
|
|
55
|
-
console.log(`
|
|
88
|
+
console.log(` Playwright Projects: None`);
|
|
56
89
|
}
|
|
57
|
-
|
|
90
|
+
printLatestBuild(env.latest_build);
|
|
91
|
+
}
|
|
58
92
|
}
|
|
59
93
|
else {
|
|
60
94
|
console.log(`No environments found for repository: ${repoName}`);
|
package/dist/bin/index.js
CHANGED
|
@@ -269,7 +269,7 @@ async function main() {
|
|
|
269
269
|
.command("environments")
|
|
270
270
|
.description("List environments and their latest builds")
|
|
271
271
|
.action(async () => {
|
|
272
|
-
await (0, environments_1.listEnvironments)();
|
|
272
|
+
await (0, environments_1.listEnvironments)(process.cwd());
|
|
273
273
|
process.exit(0);
|
|
274
274
|
});
|
|
275
275
|
program
|
package/dist/bin/setup.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/bin/setup.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/bin/setup.ts"],"names":[],"mappings":"AA2HA,wBAAsB,QAAQ,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,iBA4BhE"}
|
package/dist/bin/setup.js
CHANGED
|
@@ -48,17 +48,17 @@ async function installDependencies(targetDir) {
|
|
|
48
48
|
async function installPlaywrightBrowser(targetDir) {
|
|
49
49
|
console.log(`🎭 Installing Playwright browser...`);
|
|
50
50
|
try {
|
|
51
|
-
const { stderr
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (playwrightStderr && !playwrightStderr.includes("Installing")) {
|
|
55
|
-
console.error(`Playwright install error: ${playwrightStderr}`);
|
|
56
|
-
process.exit(1);
|
|
51
|
+
const { stderr } = await execAsync(`npx playwright install chromium --with-deps`, { cwd: targetDir });
|
|
52
|
+
if (stderr && stderr.trim()) {
|
|
53
|
+
console.warn(`⚠️ Playwright installation warnings: ${stderr.trim()}`);
|
|
57
54
|
}
|
|
58
55
|
console.log(`✅ Playwright browser installed successfully`);
|
|
59
56
|
}
|
|
60
|
-
catch (
|
|
61
|
-
|
|
57
|
+
catch (error) {
|
|
58
|
+
// execAsync already throws on non-zero exit codes
|
|
59
|
+
const errorMessage = error.message || "Unknown error";
|
|
60
|
+
const exitCode = error.code || "unknown";
|
|
61
|
+
console.error(`❌ Failed to install Playwright browser (exit code: ${exitCode}): ${errorMessage}`);
|
|
62
62
|
process.exit(1);
|
|
63
63
|
}
|
|
64
64
|
}
|
|
@@ -73,8 +73,8 @@ async function cleanUpRepoCredSetup(repoPath) {
|
|
|
73
73
|
}
|
|
74
74
|
async function setupRepoCredentials(repoPath) {
|
|
75
75
|
console.log(`🔑 Setting up repository credentials...`);
|
|
76
|
-
const helperCommand =
|
|
77
|
-
await execAsync(`git config credential."https://github.com".helper
|
|
76
|
+
const helperCommand = `"!npx @empiricalrun/test-gen github-token --raw"`;
|
|
77
|
+
await execAsync(`git config credential."https://github.com".helper ${helperCommand}`, { cwd: repoPath });
|
|
78
78
|
console.log(`✅ Repository credentials configured`);
|
|
79
79
|
}
|
|
80
80
|
async function validateAndSetupRepo(repoPath) {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare class HTTPError extends Error {
|
|
2
|
+
status: number;
|
|
3
|
+
constructor(message: string, status: number);
|
|
4
|
+
}
|
|
5
|
+
export declare class NonRetryableHTTPError extends HTTPError {
|
|
6
|
+
}
|
|
7
|
+
export declare class RetryableHTTPError extends HTTPError {
|
|
8
|
+
}
|
|
9
|
+
export interface RequestOptions {
|
|
10
|
+
params?: Record<string, string>;
|
|
11
|
+
body?: Record<string, unknown>;
|
|
12
|
+
method: "GET" | "POST";
|
|
13
|
+
headers?: Record<string, string>;
|
|
14
|
+
}
|
|
15
|
+
export declare function makeAuthenticatedRequest<T>(url: string, options: RequestOptions, secretKey?: string, dashboardDomain?: string): Promise<T>;
|
|
16
|
+
export declare function callGitHubProxy({ method, url, body, }: {
|
|
17
|
+
method: "GET" | "POST";
|
|
18
|
+
url: string;
|
|
19
|
+
body?: any;
|
|
20
|
+
}): Promise<unknown>;
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dashboard/index.ts"],"names":[],"mappings":"AAIA,qBAAa,SAAU,SAAQ,KAAK;IAClC,MAAM,EAAE,MAAM,CAAC;gBACH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAI5C;AAED,qBAAa,qBAAsB,SAAQ,SAAS;CAAG;AAEvD,qBAAa,kBAAmB,SAAQ,SAAS;CAAG;AAEpD,MAAM,WAAW,cAAc;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,MAAM,EAAE,KAAK,GAAG,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,wBAAsB,wBAAwB,CAAC,CAAC,EAC9C,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,cAAc,EACvB,SAAS,CAAC,EAAE,MAAM,EAClB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,CAAC,CAAC,CAqDZ;AAED,wBAAsB,eAAe,CAAC,EACpC,MAAM,EACN,GAAG,EACH,IAAI,GACL,EAAE;IACD,MAAM,EAAE,KAAK,GAAG,MAAM,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,GAAG,CAAC;CACZ,oBAYA"}
|
|
@@ -0,0 +1,83 @@
|
|
|
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.RetryableHTTPError = exports.NonRetryableHTTPError = exports.HTTPError = void 0;
|
|
7
|
+
exports.makeAuthenticatedRequest = makeAuthenticatedRequest;
|
|
8
|
+
exports.callGitHubProxy = callGitHubProxy;
|
|
9
|
+
const async_retry_1 = __importDefault(require("async-retry"));
|
|
10
|
+
const totp_1 = require("./totp");
|
|
11
|
+
class HTTPError extends Error {
|
|
12
|
+
status;
|
|
13
|
+
constructor(message, status) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.status = status;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
exports.HTTPError = HTTPError;
|
|
19
|
+
class NonRetryableHTTPError extends HTTPError {
|
|
20
|
+
}
|
|
21
|
+
exports.NonRetryableHTTPError = NonRetryableHTTPError;
|
|
22
|
+
class RetryableHTTPError extends HTTPError {
|
|
23
|
+
}
|
|
24
|
+
exports.RetryableHTTPError = RetryableHTTPError;
|
|
25
|
+
async function makeAuthenticatedRequest(url, options, secretKey, dashboardDomain) {
|
|
26
|
+
const baseUrl = dashboardDomain || process.env.DASHBOARD_DOMAIN;
|
|
27
|
+
const fullUrl = new URL(url, baseUrl);
|
|
28
|
+
return await (0, async_retry_1.default)(async (bail) => {
|
|
29
|
+
if (options.params) {
|
|
30
|
+
Object.entries(options.params).forEach(([key, value]) => {
|
|
31
|
+
fullUrl.searchParams.append(key, value);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
const headers = {
|
|
35
|
+
...options.headers,
|
|
36
|
+
"Content-Type": "application/json",
|
|
37
|
+
};
|
|
38
|
+
if (!headers["Authorization"]) {
|
|
39
|
+
// Use API key auth if provided, else use TOTP
|
|
40
|
+
const totp = await (0, totp_1.getTOTP)(secretKey);
|
|
41
|
+
headers["X-Empirical-Auth-TOTP"] = totp;
|
|
42
|
+
}
|
|
43
|
+
const response = await fetch(fullUrl.toString(), {
|
|
44
|
+
headers,
|
|
45
|
+
method: options.method,
|
|
46
|
+
body: options.body ? JSON.stringify(options.body) : undefined,
|
|
47
|
+
});
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
let error;
|
|
50
|
+
const msg = `HTTP error in ${options.method} request to ${fullUrl.toString()}! Status code: ${response.status}`;
|
|
51
|
+
if (response.status < 500) {
|
|
52
|
+
// Don't retry for status codes less than 500 (client errors)
|
|
53
|
+
error = new NonRetryableHTTPError(msg, response.status);
|
|
54
|
+
bail(error);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
error = new RetryableHTTPError(msg, response.status);
|
|
59
|
+
}
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
return response.json();
|
|
63
|
+
}, {
|
|
64
|
+
retries: 3,
|
|
65
|
+
factor: 2,
|
|
66
|
+
minTimeout: 1_000,
|
|
67
|
+
maxTimeout: 5_000,
|
|
68
|
+
onRetry: (error, retryCount) => {
|
|
69
|
+
console.log(`Retrying... ${retryCount}`);
|
|
70
|
+
console.log(error);
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
async function callGitHubProxy({ method, url, body, }) {
|
|
75
|
+
return await makeAuthenticatedRequest(`${process.env.DASHBOARD_DOMAIN}/api/github/proxy`, {
|
|
76
|
+
method: "POST",
|
|
77
|
+
body: {
|
|
78
|
+
method,
|
|
79
|
+
url,
|
|
80
|
+
body,
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"totp.d.ts","sourceRoot":"","sources":["../../src/dashboard/totp.ts"],"names":[],"mappings":"AAAA,wBAAsB,OAAO,CAAC,SAAS,CAAC,EAAE,MAAM,mBAe/C"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getTOTP = getTOTP;
|
|
4
|
+
async function getTOTP(secretKey) {
|
|
5
|
+
const secret = secretKey || process.env.EMPIRICAL_TOTP_SK;
|
|
6
|
+
if (!secret) {
|
|
7
|
+
throw new Error("EMPIRICAL_TOTP_SK is not set");
|
|
8
|
+
}
|
|
9
|
+
// NOTE: Had to import dynamically to avoid ECMA Script Modules error
|
|
10
|
+
const { generateTOTP } = await import("@epic-web/totp");
|
|
11
|
+
const totp = await generateTOTP({
|
|
12
|
+
secret,
|
|
13
|
+
digits: 6,
|
|
14
|
+
period: 30,
|
|
15
|
+
algorithm: "SHA-256",
|
|
16
|
+
});
|
|
17
|
+
return totp.otp;
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-system.d.ts","sourceRoot":"","sources":["../../src/file-info/file-system.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAItD,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAgC5E"}
|
|
@@ -10,14 +10,10 @@ async function getFileInfoFromFS(directory) {
|
|
|
10
10
|
// TODO: This traverses all node_modules - can be excluded with DEFAULT_EXCLUDE
|
|
11
11
|
let currentDirName = path_1.default.basename(directory);
|
|
12
12
|
let currentDir = {
|
|
13
|
-
|
|
14
|
-
isFile: false,
|
|
13
|
+
type: "directory",
|
|
15
14
|
path: currentDirName,
|
|
16
15
|
name: currentDirName,
|
|
17
16
|
children: [],
|
|
18
|
-
getContent: async () => {
|
|
19
|
-
return "";
|
|
20
|
-
},
|
|
21
17
|
};
|
|
22
18
|
const files = await promises_1.default.readdir(directory);
|
|
23
19
|
for (const file of files) {
|
|
@@ -29,11 +25,9 @@ async function getFileInfoFromFS(directory) {
|
|
|
29
25
|
}
|
|
30
26
|
else {
|
|
31
27
|
currentDir.children.push({
|
|
32
|
-
|
|
33
|
-
isFile: true,
|
|
28
|
+
type: "file",
|
|
34
29
|
path: filePath,
|
|
35
30
|
name: file,
|
|
36
|
-
children: [],
|
|
37
31
|
getContent: async () => {
|
|
38
32
|
return await promises_1.default.readFile(filePath, "utf8");
|
|
39
33
|
},
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../../src/file-info/github.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAuFtD,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,QAAQ,CAAC,CAyFnB"}
|
|
@@ -0,0 +1,108 @@
|
|
|
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.getFileInfoFromGitHub = getFileInfoFromGitHub;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const dashboard_1 = require("../dashboard");
|
|
9
|
+
async function getFileContent(repoName, path, secretKey, dashboardDomain) {
|
|
10
|
+
// TODO: specify ref (branch name) for the chat session
|
|
11
|
+
const url = `/api/github/files?repo=${repoName}&path=${path}`;
|
|
12
|
+
const response = await (0, dashboard_1.makeAuthenticatedRequest)(url, {
|
|
13
|
+
method: "GET",
|
|
14
|
+
}, secretKey, dashboardDomain);
|
|
15
|
+
if (!response.data) {
|
|
16
|
+
throw new Error(`Unable to fetch file for FileInfo`);
|
|
17
|
+
}
|
|
18
|
+
return response.data.fileContents.content;
|
|
19
|
+
}
|
|
20
|
+
async function getContentsForDirectory({ repo, path, }, secretKey, dashboardDomain) {
|
|
21
|
+
const url = `/api/github/tree?repo=${repo}&path=${path}`;
|
|
22
|
+
const response = await (0, dashboard_1.makeAuthenticatedRequest)(url, {
|
|
23
|
+
method: "GET",
|
|
24
|
+
}, secretKey, dashboardDomain);
|
|
25
|
+
if (!response.data) {
|
|
26
|
+
throw new Error(`Unable to fetch file for FileInfo`);
|
|
27
|
+
}
|
|
28
|
+
return response.data.tree;
|
|
29
|
+
}
|
|
30
|
+
// TODO: use this helper method in the dashboard
|
|
31
|
+
async function getFileInfoFromGitHub(repoName, secretKey, dashboardDomain) {
|
|
32
|
+
const files = await getContentsForDirectory({ repo: repoName, path: "" }, secretKey, dashboardDomain);
|
|
33
|
+
const root = [];
|
|
34
|
+
const nodeMap = {};
|
|
35
|
+
if (!files) {
|
|
36
|
+
return {
|
|
37
|
+
type: "directory",
|
|
38
|
+
path: repoName,
|
|
39
|
+
name: repoName,
|
|
40
|
+
children: [],
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
files.tree.forEach((file) => {
|
|
44
|
+
if (!file.path) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const pathParts = file.path.split("/");
|
|
48
|
+
const fileName = path_1.default.basename(file.path);
|
|
49
|
+
const isFile = file.type === "blob";
|
|
50
|
+
// Create the current file/directory node
|
|
51
|
+
const currentPath = file.path;
|
|
52
|
+
const currentNode = isFile
|
|
53
|
+
? {
|
|
54
|
+
type: "file",
|
|
55
|
+
path: currentPath,
|
|
56
|
+
name: fileName,
|
|
57
|
+
getContent: async () => getFileContent(repoName, currentPath, secretKey, dashboardDomain),
|
|
58
|
+
}
|
|
59
|
+
: {
|
|
60
|
+
type: "directory",
|
|
61
|
+
path: currentPath,
|
|
62
|
+
name: fileName,
|
|
63
|
+
children: [],
|
|
64
|
+
};
|
|
65
|
+
nodeMap[currentPath] = currentNode;
|
|
66
|
+
if (pathParts.length === 1) {
|
|
67
|
+
// This is a root-level file or directory
|
|
68
|
+
root.push(currentNode);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
// This is a nested file or directory
|
|
72
|
+
const parentPath = path_1.default.dirname(currentPath);
|
|
73
|
+
// Ensure parent exists
|
|
74
|
+
if (!nodeMap[parentPath]) {
|
|
75
|
+
// Create parent directory if it doesn't exist yet
|
|
76
|
+
const parentNode = {
|
|
77
|
+
type: "directory",
|
|
78
|
+
path: parentPath,
|
|
79
|
+
name: parentPath.split("/").pop() || "",
|
|
80
|
+
children: [],
|
|
81
|
+
};
|
|
82
|
+
nodeMap[parentPath] = parentNode;
|
|
83
|
+
// Add parent to its parent or root
|
|
84
|
+
const parentPathParts = parentPath.split("/");
|
|
85
|
+
if (parentPathParts.length === 1) {
|
|
86
|
+
root.push(parentNode);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
const grandparentPath = path_1.default.dirname(parentPath);
|
|
90
|
+
if (nodeMap[grandparentPath] &&
|
|
91
|
+
nodeMap[grandparentPath].type === "directory") {
|
|
92
|
+
nodeMap[grandparentPath].children.push(parentNode);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Add current node to its parent
|
|
97
|
+
if (nodeMap[parentPath].type === "directory") {
|
|
98
|
+
nodeMap[parentPath].children.push(currentNode);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
return {
|
|
103
|
+
type: "directory",
|
|
104
|
+
path: repoName,
|
|
105
|
+
name: repoName,
|
|
106
|
+
children: root,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createPullRequestTool = void 0;
|
|
4
4
|
const child_process_1 = require("child_process");
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
|
-
const
|
|
7
|
-
const
|
|
6
|
+
const utils_1 = require("./executor/utils");
|
|
7
|
+
const git_1 = require("./executor/utils/git");
|
|
8
8
|
const createPullRequestSchema = zod_1.z.object({
|
|
9
9
|
pullRequestTitle: zod_1.z
|
|
10
10
|
.string()
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { PendingToolCall } from "@empiricalrun/llm/chat";
|
|
2
|
+
import { SupportedChatModels, ToolDefinition } from "@empiricalrun/shared-types";
|
|
3
|
+
export declare class ToolCaller {
|
|
4
|
+
tools: ToolDefinition[];
|
|
5
|
+
selectedModel: SupportedChatModels;
|
|
6
|
+
branchName: string;
|
|
7
|
+
chatSessionId: number | null;
|
|
8
|
+
workerEnv?: Record<string, string>;
|
|
9
|
+
constructor({ chatSessionId, selectedModel, branchName, workerEnv, }: {
|
|
10
|
+
chatSessionId: number | null;
|
|
11
|
+
selectedModel: SupportedChatModels;
|
|
12
|
+
branchName: string;
|
|
13
|
+
workerEnv?: Record<string, string>;
|
|
14
|
+
});
|
|
15
|
+
schemas(): {
|
|
16
|
+
name: string;
|
|
17
|
+
description: string;
|
|
18
|
+
parameters: import("zod").ZodType;
|
|
19
|
+
}[];
|
|
20
|
+
sendToQueue(requestId: string, toolCalls: PendingToolCall[]): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/definitions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9E,OAAO,EACL,mBAAmB,EACnB,cAAc,EACf,MAAM,4BAA4B,CAAC;AAcpC,qBAAa,UAAU;IACrB,KAAK,EAAE,cAAc,EAAE,CAAM;IAC7B,aAAa,EAAE,mBAAmB,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBACvB,EACV,aAAa,EACb,aAAa,EACb,UAAU,EACV,SAAS,GACV,EAAE;QACD,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;QAC7B,aAAa,EAAE,mBAAmB,CAAC;QACnC,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACpC;IAsBD,OAAO;;;;;IAID,WAAW,CACf,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,eAAe,EAAE,GAC3B,OAAO,CAAC,IAAI,CAAC;CAcjB"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ToolCaller = void 0;
|
|
4
|
+
const chat_1 = require("@empiricalrun/llm/chat");
|
|
5
|
+
const commit_and_create_pr_1 = require("../commit-and-create-pr");
|
|
6
|
+
const diagnosis_fetcher_1 = require("../diagnosis-fetcher");
|
|
7
|
+
const download_build_1 = require("../download-build");
|
|
8
|
+
const grep_1 = require("../grep");
|
|
9
|
+
const list_environments_1 = require("../list-environments");
|
|
10
|
+
const test_run_fetcher_1 = require("../test-run-fetcher");
|
|
11
|
+
const upgrade_packages_1 = require("../upgrade-packages");
|
|
12
|
+
const run_test_1 = require("./run-test");
|
|
13
|
+
const str_replace_editor_1 = require("./str_replace_editor");
|
|
14
|
+
const test_gen_browser_1 = require("./test-gen-browser");
|
|
15
|
+
const queue_1 = require("./utils/queue");
|
|
16
|
+
class ToolCaller {
|
|
17
|
+
tools = [];
|
|
18
|
+
selectedModel;
|
|
19
|
+
branchName;
|
|
20
|
+
chatSessionId;
|
|
21
|
+
workerEnv;
|
|
22
|
+
constructor({ chatSessionId, selectedModel, branchName, workerEnv, }) {
|
|
23
|
+
this.chatSessionId = chatSessionId;
|
|
24
|
+
this.selectedModel = selectedModel;
|
|
25
|
+
this.branchName = branchName;
|
|
26
|
+
this.workerEnv = workerEnv;
|
|
27
|
+
// TODO: Keep this list in sync with the ToolExecutor
|
|
28
|
+
this.tools = [
|
|
29
|
+
run_test_1.runTestTool,
|
|
30
|
+
test_gen_browser_1.generateTestWithBrowserAgent,
|
|
31
|
+
grep_1.grepTool,
|
|
32
|
+
test_run_fetcher_1.fetchTestRunReportTool,
|
|
33
|
+
diagnosis_fetcher_1.fetchDiagnosisReportTool,
|
|
34
|
+
commit_and_create_pr_1.createPullRequestTool,
|
|
35
|
+
list_environments_1.listEnvironmentsTool,
|
|
36
|
+
download_build_1.downloadBuildTool,
|
|
37
|
+
upgrade_packages_1.upgradePackagesTool,
|
|
38
|
+
];
|
|
39
|
+
if ((0, chat_1.getProviderForModel)(this.selectedModel) !== "claude") {
|
|
40
|
+
this.tools.push(...Object.values(str_replace_editor_1.textEditorTools));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
schemas() {
|
|
44
|
+
return this.tools.map((tool) => tool.schema);
|
|
45
|
+
}
|
|
46
|
+
async sendToQueue(requestId, toolCalls) {
|
|
47
|
+
const queueUrl = (0, queue_1.getQueueUrl)(toolCalls, this.tools, this.workerEnv);
|
|
48
|
+
if (!queueUrl) {
|
|
49
|
+
throw new Error(`queueUrl is required for remote execution.`);
|
|
50
|
+
}
|
|
51
|
+
await (0, queue_1.sendToolRequestToRemoteQueue)(queueUrl, {
|
|
52
|
+
toolCalls,
|
|
53
|
+
requestId,
|
|
54
|
+
chatSessionId: this.chatSessionId,
|
|
55
|
+
selectedModel: this.selectedModel,
|
|
56
|
+
branchName: this.branchName,
|
|
57
|
+
workerEnv: this.workerEnv,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.ToolCaller = ToolCaller;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ToolDefinition } from "@empiricalrun/shared-types";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
export declare const RunTestSchema: z.ZodObject<{
|
|
4
|
+
testName: z.ZodString;
|
|
5
|
+
suites: z.ZodArray<z.ZodString, "many">;
|
|
6
|
+
filePath: z.ZodString;
|
|
7
|
+
project: z.ZodString;
|
|
8
|
+
buildUrl: z.ZodOptional<z.ZodString>;
|
|
9
|
+
}, "strip", z.ZodTypeAny, {
|
|
10
|
+
suites: string[];
|
|
11
|
+
testName: string;
|
|
12
|
+
filePath: string;
|
|
13
|
+
project: string;
|
|
14
|
+
buildUrl?: string | undefined;
|
|
15
|
+
}, {
|
|
16
|
+
suites: string[];
|
|
17
|
+
testName: string;
|
|
18
|
+
filePath: string;
|
|
19
|
+
project: string;
|
|
20
|
+
buildUrl?: string | undefined;
|
|
21
|
+
}>;
|
|
22
|
+
export declare const runTestTool: ToolDefinition;
|
|
23
|
+
//# sourceMappingURL=run-test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-test.d.ts","sourceRoot":"","sources":["../../../src/tools/definitions/run-test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;EAmBxB,CAAC;AAEH,eAAO,MAAM,WAAW,EAAE,cAOzB,CAAC"}
|