@kadj-amoah/showrunner 1.1.0 → 1.1.1
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 +32 -0
- package/README.md +48 -2
- package/dist/cli.js +253 -72
- package/dist/cli.js.map +1 -1
- package/dist/index.js +35 -18
- package/dist/index.js.map +1 -1
- package/package.json +2 -4
package/dist/index.js
CHANGED
|
@@ -679,7 +679,7 @@ var HEADER = `// scripts/playwright_demo.ts
|
|
|
679
679
|
function renderPlaywrightSpec(inputs) {
|
|
680
680
|
const { manifest, recording, targetUrl, videoDir, traceDir } = inputs;
|
|
681
681
|
const launchLines = [
|
|
682
|
-
`import { chromium, firefox, webkit,
|
|
682
|
+
`import { chromium, firefox, webkit, type BrowserContext } from 'playwright-core';`,
|
|
683
683
|
`import { mkdirSync } from 'node:fs';`,
|
|
684
684
|
``,
|
|
685
685
|
`const VIDEO_DIR = ${JSON.stringify(videoDir)};`,
|
|
@@ -766,7 +766,7 @@ function renderAction(action) {
|
|
|
766
766
|
case "wait":
|
|
767
767
|
return `await page.waitForTimeout(${action.ms});`;
|
|
768
768
|
case "assert_visible":
|
|
769
|
-
return `await
|
|
769
|
+
return `await page.locator(${JSON.stringify(flattenSelector(action.selector))}).first().waitFor({ state: 'visible' });`;
|
|
770
770
|
case "press":
|
|
771
771
|
return action.selector ? `await page.locator(${JSON.stringify(flattenSelector(action.selector))}).first().press(${JSON.stringify(action.key)});` : `await page.keyboard.press(${JSON.stringify(action.key)});`;
|
|
772
772
|
case "custom":
|
|
@@ -1165,7 +1165,7 @@ async function generateManifest(opts) {
|
|
|
1165
1165
|
}
|
|
1166
1166
|
|
|
1167
1167
|
// src/scriptGen/domPreflight.ts
|
|
1168
|
-
import { chromium, firefox, webkit } from "playwright";
|
|
1168
|
+
import { chromium, firefox, webkit } from "playwright-core";
|
|
1169
1169
|
|
|
1170
1170
|
// src/recording/selectorHeuristic.ts
|
|
1171
1171
|
var SELECTOR_FOR_FN_SOURCE = `
|
|
@@ -1254,7 +1254,7 @@ async function scrapeSelectorInventory(opts) {
|
|
|
1254
1254
|
try {
|
|
1255
1255
|
await page.waitForLoadState("networkidle", { timeout: networkIdleMs });
|
|
1256
1256
|
} catch {
|
|
1257
|
-
logger.debug("domPreflight: networkidle did not fire within budget \
|
|
1257
|
+
logger.debug("domPreflight: networkidle did not fire within budget \xE2\u20AC\u201D proceeding");
|
|
1258
1258
|
}
|
|
1259
1259
|
const items = await page.evaluate(
|
|
1260
1260
|
buildScrapeScript(SELECTOR_FOR_FN_SOURCE, maxItems)
|
|
@@ -2144,7 +2144,7 @@ import {
|
|
|
2144
2144
|
chromium as chromium2,
|
|
2145
2145
|
firefox as firefox2,
|
|
2146
2146
|
webkit as webkit2
|
|
2147
|
-
} from "playwright";
|
|
2147
|
+
} from "playwright-core";
|
|
2148
2148
|
|
|
2149
2149
|
// src/manifest/alignment.ts
|
|
2150
2150
|
import { readFile as readFile6 } from "fs/promises";
|
|
@@ -2255,7 +2255,7 @@ async function buildStorageState(cookiesFile, localStorageFile, configDir) {
|
|
|
2255
2255
|
cookiesJson.origins = [...cookiesJson.origins ?? [], ...lsJson];
|
|
2256
2256
|
} else {
|
|
2257
2257
|
logger.warn(
|
|
2258
|
-
`local_storage_file at ${lsAbs} is not a Playwright origins list \
|
|
2258
|
+
`local_storage_file at ${lsAbs} is not a Playwright origins list \xE2\u20AC\u201D skipping. Use storageState() output format.`
|
|
2259
2259
|
);
|
|
2260
2260
|
}
|
|
2261
2261
|
} catch (err) {
|
|
@@ -2296,7 +2296,7 @@ function buildFormFill(auth) {
|
|
|
2296
2296
|
} catch (err) {
|
|
2297
2297
|
const cause = err instanceof Error ? err.message : String(err);
|
|
2298
2298
|
throw new AuthError(
|
|
2299
|
-
`Form auth: did not reach ${auth.success_url_pattern} within ${auth.timeout_ms}ms \
|
|
2299
|
+
`Form auth: did not reach ${auth.success_url_pattern} within ${auth.timeout_ms}ms \xE2\u20AC\u201D ${cause}`
|
|
2300
2300
|
);
|
|
2301
2301
|
}
|
|
2302
2302
|
};
|
|
@@ -2305,7 +2305,7 @@ function buildFormFill(auth) {
|
|
|
2305
2305
|
// src/recording/actions.ts
|
|
2306
2306
|
import { mkdir as mkdir5 } from "fs/promises";
|
|
2307
2307
|
import { dirname as dirname5, join as join2 } from "path";
|
|
2308
|
-
import { errors as playwrightErrors } from "playwright";
|
|
2308
|
+
import { errors as playwrightErrors } from "playwright-core";
|
|
2309
2309
|
|
|
2310
2310
|
// src/recording/cursorOverlay.ts
|
|
2311
2311
|
var CURSOR_INIT_SCRIPT = `
|
|
@@ -2379,7 +2379,7 @@ var CURSOR_INIT_SCRIPT = `
|
|
|
2379
2379
|
|
|
2380
2380
|
if (tryInstall()) return;
|
|
2381
2381
|
|
|
2382
|
-
console.log('[showrunner-cursor] deferring \
|
|
2382
|
+
console.log('[showrunner-cursor] deferring \xE2\u20AC\u201D body not ready');
|
|
2383
2383
|
|
|
2384
2384
|
const tick = () => { if (tryInstall()) cleanup(); };
|
|
2385
2385
|
const observer = new MutationObserver(tick);
|
|
@@ -2663,7 +2663,7 @@ async function recordDemo(opts) {
|
|
|
2663
2663
|
const tFirstSegmentStart = performance.now();
|
|
2664
2664
|
const preSegmentOffsetSec = (tFirstSegmentStart - tRecordingStart) / 1e3;
|
|
2665
2665
|
logger.info(
|
|
2666
|
-
`pre-segment recording offset: ${preSegmentOffsetSec.toFixed(2)}s (page.goto + setup) \
|
|
2666
|
+
`pre-segment recording offset: ${preSegmentOffsetSec.toFixed(2)}s (page.goto + setup) \xE2\u20AC\u201D slice_plan will be offset by this amount`
|
|
2667
2667
|
);
|
|
2668
2668
|
const t0 = tFirstSegmentStart;
|
|
2669
2669
|
let cursorPos = {
|
|
@@ -2742,7 +2742,7 @@ async function recordDemo(opts) {
|
|
|
2742
2742
|
);
|
|
2743
2743
|
if (adjusted < motionMs) {
|
|
2744
2744
|
warnings.push(
|
|
2745
|
-
`cursor motion for action at ${arrivalAt}s clamped from ${Math.round(motionMs)}ms to ${adjusted}ms \
|
|
2745
|
+
`cursor motion for action at ${arrivalAt}s clamped from ${Math.round(motionMs)}ms to ${adjusted}ms \xE2\u20AC\u201D manifest timing tight`
|
|
2746
2746
|
);
|
|
2747
2747
|
}
|
|
2748
2748
|
motionMs = adjusted;
|
|
@@ -2790,14 +2790,14 @@ async function recordDemo(opts) {
|
|
|
2790
2790
|
if (outcome.status === "skipped") {
|
|
2791
2791
|
warnings.push(`${action.type}: ${outcome.reason}`);
|
|
2792
2792
|
if (outcome.screenshot) failureScreenshots.push(outcome.screenshot);
|
|
2793
|
-
logger.warn(`segment ${seg.id} \
|
|
2793
|
+
logger.warn(`segment ${seg.id} \xE2\u20AC\u201D ${action.type} skipped`, {
|
|
2794
2794
|
reason: outcome.reason,
|
|
2795
2795
|
screenshot: outcome.screenshot
|
|
2796
2796
|
});
|
|
2797
2797
|
} else if (outcome.status === "segment_failed") {
|
|
2798
2798
|
failure = outcome.reason;
|
|
2799
2799
|
if (outcome.screenshot) failureScreenshots.push(outcome.screenshot);
|
|
2800
|
-
logger.error(`segment ${seg.id} \
|
|
2800
|
+
logger.error(`segment ${seg.id} \xE2\u20AC\u201D failed`, {
|
|
2801
2801
|
reason: outcome.reason,
|
|
2802
2802
|
screenshot: outcome.screenshot
|
|
2803
2803
|
});
|
|
@@ -2814,7 +2814,7 @@ async function recordDemo(opts) {
|
|
|
2814
2814
|
await page.waitForTimeout(Math.round(remaining * 1e3));
|
|
2815
2815
|
} else if (remaining < -0.5) {
|
|
2816
2816
|
warnings.push(
|
|
2817
|
-
`segment took ${elapsedInSegment.toFixed(2)}s but only ${allocated.toFixed(2)}s allocated \
|
|
2817
|
+
`segment took ${elapsedInSegment.toFixed(2)}s but only ${allocated.toFixed(2)}s allocated \xE2\u20AC\u201D manifest timing tight for this segment`
|
|
2818
2818
|
);
|
|
2819
2819
|
}
|
|
2820
2820
|
const segEnd = (performance.now() - t0) / 1e3;
|
|
@@ -2849,7 +2849,7 @@ async function recordDemo(opts) {
|
|
|
2849
2849
|
}
|
|
2850
2850
|
recordingPath = dest;
|
|
2851
2851
|
} else {
|
|
2852
|
-
logger.warn("Recording context did not produce a video file \
|
|
2852
|
+
logger.warn("Recording context did not produce a video file \xE2\u20AC\u201D recordVideo may have been ignored");
|
|
2853
2853
|
}
|
|
2854
2854
|
return {
|
|
2855
2855
|
recording_path: recordingPath,
|
|
@@ -2883,10 +2883,10 @@ async function resolveStorageState(browser, recording, authPlan) {
|
|
|
2883
2883
|
var PreflightError = class extends Error {
|
|
2884
2884
|
constructor(failures) {
|
|
2885
2885
|
const lines = failures.map(
|
|
2886
|
-
(f) => ` - ${f.segment}#${f.actionIndex} \
|
|
2886
|
+
(f) => ` - ${f.segment}#${f.actionIndex} \xE2\u2020\u2019 [${f.selectors.join(" | ")}]`
|
|
2887
2887
|
);
|
|
2888
2888
|
super(
|
|
2889
|
-
`Pre-flight check failed \
|
|
2889
|
+
`Pre-flight check failed \xE2\u20AC\u201D ${failures.length} selector(s) did not resolve on ${failures[0]?.segment ? `the live target page` : "the page"}:
|
|
2890
2890
|
${lines.join("\n")}
|
|
2891
2891
|
|
|
2892
2892
|
Fix the manifest selectors, or set recording.preflight: false to skip this check.`
|
|
@@ -4935,6 +4935,16 @@ function resolveMaybe(p, configDir) {
|
|
|
4935
4935
|
var STAGE_NAMES = ["comprehension", "script", "voiceover", "record", "mux"];
|
|
4936
4936
|
|
|
4937
4937
|
// src/pipeline/run.ts
|
|
4938
|
+
var PipelineStageError = class extends Error {
|
|
4939
|
+
constructor(stage, message, cause) {
|
|
4940
|
+
super(message);
|
|
4941
|
+
this.stage = stage;
|
|
4942
|
+
this.cause = cause;
|
|
4943
|
+
}
|
|
4944
|
+
stage;
|
|
4945
|
+
cause;
|
|
4946
|
+
name = "PipelineStageError";
|
|
4947
|
+
};
|
|
4938
4948
|
var STAGES_BY_NAME = {
|
|
4939
4949
|
comprehension: comprehensionStage,
|
|
4940
4950
|
script: scriptStage,
|
|
@@ -4974,7 +4984,14 @@ async function run(loaded, options = {}) {
|
|
|
4974
4984
|
continue;
|
|
4975
4985
|
}
|
|
4976
4986
|
const stage = STAGES_BY_NAME[name];
|
|
4977
|
-
|
|
4987
|
+
let result;
|
|
4988
|
+
try {
|
|
4989
|
+
result = await stage.run(ctx);
|
|
4990
|
+
} catch (err) {
|
|
4991
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4992
|
+
logger.event({ stage: name, status: "failed", error: message });
|
|
4993
|
+
throw new PipelineStageError(name, message, err);
|
|
4994
|
+
}
|
|
4978
4995
|
results.push(result);
|
|
4979
4996
|
logger.event({
|
|
4980
4997
|
stage: name,
|