@empiricalrun/test-gen 0.69.0 → 0.69.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @empiricalrun/test-gen
2
2
 
3
+ ## 0.69.2
4
+
5
+ ### Patch Changes
6
+
7
+ - e2f72b5: fix: handle video processing time and large uploads
8
+ - Updated dependencies [e2f72b5]
9
+ - @empiricalrun/llm@0.19.1
10
+
11
+ ## 0.69.1
12
+
13
+ ### Patch Changes
14
+
15
+ - ff84083: feat: request verification for recording, more logs clean up
16
+ - Updated dependencies [ff84083]
17
+ - @empiricalrun/test-run@0.10.5
18
+
3
19
  ## 0.69.0
4
20
 
5
21
  ### Minor Changes
@@ -1 +1 @@
1
- {"version":3,"file":"for-recorder.d.ts","sourceRoot":"","sources":["../../../../../src/agent/cua/pw-codegen/pw-pause/for-recorder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAIvC,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC,qBAAa,iCAAiC;IAO1C,OAAO,CAAC,eAAe;IANzB,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,IAAI,CAAmB;IAC/B,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,iBAAiB,CAAqB;gBAGpC,eAAe,EAAE,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC;YAKtD,QAAQ;IAWhB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBrC,sBAAsB,CAAC,IAAI,EAAE,IAAI;CAmCxC"}
1
+ {"version":3,"file":"for-recorder.d.ts","sourceRoot":"","sources":["../../../../../src/agent/cua/pw-codegen/pw-pause/for-recorder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAIvC,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC,qBAAa,iCAAiC;IAO1C,OAAO,CAAC,eAAe;IANzB,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,IAAI,CAAmB;IAC/B,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,iBAAiB,CAAqB;gBAGpC,eAAe,EAAE,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC;YAKtD,QAAQ;IAWhB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBrC,sBAAsB,CAAC,IAAI,EAAE,IAAI;CA4CxC"}
@@ -69,13 +69,22 @@ class PlaywrightPauseCodegenForRecorder {
69
69
  }
70
70
  });
71
71
  await page.addInitScript(() => {
72
- setInterval(() => {
72
+ let displayNoneSet = false;
73
+ function setDisplayNone() {
73
74
  const glassPane = document.querySelector("x-pw-glass");
74
75
  if (glassPane) {
75
76
  const styles = glassPane.getAttribute("style") || "";
76
77
  glassPane.setAttribute("style", styles + "; display: none;");
78
+ displayNoneSet = true;
77
79
  }
78
- }, 300);
80
+ }
81
+ let interval = setInterval(() => {
82
+ if (displayNoneSet) {
83
+ clearInterval(interval);
84
+ return;
85
+ }
86
+ setDisplayNone();
87
+ }, 100);
79
88
  });
80
89
  await Promise.all([pausePromise, evaluatePromise]);
81
90
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/agent/cua/pw-codegen/pw-pause/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAKjD,OAAO,EAAE,2BAA2B,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAE9E,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,oBAuCvD;AAED,qBAAa,sBAAuB,YAAW,qBAAqB;IAClE,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,IAAI,CAAmB;IAC/B,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,iBAAiB,CAAqB;;YAMhC,QAAQ;IAUhB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBrC,sBAAsB,CAAC,IAAI,EAAE,IAAI;IAyBjC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;CAU9C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/agent/cua/pw-codegen/pw-pause/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAKjD,OAAO,EAAE,2BAA2B,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAE9E,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,oBAyCvD;AAED,qBAAa,sBAAuB,YAAW,qBAAqB;IAClE,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,IAAI,CAAmB;IAC/B,OAAO,CAAC,MAAM,CAA4C;IAC1D,OAAO,CAAC,iBAAiB,CAAqB;;YAMhC,QAAQ;IAUhB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBrC,sBAAsB,CAAC,IAAI,EAAE,IAAI;IAyBjC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;CAU9C"}
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.PlaywrightPauseCodegen = exports.revertToOriginalPwCode = exports.preparePlaywrightForCodegen = void 0;
7
7
  exports.canUsePauseCodegen = canUsePauseCodegen;
