@empiricalrun/test-gen 0.66.1 → 0.67.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 +17 -0
- package/dist/agent/browsing/run.js +4 -4
- package/dist/agent/browsing/utils.d.ts +1 -0
- package/dist/agent/browsing/utils.d.ts.map +1 -1
- package/dist/agent/browsing/utils.js +5 -4
- package/dist/agent/chat/index.d.ts +1 -0
- package/dist/agent/chat/index.d.ts.map +1 -1
- package/dist/agent/chat/index.js +1 -0
- package/dist/agent/chat/prompt/index.d.ts.map +1 -1
- package/dist/agent/chat/prompt/index.js +3 -1
- package/dist/agent/cua/pw-codegen/pw-pause/for-recorder.d.ts +14 -0
- package/dist/agent/cua/pw-codegen/pw-pause/for-recorder.d.ts.map +1 -0
- package/dist/agent/cua/pw-codegen/pw-pause/for-recorder.js +62 -0
- package/dist/agent/cua/pw-codegen/pw-pause/index.d.ts.map +1 -1
- package/dist/agent/cua/pw-codegen/pw-pause/index.js +19 -15
- package/dist/agent/cua/pw-codegen/pw-pause/types.d.ts +14 -0
- package/dist/agent/cua/pw-codegen/pw-pause/types.d.ts.map +1 -0
- package/dist/agent/cua/pw-codegen/pw-pause/types.js +2 -0
- package/dist/artifacts/utils.d.ts +1 -1
- package/dist/artifacts/utils.d.ts.map +1 -1
- package/dist/artifacts/utils.js +5 -5
- package/dist/auth/api-client.d.ts +12 -0
- package/dist/auth/api-client.d.ts.map +1 -0
- package/dist/auth/api-client.js +133 -0
- package/dist/auth/cli-auth.d.ts +18 -0
- package/dist/auth/cli-auth.d.ts.map +1 -0
- package/dist/auth/cli-auth.js +184 -0
- package/dist/auth/index.d.ts +4 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +17 -0
- package/dist/auth/token-store.d.ts +15 -0
- package/dist/auth/token-store.d.ts.map +1 -0
- package/dist/auth/token-store.js +149 -0
- package/dist/bin/index.js +98 -1
- package/dist/bin/utils/index.d.ts +2 -1
- package/dist/bin/utils/index.d.ts.map +1 -1
- package/dist/bin/utils/index.js +34 -5
- package/dist/browser-injected-scripts/annotate-elements.js +1 -4
- package/dist/file/client.d.ts +1 -0
- package/dist/file/client.d.ts.map +1 -1
- package/dist/file/client.js +3 -0
- package/dist/file/server.d.ts +2 -0
- package/dist/file/server.d.ts.map +1 -1
- package/dist/file/server.js +9 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -0
- package/dist/recorder/display.d.ts +2 -0
- package/dist/recorder/display.d.ts.map +1 -0
- package/dist/recorder/display.js +50 -0
- package/dist/recorder/index.d.ts +4 -0
- package/dist/recorder/index.d.ts.map +1 -0
- package/dist/recorder/index.js +108 -0
- package/dist/recorder/request.d.ts +6 -0
- package/dist/recorder/request.d.ts.map +1 -0
- package/dist/recorder/request.js +55 -0
- package/dist/recorder/temp-files.d.ts +3 -0
- package/dist/recorder/temp-files.d.ts.map +1 -0
- package/dist/recorder/temp-files.js +39 -0
- package/dist/recorder/upload.d.ts +2 -0
- package/dist/recorder/upload.d.ts.map +1 -0
- package/dist/recorder/upload.js +85 -0
- package/dist/recorder/validation.d.ts +2 -0
- package/dist/recorder/validation.d.ts.map +1 -0
- package/dist/recorder/validation.js +24 -0
- package/package.json +2 -1
- package/tsconfig.tsbuildinfo +1 -1
package/dist/file/server.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export declare class FileServiceServer {
|
|
|
17
17
|
private artifactsInputs;
|
|
18
18
|
private result;
|
|
19
19
|
private usage;
|
|
20
|
+
private codegenSources;
|
|
20
21
|
constructor({ port, repoDir, updateFile, onComplete, }: {
|
|
21
22
|
port: number;
|
|
22
23
|
repoDir: string;
|
|
@@ -28,6 +29,7 @@ export declare class FileServiceServer {
|
|
|
28
29
|
usage: Usage | undefined;
|
|
29
30
|
};
|
|
30
31
|
getArtifactInputsFromServer(): ArtifactInput[];
|
|
32
|
+
getCodegenSources(): string | undefined;
|
|
31
33
|
setFilePath(filePath: string): void;
|
|
32
34
|
startFileService(): Promise<number>;
|
|
33
35
|
stop(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/file/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAKlE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/file/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAKlE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AASlD,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,kBAAkB,CAAC;IAC3B,KAAK,EAAE,KAAK,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,UAAU,CAAC,CAAa;IAEhC,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,KAAK,CAAoB;IAEjC,OAAO,CAAC,cAAc,CAAqB;gBAE/B,EACV,IAAI,EACJ,OAAO,EACP,UAAU,EACV,UAAU,GACX,EAAE;QACD,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,OAAO,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;KACzB;IAOD,iBAAiB;;;;IAIjB,2BAA2B;IAI3B,iBAAiB;IAIjB,WAAW,CAAC,QAAQ,EAAE,MAAM;IAItB,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;IAqEnC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAgB5B"}
|
package/dist/file/server.js
CHANGED
|
@@ -19,6 +19,7 @@ class FileServiceServer {
|
|
|
19
19
|
artifactsInputs = [];
|
|
20
20
|
result;
|
|
21
21
|
usage;
|
|
22
|
+
codegenSources;
|
|
22
23
|
constructor({ port, repoDir, updateFile, onComplete, }) {
|
|
23
24
|
this.port = port;
|
|
24
25
|
this.repoDir = repoDir;
|
|
@@ -31,6 +32,9 @@ class FileServiceServer {
|
|
|
31
32
|
getArtifactInputsFromServer() {
|
|
32
33
|
return this.artifactsInputs;
|
|
33
34
|
}
|
|
35
|
+
getCodegenSources() {
|
|
36
|
+
return this.codegenSources;
|
|
37
|
+
}
|
|
34
38
|
setFilePath(filePath) {
|
|
35
39
|
this.filePath = path_1.default.resolve(this.repoDir, filePath);
|
|
36
40
|
}
|
|
@@ -38,6 +42,11 @@ class FileServiceServer {
|
|
|
38
42
|
const app = (0, express_1.default)();
|
|
39
43
|
app.use(express_1.default.json({ limit: "50mb" }));
|
|
40
44
|
(0, ipc_1.humanLoopRoute)(app);
|
|
45
|
+
app.post("/codegen-sources", async (req) => {
|
|
46
|
+
const payload = req.body;
|
|
47
|
+
this.codegenSources = payload.map((c) => c.actions.join("\n")).join("\n");
|
|
48
|
+
console.log("[FileServiceServer] Received codegen sources", this.codegenSources);
|
|
49
|
+
});
|
|
41
50
|
app.post("/agent-results", async (req, res) => {
|
|
42
51
|
const { generatedCode, importPaths, result, usage } = req.body;
|
|
43
52
|
this.result = result;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,4 +2,5 @@ import { FrameLocator, Page } from "playwright";
|
|
|
2
2
|
import { ScopeVars } from "./types";
|
|
3
3
|
export { downloadBuild } from "./test-build";
|
|
4
4
|
export declare function createTest(task: string, pageRef: Page | FrameLocator, scope?: ScopeVars): Promise<void>;
|
|
5
|
+
export declare function recordTest(pageRef: Page): Promise<void>;
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAahD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAsB7C,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,IAAI,GAAG,YAAY,EAC5B,KAAK,CAAC,EAAE,SAAS,iBAwElB;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,IAAI,iBAY7C"}
|
package/dist/index.js
CHANGED
|
@@ -5,8 +5,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.downloadBuild = void 0;
|
|
7
7
|
exports.createTest = createTest;
|
|
8
|
+
exports.recordTest = recordTest;
|
|
8
9
|
const llm_1 = require("@empiricalrun/llm");
|
|
9
10
|
const cua_1 = require("./agent/cua");
|
|
11
|
+
const pw_pause_1 = require("./agent/cua/pw-codegen/pw-pause");
|
|
12
|
+
const for_recorder_1 = require("./agent/cua/pw-codegen/pw-pause/for-recorder");
|
|
10
13
|
const run_1 = require("./agent/master/run");
|
|
11
14
|
const scenarios_1 = require("./bin/utils/scenarios");
|
|
12
15
|
const client_1 = __importDefault(require("./file/client"));
|
|
@@ -94,3 +97,16 @@ async function createTest(task, pageRef, scope) {
|
|
|
94
97
|
await flushEvents();
|
|
95
98
|
}
|
|
96
99
|
}
|
|
100
|
+
async function recordTest(pageRef) {
|
|
101
|
+
const fileServiceClient = new client_1.default();
|
|
102
|
+
const repoDir = process.cwd();
|
|
103
|
+
const canUsePwPause = await (0, pw_pause_1.canUsePauseCodegen)(repoDir);
|
|
104
|
+
if (!canUsePwPause) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
console.log("[getCodegen] using PlaywrightPauseCodegen");
|
|
108
|
+
const codegen = new for_recorder_1.PlaywrightPauseCodegenForRecorder(async (sources) => {
|
|
109
|
+
await fileServiceClient.sendCodegenSources(sources);
|
|
110
|
+
});
|
|
111
|
+
await codegen.initialize(pageRef);
|
|
112
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display.d.ts","sourceRoot":"","sources":["../../src/recorder/display.ts"],"names":[],"mappings":"AAEA,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,MAAM,mBA+CtB"}
|
|
@@ -0,0 +1,50 @@
|
|
|
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.displayResultsAndConfirm = displayResultsAndConfirm;
|
|
7
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
8
|
+
async function displayResultsAndConfirm(name, codegenResult) {
|
|
9
|
+
let finalResult = codegenResult || "No code generated";
|
|
10
|
+
let approved = false;
|
|
11
|
+
while (!approved) {
|
|
12
|
+
// Display results in a box format
|
|
13
|
+
console.log("\n" + "=".repeat(80));
|
|
14
|
+
console.log("📝 TEST GENERATION RESULTS");
|
|
15
|
+
console.log("=".repeat(80));
|
|
16
|
+
console.log(`Test Name: ${name}`);
|
|
17
|
+
console.log("-".repeat(80));
|
|
18
|
+
console.log("Generated Code:");
|
|
19
|
+
console.log("-".repeat(80));
|
|
20
|
+
console.log(finalResult);
|
|
21
|
+
console.log("=".repeat(80));
|
|
22
|
+
// Ask user for confirmation
|
|
23
|
+
const { confirmed } = await inquirer_1.default.prompt([
|
|
24
|
+
{
|
|
25
|
+
type: "confirm",
|
|
26
|
+
name: "confirmed",
|
|
27
|
+
message: "Does this look good to you?",
|
|
28
|
+
default: true,
|
|
29
|
+
},
|
|
30
|
+
]);
|
|
31
|
+
if (confirmed) {
|
|
32
|
+
console.log("✅ Great! The test generation was successful.");
|
|
33
|
+
approved = true;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
// Open multiline editor for user to modify
|
|
37
|
+
const { editedCode } = await inquirer_1.default.prompt([
|
|
38
|
+
{
|
|
39
|
+
type: "editor",
|
|
40
|
+
name: "editedCode",
|
|
41
|
+
message: "Edit the generated code:",
|
|
42
|
+
default: finalResult,
|
|
43
|
+
},
|
|
44
|
+
]);
|
|
45
|
+
finalResult = editedCode;
|
|
46
|
+
console.log("Code updated. Let's review the changes...");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return finalResult;
|
|
50
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/recorder/index.ts"],"names":[],"mappings":"AAyCA,wBAAsB,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,iBAiF3D"}
|
|
@@ -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.runRecorder = runRecorder;
|
|
7
|
+
const test_run_1 = require("@empiricalrun/test-run");
|
|
8
|
+
const detect_port_1 = __importDefault(require("detect-port"));
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const utils_1 = require("../agent/browsing/utils");
|
|
12
|
+
const chat_1 = require("../agent/chat");
|
|
13
|
+
const pw_pause_1 = require("../agent/cua/pw-codegen/pw-pause");
|
|
14
|
+
const utils_2 = require("../artifacts/utils");
|
|
15
|
+
const server_1 = require("../file/server");
|
|
16
|
+
const display_1 = require("./display");
|
|
17
|
+
const request_1 = require("./request");
|
|
18
|
+
const temp_files_1 = require("./temp-files");
|
|
19
|
+
const upload_1 = require("./upload");
|
|
20
|
+
const validation_1 = require("./validation");
|
|
21
|
+
function extractVideoAttachments(repoDir) {
|
|
22
|
+
try {
|
|
23
|
+
const summaryPath = path_1.default.join(repoDir, "summary.json");
|
|
24
|
+
if (!fs_1.default.existsSync(summaryPath)) {
|
|
25
|
+
console.log("summary.json not found");
|
|
26
|
+
return [];
|
|
27
|
+
}
|
|
28
|
+
const summaryContent = JSON.parse(fs_1.default.readFileSync(summaryPath, "utf-8"));
|
|
29
|
+
const attachments = (0, utils_2.extractAttachmentsFromPlaywrightJSONReport)(summaryContent, "temp test");
|
|
30
|
+
const videoPaths = attachments
|
|
31
|
+
.filter((attachment) => attachment.contentType === "video/webm")
|
|
32
|
+
.map((attachment) => attachment.path);
|
|
33
|
+
return videoPaths;
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
console.warn("Error processing summary.json:", error);
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async function runRecorder({ name }) {
|
|
41
|
+
console.log(`Recording for test name: ${name}`);
|
|
42
|
+
const repoDir = process.cwd();
|
|
43
|
+
try {
|
|
44
|
+
await (0, validation_1.validate)(repoDir);
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
console.error("Error running recorder:", error);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
if (!process.env.EMPIRICALRUN_API_KEY) {
|
|
51
|
+
console.error("EMPIRICALRUN_API_KEY is not set. Please set it in your environment variables.");
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
// Prepare playwright for codegen
|
|
56
|
+
console.log("[generateTestWithBrowserAgent] Preparing playwright for codegen");
|
|
57
|
+
await (0, pw_pause_1.preparePlaywrightForCodegen)(repoDir);
|
|
58
|
+
}
|
|
59
|
+
catch (err) {
|
|
60
|
+
console.warn("[generateTestWithBrowserAgent] Error preparing playwright for codegen", err);
|
|
61
|
+
}
|
|
62
|
+
const envVariables = await (0, chat_1.fetchEnvironmentVariables)();
|
|
63
|
+
await (0, temp_files_1.createTempTestFile)();
|
|
64
|
+
const absFilePath = path_1.default.join(process.cwd(), "tests", "temp-test.spec.ts");
|
|
65
|
+
await (0, utils_1.addImportForMethod)(absFilePath, "recordTest");
|
|
66
|
+
// Start a file service for IPC with the agent (which runs in a different process)
|
|
67
|
+
const availablePort = await (0, detect_port_1.default)(3030);
|
|
68
|
+
const fileServer = new server_1.FileServiceServer({
|
|
69
|
+
port: availablePort,
|
|
70
|
+
repoDir,
|
|
71
|
+
updateFile: false,
|
|
72
|
+
});
|
|
73
|
+
await fileServer.startFileService();
|
|
74
|
+
await (0, test_run_1.runSingleTest)({
|
|
75
|
+
testName: "temp test",
|
|
76
|
+
suites: [],
|
|
77
|
+
filePath: "tests/temp-test.spec.ts",
|
|
78
|
+
projects: ["chromium"],
|
|
79
|
+
repoDir: process.cwd(),
|
|
80
|
+
envOverrides: {
|
|
81
|
+
...envVariables,
|
|
82
|
+
RUN_PLAYWRIGHT_HEADED: "true",
|
|
83
|
+
PW_CODEGEN_NO_INSPECTOR: "1",
|
|
84
|
+
IPC_FILE_SERVICE_PORT: availablePort.toString(),
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
const videoPaths = extractVideoAttachments(repoDir);
|
|
88
|
+
let attachments = [];
|
|
89
|
+
if (videoPaths.length === 0) {
|
|
90
|
+
console.warn("No video attachments found for temp test");
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
const videoUrls = await (0, upload_1.uploadVideosWithSpinner)(videoPaths, name);
|
|
94
|
+
if (videoUrls) {
|
|
95
|
+
attachments = [...attachments, ...videoUrls];
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
await (0, temp_files_1.deleteTempTestFile)();
|
|
99
|
+
await (0, pw_pause_1.revertToOriginalPwCode)(repoDir);
|
|
100
|
+
const codegenResult = fileServer.getCodegenSources();
|
|
101
|
+
await fileServer.stop();
|
|
102
|
+
const finalCode = await (0, display_1.displayResultsAndConfirm)(name, codegenResult);
|
|
103
|
+
await (0, request_1.sendToDashboardAsRequest)({
|
|
104
|
+
testName: name,
|
|
105
|
+
codegenResult: finalCode,
|
|
106
|
+
attachments,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/recorder/request.ts"],"names":[],"mappings":"AAeA,wBAAsB,wBAAwB,CAAC,EAC7C,QAAQ,EACR,aAAa,EACb,WAAW,GACZ,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,iBAKA"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sendToDashboardAsRequest = sendToDashboardAsRequest;
|
|
4
|
+
const DASHBOARD_DOMAIN = process.env.DASHBOARD_DOMAIN || "https://dash.empirical.run";
|
|
5
|
+
const title = (name) => `Add a test: ${name}`;
|
|
6
|
+
function description(codegenResult, attachments) {
|
|
7
|
+
return [
|
|
8
|
+
`To add this test, refer to the following code that was captured using playwright codegen. Make modifications that you need to make to convert this into a test case that sits well with other tests in this repository.`,
|
|
9
|
+
`Codegen result:`,
|
|
10
|
+
codegenResult,
|
|
11
|
+
`Other attachments:`,
|
|
12
|
+
...attachments,
|
|
13
|
+
].join("\n\n");
|
|
14
|
+
}
|
|
15
|
+
async function sendToDashboardAsRequest({ testName, codegenResult, attachments, }) {
|
|
16
|
+
return createRequest({
|
|
17
|
+
title: title(testName),
|
|
18
|
+
description: description(codegenResult, attachments),
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
async function createRequest({ title, description, }) {
|
|
22
|
+
if (!DASHBOARD_DOMAIN) {
|
|
23
|
+
console.warn("DASHBOARD_DOMAIN not set, skipping request creation");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (!process.env.EMPIRICALRUN_API_KEY) {
|
|
27
|
+
console.warn("EMPIRICALRUN_API_KEY not set, skipping request creation");
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const source = "cli";
|
|
32
|
+
const sourceIdentifier = "random-string";
|
|
33
|
+
const response = await fetch(`${DASHBOARD_DOMAIN}/api/requests`, {
|
|
34
|
+
method: "POST",
|
|
35
|
+
headers: {
|
|
36
|
+
"Content-Type": "application/json",
|
|
37
|
+
Authorization: `Bearer ${process.env.EMPIRICALRUN_API_KEY}`,
|
|
38
|
+
},
|
|
39
|
+
body: JSON.stringify({
|
|
40
|
+
source,
|
|
41
|
+
source_identifier: sourceIdentifier,
|
|
42
|
+
title,
|
|
43
|
+
description,
|
|
44
|
+
}),
|
|
45
|
+
});
|
|
46
|
+
if (!response.ok) {
|
|
47
|
+
throw new Error(`Failed to create request: ${response.statusText}`);
|
|
48
|
+
}
|
|
49
|
+
const data = await response.json();
|
|
50
|
+
console.log("Request created successfully:", data);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
console.error("Failed to create request:", error);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"temp-files.d.ts","sourceRoot":"","sources":["../../src/recorder/temp-files.ts"],"names":[],"mappings":"AAGA,wBAAsB,kBAAkB,kBAoBvC;AAED,wBAAsB,kBAAkB,kBAUvC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
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.createTempTestFile = createTempTestFile;
|
|
7
|
+
exports.deleteTempTestFile = deleteTempTestFile;
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
async function createTempTestFile() {
|
|
11
|
+
const tempFilePath = path_1.default.join(process.cwd(), "tests", "temp-test.spec.ts");
|
|
12
|
+
// Check if the temp file already exists
|
|
13
|
+
if (fs_1.default.existsSync(tempFilePath)) {
|
|
14
|
+
console.warn("Temporary test file already exists. Skipping creation.");
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
// Create a basic test file
|
|
18
|
+
const content = `import { test, expect } from './fixtures';
|
|
19
|
+
|
|
20
|
+
test('temp test', async ({ page }) => {
|
|
21
|
+
await page.goto('https://example.com');
|
|
22
|
+
expect(await page.title()).toBe('Example Domain');
|
|
23
|
+
await recordTest(page);
|
|
24
|
+
});
|
|
25
|
+
`;
|
|
26
|
+
fs_1.default.writeFileSync(tempFilePath, content);
|
|
27
|
+
console.log("Temporary test file created:", tempFilePath);
|
|
28
|
+
}
|
|
29
|
+
async function deleteTempTestFile() {
|
|
30
|
+
const tempFilePath = path_1.default.join(process.cwd(), "tests", "temp-test.spec.ts");
|
|
31
|
+
// Check if the temp file exists
|
|
32
|
+
if (fs_1.default.existsSync(tempFilePath)) {
|
|
33
|
+
fs_1.default.unlinkSync(tempFilePath);
|
|
34
|
+
console.log("Temporary test file deleted:", tempFilePath);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
console.warn("Temporary test file does not exist. Skipping deletion.");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/recorder/upload.ts"],"names":[],"mappings":"AAgFA,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,EAAE,EACpB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,GAAG,MAAM,EAAE,CAAC,CAe1B"}
|
|
@@ -0,0 +1,85 @@
|
|
|
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.uploadVideosWithSpinner = uploadVideosWithSpinner;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const ora_1 = __importDefault(require("ora"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const slug_1 = require("../utils/slug");
|
|
11
|
+
const ASSETS_PRODUCTION_BUCKET = "empirical-assets-production";
|
|
12
|
+
const BUCKET_DOMAINS = {
|
|
13
|
+
"empirical-assets-staging": "assets-staging.empirical.run",
|
|
14
|
+
"empirical-assets-production": "assets.empirical.run",
|
|
15
|
+
};
|
|
16
|
+
function buildVideoUrl(localPath, directory, bucket) {
|
|
17
|
+
const domain = BUCKET_DOMAINS[bucket];
|
|
18
|
+
const fileName = path_1.default.basename(localPath);
|
|
19
|
+
return `https://${domain}/${path_1.default.join(directory, fileName)}`;
|
|
20
|
+
}
|
|
21
|
+
async function uploadVideos(videoPaths, testSlug) {
|
|
22
|
+
if (videoPaths.length === 0) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
const DASHBOARD_DOMAIN = process.env.DASHBOARD_DOMAIN || "https://dash.empirical.run";
|
|
26
|
+
const API_KEY = process.env.EMPIRICALRUN_API_KEY;
|
|
27
|
+
if (!API_KEY) {
|
|
28
|
+
console.warn("EMPIRICALRUN_API_KEY not set, skipping video upload");
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const uploadDestinationDir = `recorder-uploads/${testSlug}`;
|
|
32
|
+
const bucket = ASSETS_PRODUCTION_BUCKET;
|
|
33
|
+
try {
|
|
34
|
+
const formData = new FormData();
|
|
35
|
+
formData.append("destination_dir", uploadDestinationDir);
|
|
36
|
+
formData.append("bucket", bucket);
|
|
37
|
+
for (const videoPath of videoPaths) {
|
|
38
|
+
if (fs_1.default.existsSync(videoPath)) {
|
|
39
|
+
const fileBuffer = fs_1.default.readFileSync(videoPath);
|
|
40
|
+
const fileName = path_1.default.basename(videoPath);
|
|
41
|
+
const blob = new Blob([fileBuffer], { type: "video/webm" });
|
|
42
|
+
formData.append("files", blob, fileName);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const response = await fetch(`${DASHBOARD_DOMAIN}/api/upload`, {
|
|
46
|
+
method: "POST",
|
|
47
|
+
headers: {
|
|
48
|
+
Authorization: `Bearer ${API_KEY}`,
|
|
49
|
+
},
|
|
50
|
+
body: formData,
|
|
51
|
+
});
|
|
52
|
+
if (!response.ok) {
|
|
53
|
+
console.warn(`Failed to upload videos: ${response.status} ${response.statusText}`);
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
const result = await response.json();
|
|
57
|
+
if (result.error) {
|
|
58
|
+
console.warn("Video upload error:", result.error.message);
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
return videoPaths.map((p) => buildVideoUrl(p, uploadDestinationDir, bucket));
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
console.warn("Error uploading videos:", error);
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async function uploadVideosWithSpinner(videoPaths, testName) {
|
|
69
|
+
videoPaths.forEach((videoPath) => console.log(videoPath));
|
|
70
|
+
const uploadSpinner = (0, ora_1.default)("Uploading video recordings...").start();
|
|
71
|
+
try {
|
|
72
|
+
const slugifiedTestName = `${(0, slug_1.slugify)(testName)}-${Math.random().toString(36).substring(2, 8)}`;
|
|
73
|
+
const uploaded = await uploadVideos(videoPaths, slugifiedTestName);
|
|
74
|
+
if (uploaded) {
|
|
75
|
+
uploadSpinner.succeed("Video recordings uploaded successfully");
|
|
76
|
+
return uploaded;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
uploadSpinner.warn("Video upload skipped or failed");
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
uploadSpinner.fail("Failed to upload video recordings");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/recorder/validation.ts"],"names":[],"mappings":"AAGA,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,iBAoB7C"}
|
|
@@ -0,0 +1,24 @@
|
|
|
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.validate = validate;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
async function validate(repoDir) {
|
|
10
|
+
// Check if package.json exists
|
|
11
|
+
const packageJsonPath = path_1.default.join(repoDir, "package.json");
|
|
12
|
+
if (!fs_1.default.existsSync(packageJsonPath)) {
|
|
13
|
+
throw new Error("package.json not found in the repository");
|
|
14
|
+
}
|
|
15
|
+
// Check if playwright is installed
|
|
16
|
+
const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, "utf8"));
|
|
17
|
+
const hasPlaywright = (packageJson.dependencies &&
|
|
18
|
+
packageJson.dependencies["@playwright/test"]) ||
|
|
19
|
+
(packageJson.devDependencies &&
|
|
20
|
+
packageJson.devDependencies["@playwright/test"]);
|
|
21
|
+
if (!hasPlaywright) {
|
|
22
|
+
throw new Error("Playwright is not installed. Please install @playwright/test");
|
|
23
|
+
}
|
|
24
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@empiricalrun/test-gen",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.67.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"registry": "https://registry.npmjs.org/",
|
|
6
6
|
"access": "public"
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"mime": "3.0.0",
|
|
54
54
|
"minimatch": "^10.0.1",
|
|
55
55
|
"nanoid": "^5.0.7",
|
|
56
|
+
"open": "^10.1.2",
|
|
56
57
|
"openai": "4.87.3",
|
|
57
58
|
"ora": "^8.1.0",
|
|
58
59
|
"picocolors": "^1.0.1",
|
package/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["./src/index.ts","./src/actions/assert.ts","./src/actions/click.ts","./src/actions/done.ts","./src/actions/fill.ts","./src/actions/goto.ts","./src/actions/hover.ts","./src/actions/index.ts","./src/actions/next-task.ts","./src/actions/press.ts","./src/actions/skill.ts","./src/actions/text-content.ts","./src/actions/constants/index.ts","./src/actions/utils/index.ts","./src/agent/browsing/index.ts","./src/agent/browsing/run.ts","./src/agent/browsing/utils.ts","./src/agent/chat/agent-loop.ts","./src/agent/chat/exports.ts","./src/agent/chat/index.ts","./src/agent/chat/models.ts","./src/agent/chat/state.ts","./src/agent/chat/types.ts","./src/agent/chat/utils.ts","./src/agent/chat/prompt/index.ts","./src/agent/chat/prompt/pw-utils-docs.ts","./src/agent/chat/prompt/repo.ts","./src/agent/codegen/create-test-block.ts","./src/agent/codegen/fix-ts-errors.ts","./src/agent/codegen/generate-code-apply-changes.ts","./src/agent/codegen/lexical-scoped-vars.ts","./src/agent/codegen/repo-edit.ts","./src/agent/codegen/run.ts","./src/agent/codegen/skills-retriever.ts","./src/agent/codegen/test-update-feedback.ts","./src/agent/codegen/types.ts","./src/agent/codegen/update-flow.ts","./src/agent/codegen/use-skill.ts","./src/agent/codegen/utils.ts","./src/agent/cua/computer.ts","./src/agent/cua/index.ts","./src/agent/cua/model.ts","./src/agent/cua/pw-codegen/element-from-point.ts","./src/agent/cua/pw-codegen/types.ts","./src/agent/cua/pw-codegen/pw-pause/index.ts","./src/agent/cua/pw-codegen/pw-pause/ipc.ts","./src/agent/cua/pw-codegen/pw-pause/patch.ts","./src/agent/diagnosis-agent/index.ts","./src/agent/diagnosis-agent/strict-mode-violation.ts","./src/agent/enrich-prompt/index.ts","./src/agent/enrich-prompt/utils.ts","./src/agent/infer-agent/index.ts","./src/agent/master/action-tool-calls.ts","./src/agent/master/element-annotation.ts","./src/agent/master/execute-browser-action.ts","./src/agent/master/execute-skill-action.ts","./src/agent/master/next-action.ts","./src/agent/master/planner.ts","./src/agent/master/run.ts","./src/agent/master/scroller.ts","./src/agent/master/with-hints.ts","./src/agent/master/browser-tests/cua.spec.ts","./src/agent/master/browser-tests/fixtures.ts","./src/agent/master/browser-tests/index.spec.ts","./src/agent/master/browser-tests/skills.spec.ts","./src/agent/master/icon-descriptor/index.ts","./src/agent/master/icon-descriptor/normalize-svg.ts","./src/agent/planner/run-time-planner.ts","./src/agent/planner/run.ts","./src/artifacts/index.ts","./src/artifacts/utils.ts","./src/bin/index.ts","./src/bin/logger/index.ts","./src/bin/utils/context.ts","./src/bin/utils/index.ts","./src/bin/utils/fs/index.ts","./src/bin/utils/platform/web/index.ts","./src/bin/utils/platform/web/test-files/ts-path-import-validate.ts","./src/bin/utils/scenarios/index.ts","./src/browser-injected-scripts/annotate-elements.spec.ts","./src/constants/index.ts","./src/errors/index.ts","./src/evals/add-scenario-agent.evals.ts","./src/evals/append-create-test-agent.evals.ts","./src/evals/fetch-pom-skills-agent.evals.ts","./src/evals/infer-master-or-code-agent.evals.ts","./src/evals/master-agent.evals.ts","./src/evals/type.ts","./src/evals/update-scenario-agent.evals.ts","./src/file/client.ts","./src/file/server.ts","./src/human-in-the-loop/cli.ts","./src/human-in-the-loop/index.ts","./src/human-in-the-loop/ipc.ts","./src/page/index.ts","./src/prompts/lib/ts-transformer.ts","./src/reporter/index.ts","./src/reporter/lib.ts","./src/session/index.ts","./src/test-build/index.ts","./src/tool-call-service/index.ts","./src/tool-call-service/utils.ts","./src/tools/commit-and-create-pr.ts","./src/tools/diagnosis-fetcher.ts","./src/tools/download-build.ts","./src/tools/list-environments.ts","./src/tools/str_replace_editor.ts","./src/tools/test-gen-browser.ts","./src/tools/test-run.ts","./src/tools/grep/index.ts","./src/tools/grep/ripgrep/index.ts","./src/tools/grep/ripgrep/types.ts","./src/tools/test-run-fetcher/index.ts","./src/tools/test-run-fetcher/types.ts","./src/tools/upgrade-packages/index.ts","./src/tools/upgrade-packages/utils.ts","./src/tools/utils/index.ts","./src/types/handlebars.d.ts","./src/types/index.ts","./src/uploader/index.ts","./src/uploader/utils.ts","./src/utils/checkpoint.ts","./src/utils/env.ts","./src/utils/exec.ts","./src/utils/file-tree.ts","./src/utils/file.ts","./src/utils/git.ts","./src/utils/html.ts","./src/utils/index.ts","./src/utils/json.ts","./src/utils/repo-tree.ts","./src/utils/slug.ts","./src/utils/string.ts","./src/utils/stripAnsi.ts"],"version":"5.8.3"}
|
|
1
|
+
{"root":["./src/index.ts","./src/actions/assert.ts","./src/actions/click.ts","./src/actions/done.ts","./src/actions/fill.ts","./src/actions/goto.ts","./src/actions/hover.ts","./src/actions/index.ts","./src/actions/next-task.ts","./src/actions/press.ts","./src/actions/skill.ts","./src/actions/text-content.ts","./src/actions/constants/index.ts","./src/actions/utils/index.ts","./src/agent/browsing/index.ts","./src/agent/browsing/run.ts","./src/agent/browsing/utils.ts","./src/agent/chat/agent-loop.ts","./src/agent/chat/exports.ts","./src/agent/chat/index.ts","./src/agent/chat/models.ts","./src/agent/chat/state.ts","./src/agent/chat/types.ts","./src/agent/chat/utils.ts","./src/agent/chat/prompt/index.ts","./src/agent/chat/prompt/pw-utils-docs.ts","./src/agent/chat/prompt/repo.ts","./src/agent/codegen/create-test-block.ts","./src/agent/codegen/fix-ts-errors.ts","./src/agent/codegen/generate-code-apply-changes.ts","./src/agent/codegen/lexical-scoped-vars.ts","./src/agent/codegen/repo-edit.ts","./src/agent/codegen/run.ts","./src/agent/codegen/skills-retriever.ts","./src/agent/codegen/test-update-feedback.ts","./src/agent/codegen/types.ts","./src/agent/codegen/update-flow.ts","./src/agent/codegen/use-skill.ts","./src/agent/codegen/utils.ts","./src/agent/cua/computer.ts","./src/agent/cua/index.ts","./src/agent/cua/model.ts","./src/agent/cua/pw-codegen/element-from-point.ts","./src/agent/cua/pw-codegen/types.ts","./src/agent/cua/pw-codegen/pw-pause/for-recorder.ts","./src/agent/cua/pw-codegen/pw-pause/index.ts","./src/agent/cua/pw-codegen/pw-pause/ipc.ts","./src/agent/cua/pw-codegen/pw-pause/patch.ts","./src/agent/cua/pw-codegen/pw-pause/types.ts","./src/agent/diagnosis-agent/index.ts","./src/agent/diagnosis-agent/strict-mode-violation.ts","./src/agent/enrich-prompt/index.ts","./src/agent/enrich-prompt/utils.ts","./src/agent/infer-agent/index.ts","./src/agent/master/action-tool-calls.ts","./src/agent/master/element-annotation.ts","./src/agent/master/execute-browser-action.ts","./src/agent/master/execute-skill-action.ts","./src/agent/master/next-action.ts","./src/agent/master/planner.ts","./src/agent/master/run.ts","./src/agent/master/scroller.ts","./src/agent/master/with-hints.ts","./src/agent/master/browser-tests/cua.spec.ts","./src/agent/master/browser-tests/fixtures.ts","./src/agent/master/browser-tests/index.spec.ts","./src/agent/master/browser-tests/skills.spec.ts","./src/agent/master/icon-descriptor/index.ts","./src/agent/master/icon-descriptor/normalize-svg.ts","./src/agent/planner/run-time-planner.ts","./src/agent/planner/run.ts","./src/artifacts/index.ts","./src/artifacts/utils.ts","./src/auth/api-client.ts","./src/auth/cli-auth.ts","./src/auth/index.ts","./src/auth/token-store.ts","./src/bin/index.ts","./src/bin/logger/index.ts","./src/bin/utils/context.ts","./src/bin/utils/index.ts","./src/bin/utils/fs/index.ts","./src/bin/utils/platform/web/index.ts","./src/bin/utils/platform/web/test-files/ts-path-import-validate.ts","./src/bin/utils/scenarios/index.ts","./src/browser-injected-scripts/annotate-elements.spec.ts","./src/constants/index.ts","./src/errors/index.ts","./src/evals/add-scenario-agent.evals.ts","./src/evals/append-create-test-agent.evals.ts","./src/evals/fetch-pom-skills-agent.evals.ts","./src/evals/infer-master-or-code-agent.evals.ts","./src/evals/master-agent.evals.ts","./src/evals/type.ts","./src/evals/update-scenario-agent.evals.ts","./src/file/client.ts","./src/file/server.ts","./src/human-in-the-loop/cli.ts","./src/human-in-the-loop/index.ts","./src/human-in-the-loop/ipc.ts","./src/page/index.ts","./src/prompts/lib/ts-transformer.ts","./src/recorder/display.ts","./src/recorder/index.ts","./src/recorder/request.ts","./src/recorder/temp-files.ts","./src/recorder/upload.ts","./src/recorder/validation.ts","./src/reporter/index.ts","./src/reporter/lib.ts","./src/session/index.ts","./src/test-build/index.ts","./src/tool-call-service/index.ts","./src/tool-call-service/utils.ts","./src/tools/commit-and-create-pr.ts","./src/tools/diagnosis-fetcher.ts","./src/tools/download-build.ts","./src/tools/list-environments.ts","./src/tools/str_replace_editor.ts","./src/tools/test-gen-browser.ts","./src/tools/test-run.ts","./src/tools/grep/index.ts","./src/tools/grep/ripgrep/index.ts","./src/tools/grep/ripgrep/types.ts","./src/tools/test-run-fetcher/index.ts","./src/tools/test-run-fetcher/types.ts","./src/tools/upgrade-packages/index.ts","./src/tools/upgrade-packages/utils.ts","./src/tools/utils/index.ts","./src/types/handlebars.d.ts","./src/types/index.ts","./src/uploader/index.ts","./src/uploader/utils.ts","./src/utils/checkpoint.ts","./src/utils/env.ts","./src/utils/exec.ts","./src/utils/file-tree.ts","./src/utils/file.ts","./src/utils/git.ts","./src/utils/html.ts","./src/utils/index.ts","./src/utils/json.ts","./src/utils/repo-tree.ts","./src/utils/slug.ts","./src/utils/string.ts","./src/utils/stripAnsi.ts"],"version":"5.8.3"}
|