@empiricalrun/test-gen 0.72.0 → 0.73.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 +19 -0
- package/dist/agent/chat/index.d.ts.map +1 -1
- package/dist/agent/chat/index.js +12 -22
- package/dist/agent/chat/prompt/index.d.ts.map +1 -1
- package/dist/agent/chat/prompt/index.js +3 -2
- package/dist/agent/code-review/prompt.d.ts +2 -0
- package/dist/agent/code-review/prompt.d.ts.map +1 -0
- package/dist/agent/code-review/prompt.js +19 -0
- package/dist/agent/codegen/create-test-block.d.ts.map +1 -1
- package/dist/agent/codegen/create-test-block.js +0 -10
- package/dist/agent/diagnosis-agent/index.d.ts.map +1 -1
- package/dist/agent/diagnosis-agent/index.js +0 -9
- package/dist/agent/master/execute-browser-action.d.ts +1 -1
- package/dist/agent/master/execute-browser-action.d.ts.map +1 -1
- package/dist/agent/master/execute-skill-action.d.ts +1 -1
- package/dist/agent/master/execute-skill-action.d.ts.map +1 -1
- package/dist/agent/master/run.d.ts.map +1 -1
- package/dist/agent/master/run.js +0 -74
- package/dist/artifacts/index.d.ts.map +1 -1
- package/dist/artifacts/index.js +18 -6
- package/dist/artifacts/utils.d.ts +2 -2
- package/dist/artifacts/utils.d.ts.map +1 -1
- package/dist/artifacts/utils.js +16 -5
- package/dist/auth/cli-auth.d.ts.map +1 -1
- package/dist/auth/cli-auth.js +3 -7
- package/dist/auth/index.d.ts +1 -2
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +2 -4
- package/dist/auth/token-store.d.ts +1 -1
- package/dist/auth/token-store.d.ts.map +1 -1
- package/dist/auth/token-store.js +3 -3
- package/dist/bin/environments.d.ts +5 -1
- package/dist/bin/environments.d.ts.map +1 -1
- package/dist/bin/environments.js +9 -11
- package/dist/bin/index.js +33 -74
- package/dist/bin/setup.d.ts +3 -1
- package/dist/bin/setup.d.ts.map +1 -1
- package/dist/bin/setup.js +6 -10
- package/dist/dashboard/client.d.ts +26 -0
- package/dist/dashboard/client.d.ts.map +1 -0
- package/dist/dashboard/client.js +185 -0
- package/dist/dashboard/index.d.ts +2 -20
- package/dist/dashboard/index.d.ts.map +1 -1
- package/dist/dashboard/index.js +7 -81
- package/dist/dashboard/totp.d.ts +1 -1
- package/dist/dashboard/totp.d.ts.map +1 -1
- package/dist/dashboard/totp.js +2 -6
- package/dist/dashboard/types.d.ts +9 -0
- package/dist/dashboard/types.d.ts.map +1 -0
- package/dist/dashboard/types.js +17 -0
- package/dist/file-info/github.d.ts +2 -2
- package/dist/file-info/github.d.ts.map +1 -1
- package/dist/file-info/github.js +9 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -9
- package/dist/recorder/env-variables.d.ts.map +1 -1
- package/dist/recorder/env-variables.js +3 -7
- package/dist/recorder/index.js +5 -5
- package/dist/recorder/request.js +4 -9
- package/dist/recorder/upload.d.ts +3 -2
- package/dist/recorder/upload.d.ts.map +1 -1
- package/dist/recorder/upload.js +20 -22
- package/dist/tools/commit-and-create-pr.d.ts.map +1 -1
- package/dist/tools/commit-and-create-pr.js +42 -35
- package/dist/tools/delete-file.d.ts +3 -0
- package/dist/tools/delete-file.d.ts.map +1 -0
- package/dist/tools/delete-file.js +83 -0
- package/dist/tools/diagnosis-fetcher.d.ts.map +1 -1
- package/dist/tools/diagnosis-fetcher.js +3 -7
- package/dist/tools/executor/index.d.ts +6 -9
- package/dist/tools/executor/index.d.ts.map +1 -1
- package/dist/tools/executor/index.js +23 -29
- package/dist/tools/executor/utils/checkpoint.d.ts +2 -2
- package/dist/tools/executor/utils/checkpoint.d.ts.map +1 -1
- package/dist/tools/executor/utils/checkpoint.js +6 -5
- package/dist/tools/executor/utils/git.d.ts +7 -12
- package/dist/tools/executor/utils/git.d.ts.map +1 -1
- package/dist/tools/executor/utils/git.js +11 -36
- package/dist/tools/executor/utils/index.d.ts +37 -21
- package/dist/tools/executor/utils/index.d.ts.map +1 -1
- package/dist/tools/executor/utils/index.js +57 -58
- package/dist/tools/executor/utils/pr-description.d.ts +4 -0
- package/dist/tools/executor/utils/pr-description.d.ts.map +1 -0
- package/dist/tools/executor/utils/pr-description.js +24 -0
- package/dist/tools/fetch-image/index.d.ts +3 -0
- package/dist/tools/fetch-image/index.d.ts.map +1 -0
- package/dist/tools/fetch-image/index.js +56 -0
- package/dist/tools/grep/index.d.ts.map +1 -1
- package/dist/tools/grep/index.js +1 -1
- package/dist/tools/index.d.ts +4 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +60 -0
- package/dist/tools/list-environments.d.ts.map +1 -1
- package/dist/tools/list-environments.js +2 -5
- package/dist/tools/merge-conflicts.d.ts +3 -0
- package/dist/tools/merge-conflicts.d.ts.map +1 -0
- package/dist/tools/merge-conflicts.js +107 -0
- package/dist/tools/run-test.d.ts.map +1 -1
- package/dist/tools/run-test.js +2 -2
- package/dist/tools/test-run-fetcher/index.d.ts.map +1 -1
- package/dist/tools/test-run-fetcher/index.js +2 -6
- package/dist/tools/upgrade-packages/index.d.ts.map +1 -1
- package/dist/tools/upgrade-packages/index.js +10 -11
- package/dist/tools/upgrade-packages/utils.d.ts +3 -2
- package/dist/tools/upgrade-packages/utils.d.ts.map +1 -1
- package/dist/tools/upgrade-packages/utils.js +5 -8
- package/dist/tools/utils/queue.d.ts +5 -0
- package/dist/tools/utils/queue.d.ts.map +1 -0
- package/dist/tools/utils/queue.js +41 -0
- package/package.json +5 -5
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/auth/api-client.d.ts +0 -13
- package/dist/auth/api-client.d.ts.map +0 -1
- package/dist/auth/api-client.js +0 -107
- package/dist/session/index.d.ts +0 -20
- package/dist/session/index.d.ts.map +0 -1
- package/dist/session/index.js +0 -104
- package/dist/tools/definitions/index.d.ts +0 -22
- package/dist/tools/definitions/index.d.ts.map +0 -1
- package/dist/tools/definitions/index.js +0 -61
- package/dist/tools/definitions/utils/queue.d.ts +0 -8
- package/dist/tools/definitions/utils/queue.d.ts.map +0 -1
- package/dist/tools/definitions/utils/queue.js +0 -58
package/dist/auth/token-store.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.storeTokens = storeTokens;
|
|
4
|
-
exports.
|
|
4
|
+
exports.getStoredUserTokens = getStoredUserTokens;
|
|
5
5
|
exports.clearTokens = clearTokens;
|
|
6
6
|
exports.isAuthenticated = isAuthenticated;
|
|
7
7
|
const crypto_1 = require("crypto");
|
|
@@ -81,7 +81,7 @@ async function storeTokens(tokens) {
|
|
|
81
81
|
throw new Error(`Failed to store authentication tokens: ${error}`);
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
|
-
async function
|
|
84
|
+
async function getStoredUserTokens() {
|
|
85
85
|
try {
|
|
86
86
|
const dashboardDomain = getDashboardDomain();
|
|
87
87
|
const tokenStorage = await getTokenStorage();
|
|
@@ -138,7 +138,7 @@ async function clearTokens() {
|
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
async function isAuthenticated() {
|
|
141
|
-
const tokens = await
|
|
141
|
+
const tokens = await getStoredUserTokens();
|
|
142
142
|
if (!tokens)
|
|
143
143
|
return false;
|
|
144
144
|
// Check if token is not expired (with 5 minute buffer)
|
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import type { IDashboardAPIClient } from "@empiricalrun/shared-types";
|
|
2
|
+
export declare function listEnvironments({ apiClient, repoPath: repoDir, }: {
|
|
3
|
+
repoPath: string;
|
|
4
|
+
apiClient: IDashboardAPIClient;
|
|
5
|
+
}): Promise<void>;
|
|
2
6
|
//# 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":"AAAA,OAAO,KAAK,EACV,mBAAmB,EAEpB,MAAM,4BAA4B,CAAC;AAiEpC,wBAAsB,gBAAgB,CAAC,EACrC,SAAS,EACT,QAAQ,EAAE,OAAO,GAClB,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,mBAAmB,CAAC;CAChC,iBAiDA"}
|
package/dist/bin/environments.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.listEnvironments = listEnvironments;
|
|
4
4
|
const test_run_1 = require("@empiricalrun/test-run");
|
|
5
|
-
const api_client_1 = require("../auth/api-client");
|
|
6
5
|
const validation_1 = require("../recorder/validation");
|
|
7
6
|
async function getMatchingPlaywrightProjects(patterns, repoDir) {
|
|
8
7
|
if (patterns.length === 0) {
|
|
@@ -58,18 +57,17 @@ function printLatestBuild(latestBuild) {
|
|
|
58
57
|
console.log(` │ URL: ${latestBuild.build_url}`);
|
|
59
58
|
console.log(` └─`);
|
|
60
59
|
}
|
|
61
|
-
async function listEnvironments(repoDir) {
|
|
60
|
+
async function listEnvironments({ apiClient, repoPath: repoDir, }) {
|
|
62
61
|
try {
|
|
63
62
|
let repoName = await (0, validation_1.validatePackageJson)(repoDir);
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const envIndex = result.data.environments.indexOf(env);
|
|
63
|
+
const data = await apiClient.request(`/api/environments/list`, {
|
|
64
|
+
method: "GET",
|
|
65
|
+
params: { project_repo_name: repoName },
|
|
66
|
+
});
|
|
67
|
+
if (data.data?.environments && data.data.environments.length > 0) {
|
|
68
|
+
const environments = data.data.environments;
|
|
69
|
+
for (const env of environments) {
|
|
70
|
+
const envIndex = environments.indexOf(env);
|
|
73
71
|
if (envIndex > 0) {
|
|
74
72
|
console.log("");
|
|
75
73
|
}
|
package/dist/bin/index.js
CHANGED
|
@@ -18,10 +18,9 @@ const enrich_prompt_1 = require("../agent/enrich-prompt");
|
|
|
18
18
|
const infer_agent_1 = require("../agent/infer-agent");
|
|
19
19
|
const run_3 = require("../agent/planner/run");
|
|
20
20
|
const auth_1 = require("../auth");
|
|
21
|
-
const
|
|
21
|
+
const client_1 = require("../dashboard/client");
|
|
22
22
|
const recorder_1 = require("../recorder");
|
|
23
23
|
const validation_1 = require("../recorder/validation");
|
|
24
|
-
const session_1 = require("../session");
|
|
25
24
|
const test_build_1 = require("../test-build");
|
|
26
25
|
const environments_1 = require("./environments");
|
|
27
26
|
const logger_1 = require("./logger");
|
|
@@ -56,33 +55,12 @@ async function runChatAgent({ modelInput, useDiskForChatState, initialPromptPath
|
|
|
56
55
|
async function runAgentsWorkflow(testGenConfig, testGenToken) {
|
|
57
56
|
const logger = new logger_1.CustomLogger();
|
|
58
57
|
const { specPath, testCase } = testGenConfig;
|
|
59
|
-
const session = (0, session_1.getSessionDetails)();
|
|
60
|
-
const trace = llm_1.langfuseInstance?.trace({
|
|
61
|
-
name: "generate-test",
|
|
62
|
-
id: crypto.randomUUID(),
|
|
63
|
-
release: session.version,
|
|
64
|
-
tags: [
|
|
65
|
-
testGenConfig.options?.metadata.projectName || "",
|
|
66
|
-
testGenConfig.options?.metadata.environment || "",
|
|
67
|
-
].filter((s) => !!s),
|
|
68
|
-
});
|
|
69
|
-
if (await (0, session_1.shouldStopSession)()) {
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
58
|
let agentFromConfig = testGenConfig.options?.agent;
|
|
73
59
|
let agent = agentFromConfig || "auto";
|
|
74
|
-
trace?.update({
|
|
75
|
-
metadata: {
|
|
76
|
-
generationId: session.generationId,
|
|
77
|
-
sessionId: session.sessionId,
|
|
78
|
-
testUrl: session.testUrl,
|
|
79
|
-
},
|
|
80
|
-
});
|
|
81
60
|
// assuming if there is no test case specific test name, we need to update the test case name
|
|
82
61
|
if (!testCase.name) {
|
|
83
62
|
logger.success(`Generating code for the provided task. ${process.env.LOG_URL ? `[view log](${process.env.LOG_URL})` : ""}`);
|
|
84
63
|
await (0, repo_edit_1.repoEditAgent)({
|
|
85
|
-
trace,
|
|
86
64
|
task: testGenConfig.testCase.steps.join("\n"),
|
|
87
65
|
logger,
|
|
88
66
|
});
|
|
@@ -93,7 +71,6 @@ async function runAgentsWorkflow(testGenConfig, testGenToken) {
|
|
|
93
71
|
// If failure context is available, we can enrich the user prompt to contain
|
|
94
72
|
// the failure context
|
|
95
73
|
const requestedChangeResp = await (0, enrich_prompt_1.enrichPromptWithFailingLine)({
|
|
96
|
-
trace,
|
|
97
74
|
testBlock: testGenConfig.testErrorDiagnosis.failingLine,
|
|
98
75
|
testFilePath: testGenConfig.testErrorDiagnosis.failingFile,
|
|
99
76
|
suggestionForFix: testCase.steps.join("\n"),
|
|
@@ -105,7 +82,6 @@ async function runAgentsWorkflow(testGenConfig, testGenToken) {
|
|
|
105
82
|
// TODO: fix this hardcoding of user prompt - ideally its an auto fix intent
|
|
106
83
|
testCase.steps[0]?.toLowerCase().trim() == "can you please fix the test") {
|
|
107
84
|
const { task: updatedTask } = await (0, diagnosis_agent_1.createTaskUsingFailureDiagnosis)({
|
|
108
|
-
trace,
|
|
109
85
|
diagnosis: testGenConfig.testErrorDiagnosis,
|
|
110
86
|
});
|
|
111
87
|
if (updatedTask) {
|
|
@@ -116,7 +92,6 @@ async function runAgentsWorkflow(testGenConfig, testGenToken) {
|
|
|
116
92
|
if (!agent || agent === "auto") {
|
|
117
93
|
const { response } = await (0, infer_agent_1.inferAgentBasedTask)({
|
|
118
94
|
task: testCase.steps.join("\n"),
|
|
119
|
-
trace,
|
|
120
95
|
});
|
|
121
96
|
agent = response;
|
|
122
97
|
}
|
|
@@ -126,7 +101,6 @@ async function runAgentsWorkflow(testGenConfig, testGenToken) {
|
|
|
126
101
|
const plan = await (0, run_3.planTask)({
|
|
127
102
|
task,
|
|
128
103
|
specPath,
|
|
129
|
-
trace,
|
|
130
104
|
});
|
|
131
105
|
new logger_1.CustomLogger({ useReporter: false }).log("Generated Plan:");
|
|
132
106
|
console.log(plan);
|
|
@@ -135,17 +109,12 @@ async function runAgentsWorkflow(testGenConfig, testGenToken) {
|
|
|
135
109
|
await (0, run_2.generateTestWithCodegen)({
|
|
136
110
|
testCase,
|
|
137
111
|
file: specPath,
|
|
138
|
-
trace,
|
|
139
112
|
});
|
|
140
113
|
}
|
|
141
114
|
else {
|
|
142
115
|
const filePathToUpdate = await (0, utils_1.prepareFileForMasterAgent)({
|
|
143
116
|
testCase,
|
|
144
117
|
specPath,
|
|
145
|
-
trace,
|
|
146
|
-
});
|
|
147
|
-
void (0, session_1.updateSessionStatus)(testGenConfig.options?.metadata.testSessionId, {
|
|
148
|
-
status: "agent_live_session_started",
|
|
149
118
|
});
|
|
150
119
|
const projectName = await (0, run_1.convertProjectsFilterToProject)({
|
|
151
120
|
pwProjectsFilter: testGenConfig.environment?.playwrightProjects,
|
|
@@ -247,15 +216,14 @@ async function main() {
|
|
|
247
216
|
program
|
|
248
217
|
.command("repos")
|
|
249
218
|
.description("List your projects and repositories")
|
|
250
|
-
.
|
|
219
|
+
.option("--auth-type <type>", 'Use "user-access-token" or "project-api-key"', "user-access-token")
|
|
220
|
+
.action(async (opts) => {
|
|
221
|
+
const apiClient = new client_1.DashboardAPIClient({
|
|
222
|
+
authType: opts.authType,
|
|
223
|
+
});
|
|
251
224
|
try {
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
console.error("❌ Failed to fetch projects:", response.statusText);
|
|
255
|
-
process.exit(1);
|
|
256
|
-
}
|
|
257
|
-
const result = await response.json();
|
|
258
|
-
result.data.projects.forEach((project) => {
|
|
225
|
+
const data = await apiClient.request("/api/projects", { method: "GET" });
|
|
226
|
+
data.data?.projects?.forEach((project) => {
|
|
259
227
|
console.log(` ${project.repo_name}`);
|
|
260
228
|
});
|
|
261
229
|
}
|
|
@@ -265,11 +233,27 @@ async function main() {
|
|
|
265
233
|
}
|
|
266
234
|
process.exit(0);
|
|
267
235
|
});
|
|
236
|
+
program
|
|
237
|
+
.command("setup")
|
|
238
|
+
.description("Clone a repository from your projects")
|
|
239
|
+
.requiredOption("--repo-name <string>", "Name of the repository to clone")
|
|
240
|
+
.option("--auth-type <type>", 'Use "user-access-token" or "project-api-key"', "user-access-token")
|
|
241
|
+
.action(async (opts) => {
|
|
242
|
+
const apiClient = new client_1.DashboardAPIClient({
|
|
243
|
+
authType: opts.authType,
|
|
244
|
+
});
|
|
245
|
+
await (0, setup_1.runSetup)({ apiClient, repoName: opts.repoName });
|
|
246
|
+
process.exit(0);
|
|
247
|
+
});
|
|
268
248
|
program
|
|
269
249
|
.command("environments")
|
|
270
250
|
.description("List environments and their latest builds")
|
|
271
|
-
.
|
|
272
|
-
|
|
251
|
+
.option("--auth-type <type>", 'Use "user-access-token" or "project-api-key"', "user-access-token")
|
|
252
|
+
.action(async (opts) => {
|
|
253
|
+
const apiClient = new client_1.DashboardAPIClient({
|
|
254
|
+
authType: opts.authType,
|
|
255
|
+
});
|
|
256
|
+
await (0, environments_1.listEnvironments)({ apiClient, repoPath: process.cwd() });
|
|
273
257
|
process.exit(0);
|
|
274
258
|
});
|
|
275
259
|
program
|
|
@@ -304,28 +288,14 @@ async function main() {
|
|
|
304
288
|
});
|
|
305
289
|
process.exit(0);
|
|
306
290
|
});
|
|
307
|
-
program
|
|
308
|
-
.command("setup")
|
|
309
|
-
.description("Clone a repository from your projects")
|
|
310
|
-
.option("--repo-name <string>", "Name of the repository to clone")
|
|
311
|
-
.action(async (opts) => {
|
|
312
|
-
const options = await (0, utils_2.validateAndCompleteCliOptions)(opts, ["repoName"]);
|
|
313
|
-
await (0, setup_1.runSetup)({ repoName: options.repoName });
|
|
314
|
-
process.exit(0);
|
|
315
|
-
});
|
|
316
291
|
program
|
|
317
292
|
.command("fetch-chat-state")
|
|
318
293
|
.description("Fetch chat session state from the dashboard")
|
|
319
294
|
.requiredOption("--id <id>", "Chat session ID")
|
|
320
295
|
.action(async (opts) => {
|
|
321
296
|
try {
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
console.error("❌ Failed to fetch chat session:", response.statusText);
|
|
325
|
-
process.exit(1);
|
|
326
|
-
}
|
|
327
|
-
const responseData = await response.json();
|
|
328
|
-
const chatState = responseData.data.chat_session.chat_state;
|
|
297
|
+
const data = await client_1.apiClient.request(`/api/chat-sessions/${opts.id}`, { method: "GET" });
|
|
298
|
+
const chatState = data.data.chat_session.chat_state;
|
|
329
299
|
const filename = `chat-session-${opts.id}.json`;
|
|
330
300
|
fs_1.default.writeFileSync(filename, JSON.stringify(chatState, null, 2));
|
|
331
301
|
console.log(`✅ Chat state saved to ${filename}`);
|
|
@@ -347,15 +317,11 @@ async function main() {
|
|
|
347
317
|
console.error("❌ Not a valid git repo with package.json. Run this command inside a project directory.");
|
|
348
318
|
process.exit(1);
|
|
349
319
|
}
|
|
350
|
-
const
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
"Failed to fetch GitHub token for the repository";
|
|
356
|
-
throw new Error(errorMsg);
|
|
357
|
-
}
|
|
358
|
-
const { access_token } = json.data;
|
|
320
|
+
const data = await client_1.apiClient.request(`/api/projects/clone`, {
|
|
321
|
+
method: "GET",
|
|
322
|
+
params: { project_repo_name: repoName },
|
|
323
|
+
});
|
|
324
|
+
const { access_token } = data.data;
|
|
359
325
|
if (options.raw) {
|
|
360
326
|
console.log("username=x-access-token");
|
|
361
327
|
console.log(`password=${access_token}`);
|
|
@@ -378,12 +344,6 @@ async function main() {
|
|
|
378
344
|
const testGenToken = options.token
|
|
379
345
|
? options.token
|
|
380
346
|
: (0, scenarios_1.buildTokenFromOptions)(options);
|
|
381
|
-
(0, session_1.setSessionDetails)({
|
|
382
|
-
testCaseId: testGenConfig.testCase.id,
|
|
383
|
-
sessionId: testGenConfig.options?.metadata.testSessionId,
|
|
384
|
-
generationId: testGenConfig.options?.metadata.generationId,
|
|
385
|
-
projectRepoName: testGenConfig.options?.metadata.projectRepoName,
|
|
386
|
-
});
|
|
387
347
|
if (testGenConfig.build?.url) {
|
|
388
348
|
// Download the build if repo has a download script
|
|
389
349
|
await (0, test_build_1.downloadBuild)({
|
|
@@ -401,7 +361,6 @@ async function main() {
|
|
|
401
361
|
}
|
|
402
362
|
await (0, llm_1.flushAllTraces)();
|
|
403
363
|
await (0, logger_1.waitForLogsToFlush)();
|
|
404
|
-
await (0, session_1.endSession)();
|
|
405
364
|
if (testGenFailed) {
|
|
406
365
|
process.exit(1);
|
|
407
366
|
}
|
package/dist/bin/setup.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { IDashboardAPIClient } from "@empiricalrun/shared-types";
|
|
2
|
+
export declare function runSetup({ apiClient, repoName, }: {
|
|
3
|
+
apiClient: IDashboardAPIClient;
|
|
2
4
|
repoName: string;
|
|
3
5
|
}): Promise<void>;
|
|
4
6
|
//# sourceMappingURL=setup.d.ts.map
|
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":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AA2HjE,wBAAsB,QAAQ,CAAC,EAC7B,SAAS,EACT,QAAQ,GACT,EAAE;IACD,SAAS,EAAE,mBAAmB,CAAC;IAC/B,QAAQ,EAAE,MAAM,CAAC;CAClB,iBAqBA"}
|
package/dist/bin/setup.js
CHANGED
|
@@ -8,7 +8,6 @@ const child_process_1 = require("child_process");
|
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
10
|
const util_1 = require("util");
|
|
11
|
-
const api_client_1 = require("../auth/api-client");
|
|
12
11
|
const utils_1 = require("./utils");
|
|
13
12
|
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
14
13
|
async function cloneRepository(cloneUrl, repoName) {
|
|
@@ -101,17 +100,14 @@ async function validateAndSetupRepo(repoPath) {
|
|
|
101
100
|
console.error("⚠️ Authentication test failed:", error.message);
|
|
102
101
|
}
|
|
103
102
|
}
|
|
104
|
-
async function runSetup({ repoName }) {
|
|
103
|
+
async function runSetup({ apiClient, repoName, }) {
|
|
105
104
|
try {
|
|
106
105
|
console.log(`🔍 Fetching details for repository: ${repoName}`);
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
throw new Error(`Failed to fetch repository details: ${response.statusText}`);
|
|
113
|
-
}
|
|
114
|
-
const { data: repoDetails } = await response.json();
|
|
106
|
+
const data = await apiClient.request(`/api/projects/clone`, {
|
|
107
|
+
method: "GET",
|
|
108
|
+
params: { project_repo_name: repoName },
|
|
109
|
+
});
|
|
110
|
+
const { data: repoDetails } = data;
|
|
115
111
|
const { clone_url } = repoDetails;
|
|
116
112
|
console.log(`📂 Clone URL: ${(0, utils_1.cleanUpGithubUrl)(clone_url)}`);
|
|
117
113
|
const targetDir = await cloneRepository(clone_url, repoName);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { IDashboardAPIClient, RequestOptions } from "@empiricalrun/shared-types";
|
|
2
|
+
type AuthenticationType = "user-access-token" | "project-api-key" | "admin-totp";
|
|
3
|
+
export declare class DashboardAPIClient implements IDashboardAPIClient {
|
|
4
|
+
private baseUrl;
|
|
5
|
+
private authType;
|
|
6
|
+
private projectApiKey?;
|
|
7
|
+
private secretKey?;
|
|
8
|
+
constructor({ authType, projectApiKey, secretKey, baseUrl, }: {
|
|
9
|
+
authType: AuthenticationType;
|
|
10
|
+
projectApiKey?: string;
|
|
11
|
+
secretKey?: string;
|
|
12
|
+
baseUrl?: string;
|
|
13
|
+
});
|
|
14
|
+
request<T>(endpoint: string, options: RequestOptions): Promise<T>;
|
|
15
|
+
callGitHubProxy<T>({ method, url, body, }: {
|
|
16
|
+
method: "GET" | "POST" | "PATCH" | "PUT" | "DELETE";
|
|
17
|
+
url: string;
|
|
18
|
+
body?: any;
|
|
19
|
+
}): Promise<T>;
|
|
20
|
+
ensureUserIsAuthenticated(): Promise<void>;
|
|
21
|
+
private _makeRequest;
|
|
22
|
+
private refreshUserToken;
|
|
23
|
+
}
|
|
24
|
+
export declare const apiClient: DashboardAPIClient;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/dashboard/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,cAAc,EACf,MAAM,4BAA4B,CAAC;AAapC,KAAK,kBAAkB,GACnB,mBAAmB,GACnB,iBAAiB,GACjB,YAAY,CAAC;AAEjB,qBAAa,kBAAmB,YAAW,mBAAmB;IAC5D,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAqB;IACrC,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,SAAS,CAAC,CAAS;gBAEf,EACV,QAAQ,EACR,aAAa,EACb,SAAS,EACT,OAAO,GACR,EAAE;QACD,QAAQ,EAAE,kBAAkB,CAAC;QAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB;IAsBK,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC;IAmDjE,eAAe,CAAC,CAAC,EAAE,EACvB,MAAM,EACN,GAAG,EACH,IAAI,GACL,EAAE;QACD,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;QACpD,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,CAAC,EAAE,GAAG,CAAC;KACZ,GAAG,OAAO,CAAC,CAAC,CAAC;IAYR,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC;YAelC,YAAY;YAmDZ,gBAAgB;CAyC/B;AAED,eAAO,MAAM,SAAS,oBAEpB,CAAC"}
|
|
@@ -0,0 +1,185 @@
|
|
|
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.apiClient = exports.DashboardAPIClient = void 0;
|
|
7
|
+
const async_retry_1 = __importDefault(require("async-retry"));
|
|
8
|
+
const token_store_1 = require("../auth/token-store");
|
|
9
|
+
const logger_1 = require("../logger");
|
|
10
|
+
const totp_1 = require("./totp");
|
|
11
|
+
const types_1 = require("./types");
|
|
12
|
+
class DashboardAPIClient {
|
|
13
|
+
baseUrl;
|
|
14
|
+
authType;
|
|
15
|
+
projectApiKey;
|
|
16
|
+
secretKey;
|
|
17
|
+
constructor({ authType, projectApiKey, secretKey, baseUrl, }) {
|
|
18
|
+
this.baseUrl =
|
|
19
|
+
baseUrl || process.env.DASHBOARD_DOMAIN || "https://dash.empirical.run";
|
|
20
|
+
this.authType = authType;
|
|
21
|
+
if (this.authType === "project-api-key") {
|
|
22
|
+
if (!projectApiKey && !process.env.EMPIRICALRUN_API_KEY) {
|
|
23
|
+
throw new Error("Project API key is required when authentication type is 'project-api-key'");
|
|
24
|
+
}
|
|
25
|
+
this.projectApiKey = projectApiKey || process.env.EMPIRICALRUN_API_KEY;
|
|
26
|
+
}
|
|
27
|
+
else if (this.authType === "admin-totp") {
|
|
28
|
+
if (!secretKey && !process.env.EMPIRICAL_TOTP_SK) {
|
|
29
|
+
throw new Error("Secret key is required when authentication type is 'admin-totp'");
|
|
30
|
+
}
|
|
31
|
+
this.secretKey = secretKey || process.env.EMPIRICAL_TOTP_SK;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async request(endpoint, options) {
|
|
35
|
+
let response;
|
|
36
|
+
if (this.secretKey) {
|
|
37
|
+
const totp = await (0, totp_1.getTOTP)(this.secretKey);
|
|
38
|
+
const authHeader = {
|
|
39
|
+
"X-Empirical-Auth-TOTP": totp,
|
|
40
|
+
};
|
|
41
|
+
response = await this._makeRequest(endpoint, options, authHeader);
|
|
42
|
+
}
|
|
43
|
+
else if (this.projectApiKey) {
|
|
44
|
+
const authHeader = {
|
|
45
|
+
Authorization: `Bearer ${this.projectApiKey}`,
|
|
46
|
+
};
|
|
47
|
+
response = await this._makeRequest(endpoint, options, authHeader);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
await this.ensureUserIsAuthenticated();
|
|
51
|
+
const tokens = await (0, token_store_1.getStoredUserTokens)();
|
|
52
|
+
if (!tokens) {
|
|
53
|
+
throw new Error("Not authenticated. Please run the login command first.");
|
|
54
|
+
}
|
|
55
|
+
const authHeader = {
|
|
56
|
+
Authorization: `Bearer ${tokens.access_token}`,
|
|
57
|
+
};
|
|
58
|
+
response = await this._makeRequest(endpoint, options, authHeader);
|
|
59
|
+
if (response && response.status === 401) {
|
|
60
|
+
logger_1.logger.debug("Access token expired, attempting to refresh...");
|
|
61
|
+
const refreshed = await this.refreshUserToken();
|
|
62
|
+
if (refreshed) {
|
|
63
|
+
const newTokens = await (0, token_store_1.getStoredUserTokens)();
|
|
64
|
+
if (newTokens) {
|
|
65
|
+
const authHeader = {
|
|
66
|
+
Authorization: `Bearer ${newTokens.access_token}`,
|
|
67
|
+
};
|
|
68
|
+
response = this._makeRequest(endpoint, options, authHeader);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
throw new Error("Authentication failed. Please run the login command again.");
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (!response) {
|
|
75
|
+
throw new Error("No response received from the API");
|
|
76
|
+
}
|
|
77
|
+
return response.json();
|
|
78
|
+
}
|
|
79
|
+
async callGitHubProxy({ method, url, body, }) {
|
|
80
|
+
const requestBody = {
|
|
81
|
+
method,
|
|
82
|
+
url,
|
|
83
|
+
body,
|
|
84
|
+
};
|
|
85
|
+
return await this.request(`/api/github/proxy`, {
|
|
86
|
+
method: "POST",
|
|
87
|
+
body: requestBody,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
async ensureUserIsAuthenticated() {
|
|
91
|
+
if (!(await (0, token_store_1.isAuthenticated)())) {
|
|
92
|
+
const tokens = await (0, token_store_1.getStoredUserTokens)();
|
|
93
|
+
if (!tokens) {
|
|
94
|
+
throw new Error("Not authenticated. Please run the login command first.");
|
|
95
|
+
}
|
|
96
|
+
const refreshed = await this.refreshUserToken();
|
|
97
|
+
if (!refreshed) {
|
|
98
|
+
throw new Error("Session expired. Please run the login command again.");
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
async _makeRequest(endpoint, options, authHeader) {
|
|
103
|
+
const method = options.method || "GET";
|
|
104
|
+
const url = new URL(endpoint, this.baseUrl);
|
|
105
|
+
if (options.params) {
|
|
106
|
+
Object.entries(options.params).forEach(([key, value]) => {
|
|
107
|
+
url.searchParams.append(key, value);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
const headers = {
|
|
111
|
+
...authHeader,
|
|
112
|
+
"Content-Type": "application/json",
|
|
113
|
+
"User-Agent": "@empiricalrun/test-gen",
|
|
114
|
+
};
|
|
115
|
+
return await (0, async_retry_1.default)(async (bail) => {
|
|
116
|
+
const response = await fetch(url, {
|
|
117
|
+
headers,
|
|
118
|
+
method: method,
|
|
119
|
+
body: options.body ? JSON.stringify(options.body) : undefined,
|
|
120
|
+
});
|
|
121
|
+
if (!response.ok) {
|
|
122
|
+
let error;
|
|
123
|
+
const msg = `HTTP error in ${method} request to ${url}! Status code: ${response.status}`;
|
|
124
|
+
if (response.status < 500) {
|
|
125
|
+
// Don't retry for status codes less than 500 (client errors)
|
|
126
|
+
error = new types_1.NonRetryableHTTPError(msg, response.status);
|
|
127
|
+
bail(error);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
error = new types_1.RetryableHTTPError(msg, response.status);
|
|
132
|
+
}
|
|
133
|
+
throw error;
|
|
134
|
+
}
|
|
135
|
+
return response;
|
|
136
|
+
}, {
|
|
137
|
+
retries: 3,
|
|
138
|
+
factor: 2,
|
|
139
|
+
minTimeout: 1_000,
|
|
140
|
+
maxTimeout: 5_000,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
async refreshUserToken() {
|
|
144
|
+
const tokens = await (0, token_store_1.getStoredUserTokens)();
|
|
145
|
+
if (!tokens || !tokens.refresh_token) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
const response = await fetch(`${this.baseUrl}/api/cli/refresh`, {
|
|
150
|
+
method: "POST",
|
|
151
|
+
headers: {
|
|
152
|
+
"Content-Type": "application/json",
|
|
153
|
+
},
|
|
154
|
+
body: JSON.stringify({
|
|
155
|
+
refresh_token: tokens.refresh_token,
|
|
156
|
+
}),
|
|
157
|
+
});
|
|
158
|
+
if (!response.ok) {
|
|
159
|
+
const errorText = await response.text();
|
|
160
|
+
console.error("Token refresh failed:", errorText);
|
|
161
|
+
await (0, token_store_1.clearTokens)();
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
const data = await response.json();
|
|
165
|
+
await (0, token_store_1.storeTokens)({
|
|
166
|
+
access_token: data.access_token,
|
|
167
|
+
refresh_token: data.refresh_token,
|
|
168
|
+
expires_at: data.expires_at,
|
|
169
|
+
user_id: data.user?.id || tokens.user_id,
|
|
170
|
+
user_email: data.user?.email || tokens.user_email,
|
|
171
|
+
});
|
|
172
|
+
logger_1.logger.debug("Access token refreshed successfully via dashboard");
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
console.error("Token refresh error:", error);
|
|
177
|
+
await (0, token_store_1.clearTokens)();
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
exports.DashboardAPIClient = DashboardAPIClient;
|
|
183
|
+
exports.apiClient = new DashboardAPIClient({
|
|
184
|
+
authType: "user-access-token",
|
|
185
|
+
});
|
|
@@ -1,21 +1,3 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
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>;
|
|
1
|
+
export { DashboardAPIClient } from "./client";
|
|
2
|
+
export { HTTPError, NonRetryableHTTPError, RetryableHTTPError } from "./types";
|
|
21
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dashboard/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dashboard/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC"}
|