8
8
  const express_1 = __importDefault(require("express"));
9
+ const logger_1 = require("../../../../logger");
9
10
  const ipc_1 = require("./ipc");
10
11
  const patch_1 = require("./patch");
11
12
  var patch_2 = require("./patch");
@@ -16,12 +17,12 @@ async function canUsePauseCodegen(repoDir) {
16
17
  if (!hasPatchedPwCode) {
17
18
  // This codegen approach requires patching the playwright code to setup an
18
19
  // IPC server <> client that passes generated code from Playwright to @empiricalrun/test-gen
19
- console.log("Cannot use pause codegen because recorder app is not patched");
20
+ logger_1.logger.error("Cannot use pause codegen because recorder app is not patched");
20
21
  return false;
21
22
  }
22
23
  if (!(await (0, ipc_1.isIPCPortAvailable)())) {
23
24
  // The IPC port is hardcoded, and it should be available for IPC to work
24
- console.log("Cannot use pause codegen because IPC port is not available");
25
+ logger_1.logger.error("Cannot use pause codegen because IPC port is not available");
25
26
  return false;
26
27
  }
27
28
  const isRunningHeaded = process.env.RUN_PLAYWRIGHT_HEADED &&
@@ -29,7 +30,7 @@ async function canUsePauseCodegen(repoDir) {
29
30
  if (!isRunningHeaded) {
30
31
  // This codegen approach requires running Playwright in headed mode because
31
32
  // it depends on the page.pause() API, which is no-op in headless mode
32
- console.log("Cannot use pause codegen because RUN_PLAYWRIGHT_HEADED is not true");
33
+ logger_1.logger.error("Cannot use pause codegen because RUN_PLAYWRIGHT_HEADED is not true");
33
34
  return false;
34
35
  }
35
36
  // eslint-disable-next-line turbo/no-undeclared-env-vars
@@ -37,7 +38,7 @@ async function canUsePauseCodegen(repoDir) {
37
38
  // PW_CODEGEN_NO_INSPECTOR should be set to true, so that Playwright runs the
38
39
  // EmptyRecorderApp() -- which is the entrypoint to our patched code
39
40
  // Ref: https://github.com/microsoft/playwright/blob/c96558d0691c0377dbc0c772a1bd8120d546e6d7/packages/playwright-core/src/server/recorder/recorderApp.ts#L98
40
- console.log("Cannot use pause codegen because PW_CODEGEN_NO_INSPECTOR is not set");
41
+ logger_1.logger.error("Cannot use pause codegen because PW_CODEGEN_NO_INSPECTOR is not set");
41
42
  return false;
42
43
  }
43
44
  // Need all conditions to be met to use pause codegen
@@ -3,7 +3,7 @@ declare class APIClient {
3
3
  constructor();
4
4
  request(endpoint: string, options?: RequestInit): Promise<Response>;
5
5
  private makeRequest;
6
- private ensureAuthenticated;
6
+ ensureAuthenticated(): Promise<void>;
7
7
  private refreshToken;
8
8
  }
9
9
  export declare const apiClient: APIClient;
@@ -1 +1 @@
1
- {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/auth/api-client.ts"],"names":[],"mappings":"AAQA,cAAM,SAAS;IACb,OAAO,CAAC,MAAM,CAAS;;IAMjB,OAAO,CACX,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,QAAQ,CAAC;YA2BN,WAAW;YAuBX,mBAAmB;YAiBnB,YAAY;CA4C3B;AAED,eAAO,MAAM,SAAS,WAAkB,CAAC"}
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/auth/api-client.ts"],"names":[],"mappings":"AAQA,cAAM,SAAS;IACb,OAAO,CAAC,MAAM,CAAS;;IAMjB,OAAO,CACX,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC,QAAQ,CAAC;YA2BN,WAAW;IAuBnB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;YAiB5B,YAAY;CA4C3B;AAED,eAAO,MAAM,SAAS,WAAkB,CAAC"}
@@ -147,7 +147,7 @@ async function authenticate() {
147
147
  server.listen(clientPort, () => {
148
148
  // Open browser to your Next.js auth page
149
149
  const authUrl = `${appUrl}/auth/cli?redirect_uri=${encodeURIComponent(redirectUri)}`;
150
- console.log("Opening browser for authentication...");
150
+ console.log("🔐 Opening browser for authentication...\n");
151
151
  console.log(`If the browser doesn't open automatically, visit: ${authUrl}`);
152
152
  (0, open_1.default)(authUrl).catch((err) => {
153
153
  console.warn("Could not open browser automatically:", err.message);
package/dist/bin/index.js CHANGED
@@ -199,7 +199,6 @@ async function main() {
199
199
  .command("login")
200
200
  .description("Authenticate with your Empirical account")
201
201
  .action(async () => {
202
- console.log("🔐 Starting authentication...\n");
203
202
  try {
204
203
  const result = await (0, auth_1.authenticate)();
205
204
  if (result.success) {
@@ -207,7 +206,6 @@ async function main() {
207
206
  if (result.user) {
208
207
  console.log(`👤 Logged in as: ${result.user.email}`);
209
208
  }
210
- console.log("\nYou can now use authenticated CLI commands.\n");
211
209
  }
212
210
  else {
213
211
  console.error("❌ Authentication failed:", result.error);
@@ -100,7 +100,7 @@ async function printBanner() {
100
100
  versionSuffix = ` (latest)`;
101
101
  }
102
102
  else {
103
- versionSuffix = ` ${reset}(latest is ${latestVersion})`;
103
+ versionSuffix = ` ${reset}(latest is v${latestVersion})`;
104
104
  }
105
105
  }
106
106
  const logLine1 = `Running ${PACKAGE_NAME} v${version}${versionSuffix}`;
@@ -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;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"}
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;IA8HnC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAgB5B"}
@@ -42,6 +42,62 @@ class FileServiceServer {
42
42
  const app = (0, express_1.default)();
43
43
  app.use(express_1.default.json({ limit: "50mb" }));
44
44
  (0, ipc_1.humanLoopRoute)(app);
45
+ app.get("/ready", (req, res) => {
46
+ const html = `
47
+ <!DOCTYPE html>
48
+ <html>
49
+ <head>
50
+ <title>Record</title>
51
+ <style>
52
+ body {
53
+ display: flex;
54
+ justify-content: center;
55
+ align-items: center;
56
+ height: 100vh;
57
+ margin: 0;
58
+ font-family: sans-serif;
59
+ font-size: 24px;
60
+ }
61
+ .message {
62
+ opacity: 0;
63
+ animation: fadeIn 0.5s ease-in forwards;
64
+ }
65
+ .pulsate {
66
+ animation: pulsate 1s ease-in-out infinite;
67
+ }
68
+ @keyframes fadeIn {
69
+ to {
70
+ opacity: 1;
71
+ }
72
+ }
73
+ @keyframes pulsate {
74
+ 0%, 100% {
75
+ opacity: 1;
76
+ }
77
+ 50% {
78
+ opacity: 0.6;
79
+ }
80
+ }
81
+ </style>
82
+ </head>
83
+ <body>
84
+ <div class="message pulsate" id="message">Getting ready to record</div>
85
+ <script>
86
+ setTimeout(() => {
87
+ const message = document.getElementById('message');
88
+ message.className = 'message';
89
+ message.style.opacity = '0';
90
+ setTimeout(() => {
91
+ message.textContent = 'Ready to record';
92
+ message.style.opacity = '1';
93
+ }, 300);
94
+ }, 2000);
95
+ </script>
96
+ </body>
97
+ </html>
98
+ `;
99
+ res.send(html);
100
+ });
45
101
  app.post("/codegen-sources", async (req) => {
46
102
  const payload = req.body;
47
103
  this.codegenSources = payload.map((c) => c.actions.join("\n")).join("\n");
package/dist/index.js CHANGED
@@ -103,7 +103,7 @@ async function recordTest(pageRef) {
103
103
  const repoDir = process.cwd();
104
104
  const canUsePwPause = await (0, pw_pause_1.canUsePauseCodegen)(repoDir);
105
105
  if (!canUsePwPause) {
106
- return;
106
+ throw new Error("Unable to start recording: please report this issue.");
107
107
  }
108
108
  logger_1.logger.debug("[getCodegen] using PlaywrightPauseCodegen");
109
109
  const codegen = new for_recorder_1.PlaywrightPauseCodegenForRecorder(async (sources) => {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/recorder/index.ts"],"names":[],"mappings":"AAkBA,wBAAsB,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,iBAyF3D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/recorder/index.ts"],"names":[],"mappings":"AAkBA,wBAAsB,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,iBAgG3D"}
@@ -9,9 +9,9 @@ const detect_port_1 = __importDefault(require("detect-port"));
9
9
  const path_1 = __importDefault(require("path"));
10
10
  const utils_1 = require("../agent/browsing/utils");
11
11
  const pw_pause_1 = require("../agent/cua/pw-codegen/pw-pause");
12
+ const api_client_1 = require("../auth/api-client");
12
13
  const server_1 = require("../file/server");
13
14
  const logger_1 = require("../logger");
14
- const display_1 = require("./display");
15
15
  const env_variables_1 = require("./env-variables");
16
16
  const request_1 = require("./request");
17
17
  const temp_files_1 = require("./temp-files");
@@ -19,6 +19,13 @@ const upload_1 = require("./upload");
19
19
  const validation_1 = require("./validation");
20
20
  async function runRecorder({ name }) {
21
21
  console.log(`Recording for test name: ${name}`);
22
+ try {
23
+ await api_client_1.apiClient.ensureAuthenticated();
24
+ }
25
+ catch (error) {
26
+ console.error("Authentication required: please run @empiricalrun/test-gen login first");
27
+ process.exit(1);
28
+ }
22
29
  const repoDir = process.cwd();
23
30
  let repoName = "";
24
31
  let fileServer = null;
@@ -50,9 +57,6 @@ async function runRecorder({ name }) {
50
57
  logger_1.logger.warn("[generateTestWithBrowserAgent] Error preparing playwright for codegen", err);
51
58
  }
52
59
  const envVariables = await (0, env_variables_1.fetchEnvironmentVariables)(repoName);
53
- await (0, temp_files_1.createTempTestFile)();
54
- const absFilePath = path_1.default.join(process.cwd(), "tests", "temp-test.spec.ts");
55
- await (0, utils_1.addImportForMethod)(absFilePath, "recordTest");
56
60
  // Start a file service for IPC with the agent (which runs in a different process)
57
61
  const availablePort = await (0, detect_port_1.default)(3030);
58
62
  fileServer = new server_1.FileServiceServer({
@@ -61,6 +65,9 @@ async function runRecorder({ name }) {
61
65
  updateFile: false,
62
66
  });
63
67
  await fileServer.startFileService();
68
+ await (0, temp_files_1.createTempTestFile)(availablePort);
69
+ const absFilePath = path_1.default.join(process.cwd(), "tests", "temp-test.spec.ts");
70
+ await (0, utils_1.addImportForMethod)(absFilePath, "recordTest");
64
71
  await (0, test_run_1.runSingleTest)({
65
72
  testName: "temp test",
66
73
  suites: [],
@@ -89,11 +96,10 @@ async function runRecorder({ name }) {
89
96
  await (0, pw_pause_1.revertToOriginalPwCode)(repoDir);
90
97
  const codegenResult = fileServer.getCodegenSources();
91
98
  await fileServer.stop();
92
- const finalCode = await (0, display_1.displayResultsAndConfirm)(name, codegenResult);
93
99
  await (0, request_1.sendToDashboardAsRequest)({
94
100
  repoName,
95
101
  testName: name,
96
- codegenResult: finalCode,
102
+ codegenResult: codegenResult,
97
103
  attachments,
98
104
  });
99
105
  }
@@ -1 +1 @@
1
- {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/recorder/request.ts"],"names":[],"mappings":"AAaA,wBAAsB,wBAAwB,CAAC,EAC7C,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,WAAW,GACZ,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,iBAMA"}
1
+ {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/recorder/request.ts"],"names":[],"mappings":"AA+KA,wBAAsB,wBAAwB,CAAC,EAC7C,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,WAAW,GACZ,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,iBAmBA"}
@@ -1,21 +1,172 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.sendToDashboardAsRequest = sendToDashboardAsRequest;
7
+ const inquirer_1 = __importDefault(require("inquirer"));
4
8
  const api_client_1 = require("../auth/api-client");
5
- const title = (name) => `Add a test: ${name}`;
6
- function description(codegenResult, attachments) {
9
+ function truncateForDisplay(text, maxLineLength) {
10
+ const lines = text.split("\n");
11
+ return lines
12
+ .map((line) => {
13
+ if (line.length <= maxLineLength) {
14
+ return line;
15
+ }
16
+ return line.substring(0, maxLineLength - 3) + "...";
17
+ })
18
+ .join("\n");
19
+ }
20
+ function wrapText(text, width) {
21
+ const allLines = [];
22
+ // Split by newlines first to preserve existing line breaks
23
+ const paragraphs = text.split("\n");
24
+ for (const paragraph of paragraphs) {
25
+ if (paragraph.trim() === "") {
26
+ allLines.push("");
27
+ continue;
28
+ }
29
+ // If the line is already shorter than width, use it as-is
30
+ if (paragraph.length <= width) {
31
+ allLines.push(paragraph);
32
+ continue;
33
+ }
34
+ // Otherwise, wrap the line
35
+ const words = paragraph.split(" ");
36
+ let currentLine = "";
37
+ for (const word of words) {
38
+ if (currentLine.length + word.length + 1 <= width) {
39
+ currentLine += (currentLine.length > 0 ? " " : "") + word;
40
+ }
41
+ else {
42
+ if (currentLine.length > 0) {
43
+ allLines.push(currentLine);
44
+ currentLine = word;
45
+ }
46
+ else {
47
+ // Word is longer than width, split it into chunks
48
+ if (word.length > width) {
49
+ let remainingWord = word;
50
+ while (remainingWord.length > width) {
51
+ allLines.push(remainingWord.substring(0, width));
52
+ remainingWord = remainingWord.substring(width);
53
+ }
54
+ currentLine = remainingWord;
55
+ }
56
+ else {
57
+ currentLine = word;
58
+ }
59
+ }
60
+ }
61
+ }
62
+ if (currentLine.length > 0) {
63
+ allLines.push(currentLine);
64
+ }
65
+ }
66
+ return allLines;
67
+ }
68
+ function printInBox(header, title, description) {
69
+ const boxWidth = 80;
70
+ const contentWidth = boxWidth - 4; // Account for borders and padding
71
+ // Create box with padding
72
+ console.log("\n" + "┌" + "─".repeat(boxWidth - 2) + "┐");
73
+ // Header section
74
+ console.log("│ " + header + " ".repeat(boxWidth - 4 - header.length) + "│");
75
+ console.log("│" + "─".repeat(boxWidth - 2) + "│");
76
+ // Title content with wrapping
77
+ const titleLines = wrapText(title, contentWidth - 2);
78
+ titleLines.forEach((line) => {
79
+ const padding = Math.max(0, boxWidth - 4 - line.length);
80
+ console.log("│ " + line + " ".repeat(padding) + "│");
81
+ });
82
+ console.log("│" + "─".repeat(boxWidth - 2) + "│");
83
+ console.log("│ Description:" + " ".repeat(boxWidth - 16) + "│");
84
+ console.log("│" + " ".repeat(boxWidth - 2) + "│");
85
+ // Description content with wrapping
86
+ const descriptionLines = wrapText(description, contentWidth - 2);
87
+ descriptionLines.forEach((line) => {
88
+ const padding = Math.max(0, boxWidth - 4 - line.length);
89
+ console.log("│ " + line + " ".repeat(padding) + "│");
90
+ });
91
+ console.log("│" + " ".repeat(boxWidth - 2) + "│");
92
+ console.log("└" + "─".repeat(boxWidth - 2) + "┘");
93
+ }
94
+ const defaultTitle = (name) => `Add a test: ${name}`;
95
+ function defaultDescription(codegenResult, attachments) {
96
+ const backtickedCodegenResult = `\`\`\`\n${codegenResult}\n\`\`\``;
7
97
  return [
8
98
  `To add this test, refer to the following code and videos that were 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
99
  `Codegen result:`,
10
- codegenResult,
100
+ backtickedCodegenResult,
11
101
  ...attachments.map((attachment) => `[[${attachment}]]`),
12
102
  ].join("\n\n");
13
103
  }
104
+ function defaultDescriptionForDisplay(codegenResult, attachments) {
105
+ const truncatedCodegenResult = truncateForDisplay(codegenResult, 74);
106
+ const backtickedCodegenResult = `\`\`\`\n${truncatedCodegenResult}\n\`\`\``;
107
+ return [
108
+ `To add this test, refer to the following code and videos that were 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.`,
109
+ `Codegen result:`,
110
+ backtickedCodegenResult,
111
+ ...attachments.map((attachment) => `[[${attachment}]]`),
112
+ ].join("\n\n");
113
+ }
114
+ async function confirmRequestDetails(initialTitle, initialDescription, initialDescriptionForDisplay) {
115
+ let finalTitle = initialTitle;
116
+ let finalDescription = initialDescription;
117
+ let finalDescriptionForDisplay = initialDescriptionForDisplay;
118
+ let approved = false;
119
+ while (!approved) {
120
+ printInBox("📝 Create new request", finalTitle, finalDescriptionForDisplay);
121
+ const { confirmed } = await inquirer_1.default.prompt([
122
+ {
123
+ type: "confirm",
124
+ name: "confirmed",
125
+ message: "Does this look good to send to the dashboard?",
126
+ default: true,
127
+ },
128
+ ]);
129
+ if (confirmed) {
130
+ console.log("✅ Great! Sending request to dashboard...");
131
+ approved = true;
132
+ }
133
+ else {
134
+ // Let user edit title and description
135
+ const { editedTitle } = await inquirer_1.default.prompt([
136
+ {
137
+ type: "input",
138
+ name: "editedTitle",
139
+ message: "Edit the title:",
140
+ default: finalTitle,
141
+ },
142
+ ]);
143
+ const { editedDescription } = await inquirer_1.default.prompt([
144
+ {
145
+ type: "editor",
146
+ name: "editedDescription",
147
+ message: "Edit the description:",
148
+ default: finalDescription,
149
+ },
150
+ ]);
151
+ finalTitle = editedTitle;
152
+ finalDescription = editedDescription;
153
+ // For simplicity, if description is edited, just use it as-is for display
154
+ finalDescriptionForDisplay = editedDescription;
155
+ console.clear();
156
+ console.log("Request details updated.");
157
+ }
158
+ }
159
+ return { title: finalTitle, description: finalDescription };
160
+ }
14
161
  async function sendToDashboardAsRequest({ repoName, testName, codegenResult, attachments, }) {
162
+ const initialTitle = defaultTitle(testName);
163
+ const initialDescription = defaultDescription(codegenResult, attachments);
164
+ const initialDescriptionForDisplay = defaultDescriptionForDisplay(codegenResult, attachments);
165
+ const { title, description } = await confirmRequestDetails(initialTitle, initialDescription, initialDescriptionForDisplay);
15
166
  return createRequest({
16
167
  repoName,
17
- title: title(testName),
18
- description: description(codegenResult, attachments),
168
+ title,
169
+ description,
19
170
  });
20
171
  }
21
172
  async function createRequest({ repoName, title, description, }) {
@@ -1,3 +1,3 @@
1
- export declare function createTempTestFile(): Promise<void>;
1
+ export declare function createTempTestFile(port: number): Promise<void>;
2
2
  export declare function deleteTempTestFile(): Promise<void>;
3
3
  //# sourceMappingURL=temp-files.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"temp-files.d.ts","sourceRoot":"","sources":["../../src/recorder/temp-files.ts"],"names":[],"mappings":"AAKA,wBAAsB,kBAAkB,kBAoBvC;AAED,wBAAsB,kBAAkB,kBAUvC"}
1
+ {"version":3,"file":"temp-files.d.ts","sourceRoot":"","sources":["../../src/recorder/temp-files.ts"],"names":[],"mappings":"AAKA,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,iBAmBpD;AAED,wBAAsB,kBAAkB,kBAUvC"}
@@ -8,7 +8,7 @@ exports.deleteTempTestFile = deleteTempTestFile;
8
8
  const fs_1 = __importDefault(require("fs"));
9
9
  const path_1 = __importDefault(require("path"));
10
10
  const logger_1 = require("../logger");
11
- async function createTempTestFile() {
11
+ async function createTempTestFile(port) {
12
12
  const tempFilePath = path_1.default.join(process.cwd(), "tests", "temp-test.spec.ts");
13
13
  // Check if the temp file already exists
14
14
  if (fs_1.default.existsSync(tempFilePath)) {
@@ -19,8 +19,7 @@ async function createTempTestFile() {
19
19
  const content = `import { test, expect } from './fixtures';
20
20
 
21
21
  test('temp test', async ({ page }) => {
22
- await page.goto('https://example.com');
23
- expect(await page.title()).toBe('Example Domain');
22
+ await page.goto('http://localhost:${port}/ready');
24
23
  await recordTest(page);
25
24
  });
26
25
  `;
@@ -1 +1 @@
1
- {"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/recorder/upload.ts"],"names":[],"mappings":"AAcA,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAoBjE;AA4DD,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,EAAE,EACpB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,GAAG,MAAM,EAAE,CAAC,CAc1B"}
1
+ {"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/recorder/upload.ts"],"names":[],"mappings":"AAcA,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAoBjE;AA6FD,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,EAAE,EACpB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,GAAG,MAAM,EAAE,CAAC,CAc1B"}
@@ -47,30 +47,56 @@ async function uploadVideos(videoPaths, testSlug) {
47
47
  const uploadDestinationDir = `recorder-uploads/${testSlug}`;
48
48
  const bucket = ASSETS_PRODUCTION_BUCKET;
49
49
  try {
50
- const formData = new FormData();
51
- formData.append("destination_dir", uploadDestinationDir);
52
- formData.append("bucket", bucket);
53
- for (const videoPath of videoPaths) {
54
- if (fs_1.default.existsSync(videoPath)) {
55
- const fileBuffer = fs_1.default.readFileSync(videoPath);
56
- const fileName = path_1.default.basename(videoPath);
57
- const blob = new Blob([fileBuffer], { type: "video/webm" });
58
- formData.append("files", blob, fileName);
59
- }
50
+ // Step 1: Get pre-signed URLs from the API
51
+ const files = videoPaths
52
+ .filter((videoPath) => fs_1.default.existsSync(videoPath))
53
+ .map((videoPath) => ({
54
+ name: path_1.default.basename(videoPath),
55
+ type: "video/webm",
56
+ }));
57
+ if (files.length === 0) {
58
+ return null;
60
59
  }
61
- const response = await api_client_1.apiClient.request("/api/upload", {
60
+ const presignedResponse = await api_client_1.apiClient.request("/api/upload", {
62
61
  method: "POST",
63
- body: formData,
62
+ headers: {
63
+ "Content-Type": "application/json",
64
+ },
65
+ body: JSON.stringify({
66
+ files,
67
+ destination_dir: uploadDestinationDir,
68
+ bucket,
69
+ }),
64
70
  });
65
- if (!response.ok) {
66
- console.warn(`Failed to upload videos: ${response.status} ${response.statusText}`);
71
+ if (!presignedResponse.ok) {
72
+ console.warn(`Failed to get pre-signed URLs: ${presignedResponse.status} ${presignedResponse.statusText}`);
67
73
  return null;
68
74
  }
69
- const result = await response.json();
70
- if (result.error) {
71
- console.warn("Video upload error:", result.error.message);
75
+ const presignedResult = await presignedResponse.json();
76
+ if (presignedResult.error) {
77
+ console.warn("Pre-signed URL error:", presignedResult.error.message);
72
78
  return null;
73
79
  }
80
+ // Step 2: Upload files directly to R2 using pre-signed URLs
81
+ const uploadPromises = presignedResult.data.presigned_urls.map(async (urlInfo) => {
82
+ const videoPath = videoPaths.find((p) => path_1.default.basename(p) === urlInfo.file_name);
83
+ if (!videoPath || !fs_1.default.existsSync(videoPath)) {
84
+ throw new Error(`Video file not found: ${urlInfo.file_name}`);
85
+ }
86
+ const fileBuffer = fs_1.default.readFileSync(videoPath);
87
+ const uploadResponse = await fetch(urlInfo.upload_url, {
88
+ method: "PUT",
89
+ body: fileBuffer,
90
+ headers: {
91
+ "Content-Type": "video/webm",
92
+ },
93
+ });
94
+ if (!uploadResponse.ok) {
95
+ throw new Error(`Failed to upload ${urlInfo.file_name}: ${uploadResponse.status} ${uploadResponse.statusText}`);
96
+ }
97
+ return urlInfo.key;
98
+ });
99
+ await Promise.all(uploadPromises);
74
100
  return videoPaths.map((p) => buildVideoUrl(p, uploadDestinationDir, bucket));
75
101
  }
76
102
  catch (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@empiricalrun/test-gen",
3
- "version": "0.69.0",
3
+ "version": "0.69.2",
4
4
  "publishConfig": {
5
5
  "registry": "https://registry.npmjs.org/",
6
6
  "access": "public"
@@ -64,9 +64,9 @@
64
64
  "tsx": "^4.16.2",
65
65
  "typescript": "^5.3.3",
66
66
  "zod": "^3.23.8",
67
- "@empiricalrun/llm": "^0.19.0",
67
+ "@empiricalrun/llm": "^0.19.1",
68
68
  "@empiricalrun/r2-uploader": "^0.3.9",
69
- "@empiricalrun/test-run": "^0.10.4"
69
+ "@empiricalrun/test-run": "^0.10.5"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@playwright/test": "1.53.0",
@@ -1 +1 @@
1
- {"root":["./src/index.ts","./src/logger.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/setup.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/env-variables.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"}
1
+ {"root":["./src/index.ts","./src/logger.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/setup.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/env-variables.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"}
@@ -1,2 +0,0 @@
1
- export declare function displayResultsAndConfirm(name: string, codegenResult: string): Promise<string>;
2
- //# sourceMappingURL=display.d.ts.map
@@ -1 +0,0 @@
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"}
@@ -1,50 +0,0 @@
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
- }