@jevitate/cli 0.1.0 → 0.2.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/README.md +23 -0
- package/dist/ai-cli.js +40 -30
- package/dist/ai-cli.js.map +1 -1
- package/dist/author-journey-cli.d.ts +4 -0
- package/dist/author-journey-cli.js +109 -0
- package/dist/author-journey-cli.js.map +1 -0
- package/dist/bin.js +58077 -22454
- package/dist/bin.js.map +1 -1
- package/dist/browser-run-options.d.ts +58 -0
- package/dist/browser-run-options.js +106 -0
- package/dist/browser-run-options.js.map +1 -0
- package/dist/build-info.generated.d.ts +2 -0
- package/dist/build-info.generated.js +10 -0
- package/dist/build-info.generated.js.map +1 -0
- package/dist/check-api.d.ts +5 -0
- package/dist/check-api.js +233 -0
- package/dist/check-api.js.map +1 -0
- package/dist/check-budget.d.ts +26 -0
- package/dist/check-budget.js +89 -0
- package/dist/check-budget.js.map +1 -0
- package/dist/check-cli.d.ts +31 -0
- package/dist/check-cli.js +109 -0
- package/dist/check-cli.js.map +1 -0
- package/dist/check-execute.d.ts +25 -0
- package/dist/check-execute.js +385 -0
- package/dist/check-execute.js.map +1 -0
- package/dist/check-plan.d.ts +113 -0
- package/dist/check-plan.js +448 -0
- package/dist/check-plan.js.map +1 -0
- package/dist/check-suite.d.ts +171 -0
- package/dist/check-suite.js +515 -0
- package/dist/check-suite.js.map +1 -0
- package/dist/check-types.d.ts +181 -0
- package/dist/check-types.js +35 -0
- package/dist/check-types.js.map +1 -0
- package/dist/cli-args.d.ts +26 -0
- package/dist/cli-args.js +50 -0
- package/dist/cli-args.js.map +1 -0
- package/dist/cli-output.d.ts +102 -0
- package/dist/cli-output.js +516 -0
- package/dist/cli-output.js.map +1 -0
- package/dist/cli-reference.d.ts +3 -0
- package/dist/cli-reference.js +81 -0
- package/dist/cli-reference.js.map +1 -0
- package/dist/cli-refusal.d.ts +12 -0
- package/dist/cli-refusal.js +52 -0
- package/dist/cli-refusal.js.map +1 -0
- package/dist/cli-shared.d.ts +330 -0
- package/dist/cli-shared.js +492 -0
- package/dist/cli-shared.js.map +1 -0
- package/dist/cli-surface.d.ts +33 -0
- package/dist/cli-surface.js +48 -0
- package/dist/cli-surface.js.map +1 -0
- package/dist/conversation-options.d.ts +15 -0
- package/dist/conversation-options.js +10 -0
- package/dist/conversation-options.js.map +1 -0
- package/dist/credentials-file.d.ts +15 -0
- package/dist/credentials-file.js +56 -0
- package/dist/credentials-file.js.map +1 -0
- package/dist/data-dir.d.ts +1 -1
- package/dist/data-dir.js +1 -1
- package/dist/defect-evidence.d.ts +141 -0
- package/dist/defect-evidence.js +502 -0
- package/dist/defect-evidence.js.map +1 -0
- package/dist/demo-aspect-api.d.ts +209 -0
- package/dist/demo-aspect-api.js +397 -0
- package/dist/demo-aspect-api.js.map +1 -0
- package/dist/demo-aspect-cli.d.ts +3 -0
- package/dist/demo-aspect-cli.js +241 -0
- package/dist/demo-aspect-cli.js.map +1 -0
- package/dist/demo-capture.d.ts +108 -0
- package/dist/demo-capture.js +438 -0
- package/dist/demo-capture.js.map +1 -0
- package/dist/engine.d.ts +35 -0
- package/dist/engine.js +25 -0
- package/dist/engine.js.map +1 -0
- package/dist/environments.d.ts +155 -0
- package/dist/environments.js +364 -0
- package/dist/environments.js.map +1 -0
- package/dist/exit-codes.d.ts +46 -0
- package/dist/exit-codes.js +91 -0
- package/dist/exit-codes.js.map +1 -0
- package/dist/explore-adversarial.d.ts +137 -0
- package/dist/explore-adversarial.js +218 -0
- package/dist/explore-adversarial.js.map +1 -0
- package/dist/explore-api.d.ts +7 -187
- package/dist/explore-api.js +7 -301
- package/dist/explore-api.js.map +1 -1
- package/dist/explore-author.d.ts +79 -0
- package/dist/explore-author.js +86 -0
- package/dist/explore-author.js.map +1 -0
- package/dist/explore-cli.d.ts +7 -0
- package/dist/explore-cli.js +963 -0
- package/dist/explore-cli.js.map +1 -0
- package/dist/explore-coverage.d.ts +158 -0
- package/dist/explore-coverage.js +240 -0
- package/dist/explore-coverage.js.map +1 -0
- package/dist/explore-feature.d.ts +127 -0
- package/dist/explore-feature.js +220 -0
- package/dist/explore-feature.js.map +1 -0
- package/dist/explore-goal.d.ts +253 -0
- package/dist/explore-goal.js +374 -0
- package/dist/explore-goal.js.map +1 -0
- package/dist/explore-shared.d.ts +152 -0
- package/dist/explore-shared.js +129 -0
- package/dist/explore-shared.js.map +1 -0
- package/dist/explore-specs.d.ts +53 -0
- package/dist/explore-specs.js +333 -0
- package/dist/explore-specs.js.map +1 -0
- package/dist/findings-filing.d.ts +64 -0
- package/dist/findings-filing.js +108 -0
- package/dist/findings-filing.js.map +1 -0
- package/dist/fixture-auth.d.ts +52 -0
- package/dist/fixture-auth.js +82 -0
- package/dist/fixture-auth.js.map +1 -0
- package/dist/fixture-cli.d.ts +70 -0
- package/dist/fixture-cli.js +178 -0
- package/dist/fixture-cli.js.map +1 -0
- package/dist/github-issue-filer.d.ts +62 -0
- package/dist/github-issue-filer.js +188 -0
- package/dist/github-issue-filer.js.map +1 -0
- package/dist/host-health-run.d.ts +24 -0
- package/dist/host-health-run.js +27 -0
- package/dist/host-health-run.js.map +1 -0
- package/dist/http-5xx-outcome.d.ts +6 -0
- package/dist/http-5xx-outcome.js +39 -0
- package/dist/http-5xx-outcome.js.map +1 -0
- package/dist/inbox-cli.d.ts +7 -0
- package/dist/inbox-cli.js +197 -0
- package/dist/inbox-cli.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/init-cli.d.ts +4 -0
- package/dist/init-cli.js +127 -0
- package/dist/init-cli.js.map +1 -0
- package/dist/init-keys.d.ts +19 -2
- package/dist/init-keys.js +15 -4
- package/dist/init-keys.js.map +1 -1
- package/dist/init-next-steps.d.ts +35 -0
- package/dist/init-next-steps.js +79 -0
- package/dist/init-next-steps.js.map +1 -0
- package/dist/invariants-file.d.ts +34 -0
- package/dist/invariants-file.js +68 -0
- package/dist/invariants-file.js.map +1 -0
- package/dist/invariants-validate.d.ts +30 -0
- package/dist/invariants-validate.js +105 -0
- package/dist/invariants-validate.js.map +1 -0
- package/dist/journey-annotate-api.d.ts +76 -0
- package/dist/journey-annotate-api.js +256 -0
- package/dist/journey-annotate-api.js.map +1 -0
- package/dist/journey-annotate-cli.d.ts +9 -0
- package/dist/journey-annotate-cli.js +179 -0
- package/dist/journey-annotate-cli.js.map +1 -0
- package/dist/journey-api.d.ts +79 -2
- package/dist/journey-api.js +136 -19
- package/dist/journey-api.js.map +1 -1
- package/dist/journey-cli.d.ts +4 -0
- package/dist/journey-cli.js +370 -0
- package/dist/journey-cli.js.map +1 -0
- package/dist/journey-demo-api.d.ts +112 -0
- package/dist/journey-demo-api.js +392 -0
- package/dist/journey-demo-api.js.map +1 -0
- package/dist/journey-demo-cli.d.ts +10 -0
- package/dist/journey-demo-cli.js +155 -0
- package/dist/journey-demo-cli.js.map +1 -0
- package/dist/kill-signal.d.ts +193 -0
- package/dist/kill-signal.js +284 -0
- package/dist/kill-signal.js.map +1 -0
- package/dist/launch-armed.d.ts +37 -0
- package/dist/launch-armed.js +31 -0
- package/dist/launch-armed.js.map +1 -0
- package/dist/ledger-api.d.ts +106 -0
- package/dist/ledger-api.js +237 -0
- package/dist/ledger-api.js.map +1 -0
- package/dist/ledger-cli.d.ts +18 -0
- package/dist/ledger-cli.js +107 -0
- package/dist/ledger-cli.js.map +1 -0
- package/dist/load-api.d.ts +29 -11
- package/dist/load-api.js +23 -15
- package/dist/load-api.js.map +1 -1
- package/dist/load-cli.d.ts +4 -0
- package/dist/load-cli.js +97 -0
- package/dist/load-cli.js.map +1 -0
- package/dist/log-correlation.d.ts +147 -0
- package/dist/log-correlation.js +325 -0
- package/dist/log-correlation.js.map +1 -0
- package/dist/log-lines.d.ts +131 -0
- package/dist/log-lines.js +389 -0
- package/dist/log-lines.js.map +1 -0
- package/dist/log-sources.d.ts +71 -0
- package/dist/log-sources.js +235 -0
- package/dist/log-sources.js.map +1 -0
- package/dist/logs-cli.d.ts +3 -0
- package/dist/logs-cli.js +51 -0
- package/dist/logs-cli.js.map +1 -0
- package/dist/logs-retention.d.ts +28 -0
- package/dist/logs-retention.js +84 -0
- package/dist/logs-retention.js.map +1 -0
- package/dist/mcp-api.d.ts +89 -1
- package/dist/mcp-api.js +472 -18
- package/dist/mcp-api.js.map +1 -1
- package/dist/mcp-args.d.ts +38 -0
- package/dist/mcp-args.js +131 -0
- package/dist/mcp-args.js.map +1 -0
- package/dist/mcp-cli-bridge.d.ts +34 -0
- package/dist/mcp-cli-bridge.js +62 -0
- package/dist/mcp-cli-bridge.js.map +1 -0
- package/dist/mcp-cli-runner.d.ts +29 -0
- package/dist/mcp-cli-runner.js +44 -0
- package/dist/mcp-cli-runner.js.map +1 -0
- package/dist/mcp-cli-tools.d.ts +125 -0
- package/dist/mcp-cli-tools.js +680 -0
- package/dist/mcp-cli-tools.js.map +1 -0
- package/dist/mcp-paths.d.ts +28 -0
- package/dist/mcp-paths.js +76 -0
- package/dist/mcp-paths.js.map +1 -0
- package/dist/mission-actors.d.ts +40 -0
- package/dist/mission-actors.js +72 -0
- package/dist/mission-actors.js.map +1 -0
- package/dist/mission-api.d.ts +35 -0
- package/dist/mission-api.js +58 -2
- package/dist/mission-api.js.map +1 -1
- package/dist/mission-cli.d.ts +4 -0
- package/dist/mission-cli.js +247 -0
- package/dist/mission-cli.js.map +1 -0
- package/dist/mission-exit.d.ts +22 -0
- package/dist/mission-exit.js +26 -0
- package/dist/mission-exit.js.map +1 -0
- package/dist/mission-fixtures.d.ts +225 -0
- package/dist/mission-fixtures.js +828 -0
- package/dist/mission-fixtures.js.map +1 -0
- package/dist/mission-journal.d.ts +60 -0
- package/dist/mission-journal.js +115 -0
- package/dist/mission-journal.js.map +1 -0
- package/dist/mission-queue-cli.d.ts +10 -0
- package/dist/mission-queue-cli.js +198 -0
- package/dist/mission-queue-cli.js.map +1 -0
- package/dist/mission-queue-runner.d.ts +126 -0
- package/dist/mission-queue-runner.js +397 -0
- package/dist/mission-queue-runner.js.map +1 -0
- package/dist/multi-run-cli.d.ts +37 -0
- package/dist/multi-run-cli.js +110 -0
- package/dist/multi-run-cli.js.map +1 -0
- package/dist/multi-run.d.ts +339 -0
- package/dist/multi-run.js +619 -0
- package/dist/multi-run.js.map +1 -0
- package/dist/openrouter-call.d.ts +22 -0
- package/dist/openrouter-call.js +63 -0
- package/dist/openrouter-call.js.map +1 -0
- package/dist/profile-cli.d.ts +4 -0
- package/dist/profile-cli.js +57 -0
- package/dist/profile-cli.js.map +1 -0
- package/dist/program.d.ts +3 -75
- package/dist/program.js +119 -1921
- package/dist/program.js.map +1 -1
- package/dist/project-dir.d.ts +96 -0
- package/dist/project-dir.js +220 -0
- package/dist/project-dir.js.map +1 -0
- package/dist/record-api.d.ts +10 -6
- package/dist/record-api.js +39 -28
- package/dist/record-api.js.map +1 -1
- package/dist/record-cli.d.ts +4 -0
- package/dist/record-cli.js +64 -0
- package/dist/record-cli.js.map +1 -0
- package/dist/recording-cli.d.ts +4 -0
- package/dist/recording-cli.js +248 -0
- package/dist/recording-cli.js.map +1 -0
- package/dist/regression-api.d.ts +101 -0
- package/dist/regression-api.js +384 -5
- package/dist/regression-api.js.map +1 -1
- package/dist/regression-cli.d.ts +4 -0
- package/dist/regression-cli.js +232 -0
- package/dist/regression-cli.js.map +1 -0
- package/dist/report-api.d.ts +146 -0
- package/dist/report-api.js +430 -0
- package/dist/report-api.js.map +1 -0
- package/dist/report-cli.d.ts +12 -0
- package/dist/report-cli.js +147 -0
- package/dist/report-cli.js.map +1 -0
- package/dist/result-schema.d.ts +22 -0
- package/dist/result-schema.js +28 -0
- package/dist/result-schema.js.map +1 -0
- package/dist/run-index.d.ts +29 -0
- package/dist/run-index.js +70 -0
- package/dist/run-index.js.map +1 -0
- package/dist/run-screenshots.d.ts +123 -0
- package/dist/run-screenshots.js +229 -0
- package/dist/run-screenshots.js.map +1 -0
- package/dist/runtime-env.d.ts +8 -0
- package/dist/runtime-env.js +22 -0
- package/dist/runtime-env.js.map +1 -0
- package/dist/secret-args.d.ts +23 -0
- package/dist/secret-args.js +45 -0
- package/dist/secret-args.js.map +1 -0
- package/dist/serve-cli.d.ts +4 -0
- package/dist/serve-cli.js +95 -0
- package/dist/serve-cli.js.map +1 -0
- package/dist/server-log-verify.d.ts +34 -0
- package/dist/server-log-verify.js +115 -0
- package/dist/server-log-verify.js.map +1 -0
- package/dist/session-check.d.ts +14 -0
- package/dist/session-check.js +44 -0
- package/dist/session-check.js.map +1 -0
- package/dist/site-cli.d.ts +4 -0
- package/dist/site-cli.js +127 -0
- package/dist/site-cli.js.map +1 -0
- package/dist/site-gate-cli.d.ts +28 -0
- package/dist/site-gate-cli.js +58 -0
- package/dist/site-gate-cli.js.map +1 -0
- package/dist/source-api.js +18 -3
- package/dist/source-api.js.map +1 -1
- package/dist/source-cli.d.ts +4 -0
- package/dist/source-cli.js +284 -0
- package/dist/source-cli.js.map +1 -0
- package/dist/source-run-api.d.ts +27 -1
- package/dist/source-run-api.js +22 -11
- package/dist/source-run-api.js.map +1 -1
- package/dist/storage-state-snapshot.d.ts +50 -0
- package/dist/storage-state-snapshot.js +87 -0
- package/dist/storage-state-snapshot.js.map +1 -0
- package/dist/suite-explore-options.d.ts +289 -0
- package/dist/suite-explore-options.js +140 -0
- package/dist/suite-explore-options.js.map +1 -0
- package/dist/target-config.d.ts +109 -0
- package/dist/target-config.js +216 -0
- package/dist/target-config.js.map +1 -0
- package/dist/transcript-file.d.ts +12 -0
- package/dist/transcript-file.js +23 -0
- package/dist/transcript-file.js.map +1 -0
- package/dist/ui-api.d.ts +3 -0
- package/dist/ui-api.js +7 -1
- package/dist/ui-api.js.map +1 -1
- package/dist/usability-capture.d.ts +43 -0
- package/dist/usability-capture.js +326 -0
- package/dist/usability-capture.js.map +1 -0
- package/dist/usage-config.d.ts +36 -0
- package/dist/usage-config.js +114 -0
- package/dist/usage-config.js.map +1 -0
- package/dist/ux-api.d.ts +3 -75
- package/dist/ux-api.js +3 -220
- package/dist/ux-api.js.map +1 -1
- package/dist/ux-cli.d.ts +4 -0
- package/dist/ux-cli.js +102 -0
- package/dist/ux-cli.js.map +1 -0
- package/dist/ux-config.d.ts +29 -0
- package/dist/ux-config.js +103 -0
- package/dist/ux-config.js.map +1 -0
- package/dist/ux-evidence.d.ts +54 -0
- package/dist/ux-evidence.js +197 -0
- package/dist/ux-evidence.js.map +1 -0
- package/dist/ux-review.d.ts +112 -0
- package/dist/ux-review.js +151 -0
- package/dist/ux-review.js.map +1 -0
- package/dist/ux-usability.d.ts +238 -0
- package/dist/ux-usability.js +494 -0
- package/dist/ux-usability.js.map +1 -0
- package/dist/verify-fix-api.d.ts +173 -0
- package/dist/verify-fix-api.js +454 -0
- package/dist/verify-fix-api.js.map +1 -0
- package/dist/verify-fix-cli.d.ts +4 -0
- package/dist/verify-fix-cli.js +110 -0
- package/dist/verify-fix-cli.js.map +1 -0
- package/package.json +19 -14
- package/skills/jevitate-ci-check/SKILL.md +77 -0
- package/skills/jevitate-demo/SKILL.md +61 -0
- package/skills/jevitate-explore/SKILL.md +88 -87
- package/skills/jevitate-getting-started/SKILL.md +88 -0
- package/skills/jevitate-load-test/SKILL.md +11 -2
- package/skills/jevitate-mission-scope/SKILL.md +19 -11
- package/skills/jevitate-record/SKILL.md +23 -5
- package/skills/jevitate-run-journey/SKILL.md +61 -17
- package/skills/jevitate-sources/SKILL.md +57 -14
- package/skills/jevitate-ux-review/SKILL.md +106 -16
- package/skills/jevitate-verify-fix/SKILL.md +76 -0
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import { copyFile, mkdir, mkdtemp, readdir, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { basename, dirname, join } from "node:path";
|
|
4
|
+
import { FsJourneyStore, applyAnnotationDraft, describeStep, flatJourneySteps, secretParamValues, } from "@jevitate/journey";
|
|
5
|
+
import { assertNoSecretInPayload, redactText } from "@jevitate/ai-core";
|
|
6
|
+
import { DemoOverlay } from "@jevitate/explore";
|
|
7
|
+
import { PlaywrightBrowserPort } from "@jevitate/playwright";
|
|
8
|
+
import { BrowseTheWebToken } from "@jevitate/screenplay";
|
|
9
|
+
import { captureStepScreenshot, SecretPixelMask } from "./demo-capture.js";
|
|
10
|
+
import { runJourneyProgrammatically, UnknownJourneyError } from "./journey-api.js";
|
|
11
|
+
/**
|
|
12
|
+
* #248 — `jevitate journey demo <id>`: replay a Journey as a narrated demo. The overlay (#245) shows
|
|
13
|
+
* the Journey's goal as a title card, each step's objective as the caption (else its label, else a
|
|
14
|
+
* value-free description) with its target highlighted and a `pace` pause, then an outcome card. The
|
|
15
|
+
* outputs are made from the SAME replay: a video (Playwright recordVideo, WebM) with WebVTT subtitles
|
|
16
|
+
* timed to the captions, and a Markdown guide (goal, preconditions, per step its objective, expected
|
|
17
|
+
* result and a screenshot with the overlay hidden).
|
|
18
|
+
*
|
|
19
|
+
* The replay is `runJourneyProgrammatically` — the same fail-closed policy (paid/destructive steps
|
|
20
|
+
* refused), site policy, fixtures and environment (#247) as `journey run`; a demo never heals. A
|
|
21
|
+
* Journey that no longer replays is STALE: nothing is written and the command exits non-zero, so a
|
|
22
|
+
* CI job regenerating demos catches it. Every caption, cue and guide line is redacted with the run's
|
|
23
|
+
* secret parameters, and the written text is proven secret-free before it lands; the secret
|
|
24
|
+
* parameters are also masked in PIXELS — video and screenshots — by the display-only mask layer
|
|
25
|
+
* (#250/#251, `demo-capture.ts`), proven at every screenshot.
|
|
26
|
+
*/
|
|
27
|
+
/** How long each caption is shown before its step acts (`--pace`, ms). */
|
|
28
|
+
export const DEMO_DEFAULT_PACE_MS = 1500;
|
|
29
|
+
/** `--pace` bounds (ms). */
|
|
30
|
+
export const DEMO_MAX_PACE_MS = 60_000;
|
|
31
|
+
/** A demo's inputs were unusable (an output path of the wrong kind): nothing ran. */
|
|
32
|
+
export class DemoArgsError extends Error {
|
|
33
|
+
code = "E_JOURNEY_DEMO_ARGS";
|
|
34
|
+
}
|
|
35
|
+
/** The replay completed but a promised output could not be produced (no video file, a missing screenshot). */
|
|
36
|
+
export class DemoOutputError extends Error {
|
|
37
|
+
code = "E_JOURNEY_DEMO_OUTPUT";
|
|
38
|
+
}
|
|
39
|
+
/** #249: the mark every output of an unapproved demo carries. */
|
|
40
|
+
export const DEMO_DRAFT_MARK = "DRAFT";
|
|
41
|
+
/** A WebVTT timestamp: `HH:MM:SS.mmm`. */
|
|
42
|
+
export function vttTime(ms) {
|
|
43
|
+
const t = Math.max(0, Math.round(ms));
|
|
44
|
+
const pad = (n, w = 2) => String(n).padStart(w, "0");
|
|
45
|
+
return `${pad(Math.floor(t / 3_600_000))}:${pad(Math.floor(t / 60_000) % 60)}:${pad(Math.floor(t / 1000) % 60)}.${pad(t % 1000, 3)}`;
|
|
46
|
+
}
|
|
47
|
+
/** Cue text on one line with WebVTT's markup characters escaped (and never a `-->`). */
|
|
48
|
+
function vttText(s) {
|
|
49
|
+
return s.replace(/\s+/g, " ").trim().replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The WebVTT subtitles: one cue per step (`step-N`), in order; the goal as a leading NOTE. A draft
|
|
53
|
+
* (#249) says so in a NOTE and at the start of every cue.
|
|
54
|
+
*/
|
|
55
|
+
export function demoSubtitles(title, steps, draft = false) {
|
|
56
|
+
const note = title.replace(/\s+/g, " ").replace(/-->/g, "->").trim();
|
|
57
|
+
const mark = draft ? `[${DEMO_DRAFT_MARK}] ` : "";
|
|
58
|
+
const cues = steps.map((s) => `step-${s.number}\n${vttTime(s.cue.startMs)} --> ${vttTime(s.cue.endMs)}\n${vttText(`${mark}${s.caption}`)}\n`);
|
|
59
|
+
const draftNote = draft ? [`NOTE ${DEMO_DRAFT_MARK}: not yet approved (jevitate demo approve)\n`] : [];
|
|
60
|
+
return ["WEBVTT\n", ...draftNote, ...(note === "" ? [] : [`NOTE ${note}\n`]), ...cues].join("\n");
|
|
61
|
+
}
|
|
62
|
+
function oneLine(s) {
|
|
63
|
+
return s.replace(/\s+/g, " ").trim();
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The Markdown guide (all text already redacted); `assets` is the screenshots folder's name. A draft
|
|
67
|
+
* (#249) carries `DRAFT` in its title and a watermark line under it.
|
|
68
|
+
*/
|
|
69
|
+
export function demoGuide(journey, title, steps, assets, redact, draft = false) {
|
|
70
|
+
const m = journey.metadata;
|
|
71
|
+
const lines = [`# ${draft ? `${DEMO_DRAFT_MARK}: ` : ""}${oneLine(redact(m.name))}`, ""];
|
|
72
|
+
if (draft)
|
|
73
|
+
lines.push(`> **${DEMO_DRAFT_MARK}** — not yet approved. Review it, then run \`jevitate demo approve ${m.id}\` to promote the Journey and render the final demo.`, "");
|
|
74
|
+
lines.push(`**Goal:** ${oneLine(title)}`, "");
|
|
75
|
+
if (m.persona !== undefined || m.role !== undefined) {
|
|
76
|
+
const who = [m.persona, m.role === undefined ? undefined : `role: ${m.role}`].filter((x) => x !== undefined);
|
|
77
|
+
lines.push(`**Who:** ${oneLine(redact(who.join(" · ")))}`, "");
|
|
78
|
+
}
|
|
79
|
+
lines.push("## Before you start", "");
|
|
80
|
+
const pre = (m.preconditions ?? []).map((p) => `- ${oneLine(redact(p.description))}${p.login === true ? " (signed in)" : ""}`);
|
|
81
|
+
if (m.requiresAuth === true && !(m.preconditions ?? []).some((p) => p.login === true))
|
|
82
|
+
pre.push("- You are signed in.");
|
|
83
|
+
lines.push(...(pre.length === 0 ? ["Nothing to set up."] : pre), "", "## Steps", "");
|
|
84
|
+
for (const s of steps) {
|
|
85
|
+
lines.push(`### ${s.number}. ${oneLine(s.caption)}`, "");
|
|
86
|
+
if (s.expectedResult !== undefined)
|
|
87
|
+
lines.push(`**Expected result:** ${oneLine(s.expectedResult)}`, "");
|
|
88
|
+
if (s.screenshot !== undefined) {
|
|
89
|
+
const alt = `Step ${s.number}: ${oneLine(s.caption)}`.replace(/[[\]]/g, "");
|
|
90
|
+
lines.push(`}`)})`, "");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const criteria = (m.successCriteria ?? []).map((c) => `- ${oneLine(redact(c.description))}`);
|
|
94
|
+
if (criteria.length > 0)
|
|
95
|
+
lines.push("## When it worked", "", ...criteria, "");
|
|
96
|
+
return `${lines.join("\n").trimEnd()}\n`;
|
|
97
|
+
}
|
|
98
|
+
/** The step's caption: its objective, else its label, else a value-free description (redacted). */
|
|
99
|
+
function captionOf(s, redact) {
|
|
100
|
+
const pick = [s.recorded.objective, s.recorded.step.label].map((t) => (t ?? "").trim()).find((t) => t !== "");
|
|
101
|
+
return oneLine(redact(pick ?? describeStep(s.recorded.step)));
|
|
102
|
+
}
|
|
103
|
+
function targetOf(s) {
|
|
104
|
+
const step = s.recorded.step;
|
|
105
|
+
return step.target ?? null;
|
|
106
|
+
}
|
|
107
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
108
|
+
/** The title card is on screen at least this long (ms), whatever `--pace` is. */
|
|
109
|
+
export const TITLE_CARD_MIN_MS = 1200;
|
|
110
|
+
/** How long the title card waits for the recorder's first frame (ms) before going on regardless. */
|
|
111
|
+
export const FIRST_FRAME_WAIT_MS = 5_000;
|
|
112
|
+
/**
|
|
113
|
+
* Holds a card on screen for `ms`, re-applying it as it goes: the page is still on its initial
|
|
114
|
+
* about:blank, whose document the browser may replace right after it opens (wiping the card).
|
|
115
|
+
*/
|
|
116
|
+
async function holdCard(overlay, page, ms) {
|
|
117
|
+
const until = Date.now() + ms;
|
|
118
|
+
for (;;) {
|
|
119
|
+
const left = until - Date.now();
|
|
120
|
+
if (left <= 0)
|
|
121
|
+
return;
|
|
122
|
+
await sleep(Math.min(250, left));
|
|
123
|
+
await overlay.refresh(page);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* The demo video's clock (#248). Playwright's recorder stamps frames with the compositor's wall time
|
|
128
|
+
* and the WebM starts at the FIRST frame — which, on a loaded host, lands 1–3 s after the page
|
|
129
|
+
* opened. A frame probe (`page.screencast`, a second client of the same screencast: it is handed the
|
|
130
|
+
* latest frame at once, then every new one) reads that first frame's wall time; the probe stops after
|
|
131
|
+
* one frame. Without a probe (no video, or a page without `screencast`) the clock starts at `open`.
|
|
132
|
+
*/
|
|
133
|
+
class VideoClock {
|
|
134
|
+
#openedAt;
|
|
135
|
+
#firstFrameAt;
|
|
136
|
+
#first = Promise.resolve();
|
|
137
|
+
opened(page, video) {
|
|
138
|
+
this.#openedAt = Date.now();
|
|
139
|
+
const screencast = page.screencast;
|
|
140
|
+
if (!video || screencast === undefined)
|
|
141
|
+
return;
|
|
142
|
+
let seen = () => undefined;
|
|
143
|
+
const got = new Promise((r) => {
|
|
144
|
+
seen = r;
|
|
145
|
+
});
|
|
146
|
+
this.#first = got;
|
|
147
|
+
let stopped = false;
|
|
148
|
+
const stop = () => {
|
|
149
|
+
if (stopped)
|
|
150
|
+
return;
|
|
151
|
+
stopped = true;
|
|
152
|
+
void screencast.stop().catch(() => undefined);
|
|
153
|
+
};
|
|
154
|
+
screencast
|
|
155
|
+
.start({
|
|
156
|
+
onFrame: ({ timestamp }) => {
|
|
157
|
+
if (this.#firstFrameAt === undefined) {
|
|
158
|
+
this.#firstFrameAt = Number.isFinite(timestamp) && timestamp > 0 ? timestamp : Date.now();
|
|
159
|
+
seen();
|
|
160
|
+
// Off the frame callback: stopping from inside it would wait on this very frame's ack.
|
|
161
|
+
setTimeout(stop, 0);
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
})
|
|
165
|
+
.catch(() => seen());
|
|
166
|
+
setTimeout(() => {
|
|
167
|
+
seen();
|
|
168
|
+
stop();
|
|
169
|
+
}, FIRST_FRAME_WAIT_MS).unref();
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Resolves once the recorder has its first frame (bounded by {@link FIRST_FRAME_WAIT_MS}),
|
|
173
|
+
* calling `repaint` every 250 ms meanwhile (a page that paints nothing yields no frame).
|
|
174
|
+
*/
|
|
175
|
+
async recording(repaint) {
|
|
176
|
+
let waiting = true;
|
|
177
|
+
const done = this.#first.then(() => {
|
|
178
|
+
waiting = false;
|
|
179
|
+
});
|
|
180
|
+
while (waiting) {
|
|
181
|
+
await Promise.race([done, sleep(250)]);
|
|
182
|
+
if (waiting)
|
|
183
|
+
await repaint();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/** ms on the video's timeline: from its first frame, else from when the page opened. */
|
|
187
|
+
since() {
|
|
188
|
+
const start = this.#firstFrameAt ?? this.#openedAt;
|
|
189
|
+
return start === undefined ? 0 : Math.max(0, Date.now() - start);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/** `<dir>/<name>.assets` for `<dir>/<name>.md`. */
|
|
193
|
+
export function guideAssetsDir(guide) {
|
|
194
|
+
return join(dirname(guide), `${basename(guide).replace(/\.md$/i, "")}.assets`);
|
|
195
|
+
}
|
|
196
|
+
/** `<video without .webm>.vtt`. */
|
|
197
|
+
export function subtitlesPathFor(video) {
|
|
198
|
+
return video.replace(/\.webm$/i, ".vtt");
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Replays the Journey as a narrated demo and writes the asked-for outputs (see the module comment).
|
|
202
|
+
* Throws `UnknownJourneyError` / `DemoArgsError` before any browser opens, and every refusal
|
|
203
|
+
* `runJourneyProgrammatically` has; returns `outcome: "stale"` (writing nothing) when the replay stops.
|
|
204
|
+
*/
|
|
205
|
+
export async function demoJourney(opts) {
|
|
206
|
+
if (opts.video !== undefined && !/\.webm$/i.test(opts.video)) {
|
|
207
|
+
throw new DemoArgsError(`--video must be a .webm file (Playwright records WebM; convert it afterwards, e.g. with ffmpeg): ${opts.video}`);
|
|
208
|
+
}
|
|
209
|
+
if (opts.guide !== undefined && !/\.md$/i.test(opts.guide))
|
|
210
|
+
throw new DemoArgsError(`--guide must be a Markdown (.md) file: ${opts.guide}`);
|
|
211
|
+
const pace = opts.paceMs ?? DEMO_DEFAULT_PACE_MS;
|
|
212
|
+
if (!Number.isSafeInteger(pace) || pace < 0 || pace > DEMO_MAX_PACE_MS)
|
|
213
|
+
throw new DemoArgsError(`--pace must be an integer from 0 to ${DEMO_MAX_PACE_MS} (got ${pace})`);
|
|
214
|
+
const stored = await new FsJourneyStore(opts.dir).get(opts.id);
|
|
215
|
+
if (stored === null)
|
|
216
|
+
throw new UnknownJourneyError(`unknown journey '${opts.id}'`);
|
|
217
|
+
// #249: a draft's annotations narrate the demo without being written into the Journey.
|
|
218
|
+
const journey = opts.annotations === undefined ? stored : applyAnnotationDraft(stored, opts.annotations).journey;
|
|
219
|
+
const draft = opts.draft === true;
|
|
220
|
+
const secrets = secretParamValues(journey, opts.params);
|
|
221
|
+
const redact = (s) => redactText(s, secrets);
|
|
222
|
+
const flat = flatJourneySteps(journey);
|
|
223
|
+
const title = oneLine(redact((journey.metadata.goal ?? "").trim() || journey.metadata.name));
|
|
224
|
+
const work = await mkdtemp(join(tmpdir(), "jevitate-demo-"));
|
|
225
|
+
// #250/#251: the demo's secret parameters are masked in pixels — in the video from its first
|
|
226
|
+
// paint, and proven at every guide screenshot (a capture whose mask cannot be proven fails).
|
|
227
|
+
const mask = new SecretPixelMask(secrets);
|
|
228
|
+
const layers = [mask.layer(), ...(opts.captureLayers ?? [])];
|
|
229
|
+
try {
|
|
230
|
+
const overlay = new DemoOverlay(secrets);
|
|
231
|
+
// The video's timeline starts at its FIRST FRAME, which under load arrives seconds after the page
|
|
232
|
+
// opens (on about:blank): cues count from that frame, not from `open`, and the title card waits for
|
|
233
|
+
// it — else the card is shown before anything is recorded and every cue runs late.
|
|
234
|
+
const clock = new VideoClock();
|
|
235
|
+
const basePort = opts.browserPortFactory ?? (() => new PlaywrightBrowserPort());
|
|
236
|
+
const timedPort = () => {
|
|
237
|
+
const port = basePort();
|
|
238
|
+
return {
|
|
239
|
+
open: async (o) => {
|
|
240
|
+
const session = await port.open(o);
|
|
241
|
+
clock.opened(session.page, opts.video !== undefined);
|
|
242
|
+
return session;
|
|
243
|
+
},
|
|
244
|
+
};
|
|
245
|
+
};
|
|
246
|
+
const since = () => clock.since();
|
|
247
|
+
const steps = [];
|
|
248
|
+
const captureErrors = [];
|
|
249
|
+
const shots = join(work, "shots");
|
|
250
|
+
await mkdir(shots, { recursive: true });
|
|
251
|
+
const closeLast = () => {
|
|
252
|
+
const last = steps[steps.length - 1];
|
|
253
|
+
if (last !== undefined && last.endMs === undefined)
|
|
254
|
+
last.endMs = Math.max(since(), last.startMs + 1);
|
|
255
|
+
};
|
|
256
|
+
const observer = {
|
|
257
|
+
beforeStep: async ({ actor, index }) => {
|
|
258
|
+
const page = actor.ability(BrowseTheWebToken).session.page;
|
|
259
|
+
const s = flat[index];
|
|
260
|
+
if (s === undefined)
|
|
261
|
+
return;
|
|
262
|
+
if (index === 0) {
|
|
263
|
+
if (draft)
|
|
264
|
+
await overlay.watermark(page, DEMO_DRAFT_MARK);
|
|
265
|
+
await overlay.card(page, title, "title");
|
|
266
|
+
// An idle about:blank paints nothing new: the card's own paint is what the recorder (and
|
|
267
|
+
// the clock's probe) may be waiting for. Its hold starts once the video has frames.
|
|
268
|
+
await clock.recording(() => overlay.refresh(page));
|
|
269
|
+
await holdCard(overlay, page, Math.max(pace, TITLE_CARD_MIN_MS));
|
|
270
|
+
}
|
|
271
|
+
closeLast();
|
|
272
|
+
const caption = captionOf(s, redact);
|
|
273
|
+
const expected = oneLine(redact(s.recorded.expectedResult ?? ""));
|
|
274
|
+
steps.push({ number: index + 1, caption, ...(expected === "" ? {} : { expectedResult: expected }), startMs: since() });
|
|
275
|
+
await overlay.caption(page, { head: `step ${index + 1} of ${flat.length}`, text: caption }, targetOf(s));
|
|
276
|
+
await sleep(pace);
|
|
277
|
+
},
|
|
278
|
+
afterStep: async ({ actor, index, outcome }) => {
|
|
279
|
+
const page = actor.ability(BrowseTheWebToken).session.page;
|
|
280
|
+
if (outcome === "done") {
|
|
281
|
+
// A navigation re-renders the overlay asynchronously: re-apply it so the video shows it now.
|
|
282
|
+
await overlay.refresh(page);
|
|
283
|
+
if (opts.guide !== undefined) {
|
|
284
|
+
const file = join(shots, `step-${String(index + 1).padStart(2, "0")}.png`);
|
|
285
|
+
try {
|
|
286
|
+
await captureStepScreenshot(page, file, { step: index + 1 }, layers);
|
|
287
|
+
const entry = steps.find((x) => x.number === index + 1);
|
|
288
|
+
if (entry !== undefined)
|
|
289
|
+
entry.screenshot = file;
|
|
290
|
+
}
|
|
291
|
+
catch (err) {
|
|
292
|
+
captureErrors.push(`step ${index + 1}: ${redact(err instanceof Error ? err.message : String(err))}`);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
if (index === flat.length - 1) {
|
|
296
|
+
closeLast();
|
|
297
|
+
await overlay.card(page, `Done: ${title}`, "ok");
|
|
298
|
+
await sleep(pace);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
closeLast();
|
|
303
|
+
await overlay.card(page, `Stopped at step ${index + 1}: this demo no longer replays`, "bad");
|
|
304
|
+
await sleep(pace);
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
};
|
|
308
|
+
const { video, guide, paceMs: _pace, captureLayers: _layers, annotations: _annotations, draft: _draft, ...runOpts } = opts;
|
|
309
|
+
const browser = video === undefined ? opts.browser : { ...opts.browser, recordVideo: { dir: work } };
|
|
310
|
+
const run = await runJourneyProgrammatically({
|
|
311
|
+
...runOpts,
|
|
312
|
+
...(browser === undefined ? {} : { browser }),
|
|
313
|
+
browserPortFactory: timedPort,
|
|
314
|
+
observer,
|
|
315
|
+
mask,
|
|
316
|
+
});
|
|
317
|
+
closeLast();
|
|
318
|
+
const done = steps.map((s) => ({
|
|
319
|
+
number: s.number,
|
|
320
|
+
caption: s.caption,
|
|
321
|
+
...(s.expectedResult === undefined ? {} : { expectedResult: s.expectedResult }),
|
|
322
|
+
cue: { startMs: Math.round(s.startMs), endMs: Math.round(s.endMs ?? s.startMs + 1) },
|
|
323
|
+
...(s.screenshot === undefined ? {} : { screenshot: s.screenshot }),
|
|
324
|
+
}));
|
|
325
|
+
if (run.outcome === "quarantined") {
|
|
326
|
+
// A stale demo writes nothing: not even the screenshots its replay took.
|
|
327
|
+
for (const f of [...(run.screenshotPaths ?? []), ...(run.screenshotIndex === undefined ? [] : [run.screenshotIndex])])
|
|
328
|
+
await rm(f, { force: true });
|
|
329
|
+
const at = run.at === undefined ? undefined : run.at + 1;
|
|
330
|
+
return {
|
|
331
|
+
id: opts.id,
|
|
332
|
+
outcome: "stale",
|
|
333
|
+
reason: redact(run.reason).slice(0, 2000),
|
|
334
|
+
...(at === undefined ? {} : { stoppedAtStep: at }),
|
|
335
|
+
totalSteps: flat.length,
|
|
336
|
+
steps: done.map(({ screenshot: _s, ...s }) => s),
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
// The replay completed: every promised output must exist — never a silently partial demo.
|
|
340
|
+
if (guide !== undefined) {
|
|
341
|
+
const missing = done.filter((s) => s.screenshot === undefined).map((s) => s.number);
|
|
342
|
+
if (captureErrors.length > 0 || missing.length > 0) {
|
|
343
|
+
throw new DemoOutputError(`could not capture a screenshot for step(s) ${missing.join(", ")}${captureErrors.length > 0 ? `: ${captureErrors.join("; ")}` : ""}`);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
let videoFile;
|
|
347
|
+
if (video !== undefined) {
|
|
348
|
+
videoFile = run.videoPaths?.[0];
|
|
349
|
+
if (videoFile === undefined)
|
|
350
|
+
throw new DemoOutputError("the replay recorded no video");
|
|
351
|
+
}
|
|
352
|
+
const result = { steps: done };
|
|
353
|
+
if (video !== undefined && videoFile !== undefined) {
|
|
354
|
+
const vtt = demoSubtitles(title, done, draft);
|
|
355
|
+
assertNoSecretInPayload(vtt, secrets, "demo subtitles"); // the last line: never at rest
|
|
356
|
+
await mkdir(dirname(video), { recursive: true });
|
|
357
|
+
await copyFile(videoFile, video);
|
|
358
|
+
const subtitles = subtitlesPathFor(video);
|
|
359
|
+
await writeFile(subtitles, vtt);
|
|
360
|
+
Object.assign(result, { video, subtitles });
|
|
361
|
+
}
|
|
362
|
+
if (guide !== undefined) {
|
|
363
|
+
const assets = guideAssetsDir(guide);
|
|
364
|
+
await mkdir(assets, { recursive: true });
|
|
365
|
+
// A regenerated guide never keeps an older, longer run's screenshots.
|
|
366
|
+
for (const f of await readdir(assets))
|
|
367
|
+
if (/^step-\d+\.png$/.test(f))
|
|
368
|
+
await rm(join(assets, f), { force: true });
|
|
369
|
+
const placed = await Promise.all(done.map(async (s) => {
|
|
370
|
+
if (s.screenshot === undefined)
|
|
371
|
+
return s;
|
|
372
|
+
const to = join(assets, basename(s.screenshot));
|
|
373
|
+
await copyFile(s.screenshot, to);
|
|
374
|
+
return { ...s, screenshot: to };
|
|
375
|
+
}));
|
|
376
|
+
const md = demoGuide(journey, title, placed, basename(assets), redact, draft);
|
|
377
|
+
assertNoSecretInPayload(md, secrets, "demo guide");
|
|
378
|
+
await writeFile(guide, md);
|
|
379
|
+
Object.assign(result, { guide, steps: placed });
|
|
380
|
+
}
|
|
381
|
+
const shotFields = {
|
|
382
|
+
...(run.screenshotPaths === undefined ? {} : { screenshotPaths: run.screenshotPaths }),
|
|
383
|
+
...(run.screenshotIndex === undefined ? {} : { screenshotIndex: run.screenshotIndex }),
|
|
384
|
+
...(run.screenshotsSkipped === undefined ? {} : { screenshotsSkipped: run.screenshotsSkipped }),
|
|
385
|
+
};
|
|
386
|
+
return { id: opts.id, outcome: "ok", totalSteps: flat.length, ...result, ...shotFields };
|
|
387
|
+
}
|
|
388
|
+
finally {
|
|
389
|
+
await rm(work, { recursive: true, force: true });
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
//# sourceMappingURL=journey-demo-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journey-demo-api.js","sourceRoot":"","sources":["../src/journey-demo-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import { type CliDeps } from "./cli-shared.js";
|
|
3
|
+
/**
|
|
4
|
+
* #248 — `jevitate journey demo <id>`: replay a Journey as a narrated demo (goal title card, each
|
|
5
|
+
* step's objective as the caption with its target highlighted, an outcome card) and write a video
|
|
6
|
+
* with WebVTT subtitles and/or a Markdown guide with a screenshot per step. Headless by default;
|
|
7
|
+
* `--headed` presents it live. With neither `--video` nor `--guide`, both go to a fresh folder in
|
|
8
|
+
* the logs dir. A Journey that no longer replays writes nothing and exits 1 (a stale demo).
|
|
9
|
+
*/
|
|
10
|
+
export declare function registerJourneyDemoCommand(journey: Command, program: Command, deps: CliDeps): void;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { formatScreenshotsLine, parseScreenshotsArg } from "./run-screenshots.js";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { join, resolve as resolvePath } from "node:path";
|
|
4
|
+
import { ParamValidationError } from "@jevitate/journey";
|
|
5
|
+
import { SecretLeakError } from "@jevitate/ai-core";
|
|
6
|
+
import { SiteGateRefusedError } from "@jevitate/runtime";
|
|
7
|
+
import { ok, fail } from "./envelope.js";
|
|
8
|
+
import { UnknownJourneyError, JourneyRequiresAuthError } from "./journey-api.js";
|
|
9
|
+
import { DEMO_DEFAULT_PACE_MS, DEMO_MAX_PACE_MS, DemoArgsError, DemoOutputError, demoJourney } from "./journey-demo-api.js";
|
|
10
|
+
import { intArg } from "./cli-args.js";
|
|
11
|
+
import { artifactStamp } from "./mission-journal.js";
|
|
12
|
+
import { logsDirFor } from "./project-dir.js";
|
|
13
|
+
import { withSiteGate } from "./site-gate-cli.js";
|
|
14
|
+
import { buildMissionFixtures, checkSetupRefs, withFixtureFlags } from "./fixture-cli.js";
|
|
15
|
+
import { FixtureSetupError, FixtureSpecError, UnboundSetupRefError } from "./mission-fixtures.js";
|
|
16
|
+
import { withEngine } from "./engine.js";
|
|
17
|
+
import { EXIT_CODES } from "./exit-codes.js";
|
|
18
|
+
import { environmentFromFlags, isEnvironmentError, withEnvironmentFlags } from "./environments.js";
|
|
19
|
+
import { resolveDbPath, resolveJourneysDir, withBrowserLaunchFlags, browserRunFromFlags, withDemoFlags, withScreenshotsFlag, withEmulationFlags, emulationFromFlags, collectParam, emitJson, environmentSeams, } from "./cli-shared.js";
|
|
20
|
+
/**
|
|
21
|
+
* #248 — `jevitate journey demo <id>`: replay a Journey as a narrated demo (goal title card, each
|
|
22
|
+
* step's objective as the caption with its target highlighted, an outcome card) and write a video
|
|
23
|
+
* with WebVTT subtitles and/or a Markdown guide with a screenshot per step. Headless by default;
|
|
24
|
+
* `--headed` presents it live. With neither `--video` nor `--guide`, both go to a fresh folder in
|
|
25
|
+
* the logs dir. A Journey that no longer replays writes nothing and exits 1 (a stale demo).
|
|
26
|
+
*/
|
|
27
|
+
export function registerJourneyDemoCommand(journey, program, deps) {
|
|
28
|
+
withScreenshotsFlag(withEnvironmentFlags(withDemoFlags(withBrowserLaunchFlags(withEmulationFlags(withFixtureFlags(journey.command("demo <id>")))))))
|
|
29
|
+
.description("replay a Journey as a narrated demo (goal, step objectives as captions, target highlights) → a WebM video with .vtt subtitles " +
|
|
30
|
+
"and/or a Markdown step-by-step guide with screenshots; a Journey that no longer replays fails (exit 1)")
|
|
31
|
+
.option("--dir <path>", "journeys directory (default: the repo's .jevitate/journeys; outside a repo ~/.jevitate/journeys)")
|
|
32
|
+
.option("--param <kv>", "param as key=value (repeatable)", collectParam, {})
|
|
33
|
+
.option("--storage-state <file>", "Playwright storageState JSON to start the replay authenticated; must exist")
|
|
34
|
+
.option("--video <file>", "write the demo video here (.webm) and its subtitles beside it (.vtt)")
|
|
35
|
+
.option("--guide <file>", "write a Markdown guide here (.md), screenshots in <name>.assets/ beside it")
|
|
36
|
+
.option("--pace <ms>", `how long each step's caption shows before it acts (default ${DEMO_DEFAULT_PACE_MS})`, intArg({ min: 0, max: DEMO_MAX_PACE_MS }))
|
|
37
|
+
.option("--json", "emit a JSON envelope")
|
|
38
|
+
.action(async function (id) {
|
|
39
|
+
const ownFixtureFlags = this.opts();
|
|
40
|
+
const { dir, param, storageState: storageStateFlag, video: videoFlag, guide: guideFlag, pace, json, env: envName, baseUrl, screenshots: screenshotsFlag, ...rest } = this.opts();
|
|
41
|
+
const out = program.configureOutput().writeOut;
|
|
42
|
+
const journeysDir = resolveJourneysDir(deps, dir);
|
|
43
|
+
// #247: --env/--base-url choose where the demo runs — the same resolver as `journey run`.
|
|
44
|
+
let environment;
|
|
45
|
+
try {
|
|
46
|
+
environment = environmentFromFlags({ ...(envName === undefined ? {} : { env: envName }), ...(baseUrl === undefined ? {} : { baseUrl }) }, environmentSeams(deps));
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
if (!isEnvironmentError(err))
|
|
50
|
+
throw err;
|
|
51
|
+
emitJson(program, fail(err.code, err.message));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const fixtureFlags = {
|
|
55
|
+
...ownFixtureFlags,
|
|
56
|
+
...(ownFixtureFlags.before === undefined && environment?.hooks?.before !== undefined ? { before: environment.hooks.before } : {}),
|
|
57
|
+
...(ownFixtureFlags.after === undefined && environment?.hooks?.after !== undefined ? { after: environment.hooks.after } : {}),
|
|
58
|
+
};
|
|
59
|
+
const storageState = storageStateFlag ?? environment?.storageState;
|
|
60
|
+
if (storageState !== undefined && !existsSync(storageState)) {
|
|
61
|
+
emitJson(program, fail("E_JOURNEY_DEMO_ARGS", `storage state not found: ${storageState}`));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// #245: --headed (a display is required) and --slow-mo, resolved before any browser opens.
|
|
65
|
+
let browser;
|
|
66
|
+
let emulation;
|
|
67
|
+
let screenshots;
|
|
68
|
+
try {
|
|
69
|
+
browser = browserRunFromFlags(this.opts(), deps.explore?.env ?? process.env);
|
|
70
|
+
emulation = emulationFromFlags({ viewport: rest.viewport, device: rest.device });
|
|
71
|
+
screenshots = parseScreenshotsArg(screenshotsFlag);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
emitJson(program, fail("E_JOURNEY_DEMO_ARGS", err instanceof Error ? err.message : String(err)));
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
// Neither output named: both, in a fresh folder in the logs dir (git-ignored, pruned like any run log).
|
|
78
|
+
let video = videoFlag === undefined ? undefined : resolvePath(videoFlag);
|
|
79
|
+
let guide = guideFlag === undefined ? undefined : resolvePath(guideFlag);
|
|
80
|
+
if (video === undefined && guide === undefined) {
|
|
81
|
+
const folder = join(logsDirFor(), `journey-demo-${id.replace(/[^A-Za-z0-9._-]/g, "_")}-${artifactStamp(new Date().toISOString())}`);
|
|
82
|
+
video = join(folder, "demo.webm");
|
|
83
|
+
guide = join(folder, "guide.md");
|
|
84
|
+
}
|
|
85
|
+
try {
|
|
86
|
+
const result = await withSiteGate(resolveDbPath(deps), (siteGate) => demoJourney({
|
|
87
|
+
...(siteGate === undefined ? {} : { siteGate }),
|
|
88
|
+
dir: journeysDir,
|
|
89
|
+
id,
|
|
90
|
+
params: param,
|
|
91
|
+
browserPortFactory: deps.explore?.browserPortFactory,
|
|
92
|
+
...(browser === undefined ? {} : { browser }),
|
|
93
|
+
...(emulation === undefined ? {} : { emulation }),
|
|
94
|
+
...(screenshots === undefined ? {} : { screenshots }),
|
|
95
|
+
...(storageState !== undefined ? { storageState } : {}),
|
|
96
|
+
...(environment === undefined ? {} : { environment }),
|
|
97
|
+
...(video === undefined ? {} : { video }),
|
|
98
|
+
...(guide === undefined ? {} : { guide }),
|
|
99
|
+
...(pace === undefined ? {} : { paceMs: pace }),
|
|
100
|
+
fixtures: (site) => {
|
|
101
|
+
const fx = buildMissionFixtures(fixtureFlags, {
|
|
102
|
+
allowlist: environment === undefined ? [site] : environment.allowedOrigins,
|
|
103
|
+
baseUrl: site,
|
|
104
|
+
...(storageState !== undefined ? { storageState } : {}),
|
|
105
|
+
...(environment?.fixtures === undefined ? {} : { targetFixtures: environment.fixtures }),
|
|
106
|
+
});
|
|
107
|
+
checkSetupRefs({ "--param": Object.values(param) }, fx);
|
|
108
|
+
return fx;
|
|
109
|
+
},
|
|
110
|
+
}));
|
|
111
|
+
const data = withEngine(result);
|
|
112
|
+
// A stale demo (the Journey no longer replays) is a failed check: exit 1, and nothing written.
|
|
113
|
+
const exit = result.outcome === "ok" ? EXIT_CODES.ok : EXIT_CODES.defects;
|
|
114
|
+
if (json) {
|
|
115
|
+
emitJson(program, ok(data));
|
|
116
|
+
}
|
|
117
|
+
else if (result.outcome === "stale") {
|
|
118
|
+
program.configureOutput().writeErr?.(`error: demo of journey '${id}' is stale: it no longer replays` +
|
|
119
|
+
`${result.stoppedAtStep === undefined ? "" : ` (stopped at step ${result.stoppedAtStep} of ${result.totalSteps})`}: ${result.reason ?? "unknown"}\n` +
|
|
120
|
+
`nothing was written — fix or re-record the Journey, then regenerate the demo\n`);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
out?.(`demo of journey '${id}': ${result.steps.length} step(s) replayed\n`);
|
|
124
|
+
if (result.video !== undefined)
|
|
125
|
+
out?.(`video: ${result.video}\nsubtitles: ${result.subtitles ?? ""}\n`);
|
|
126
|
+
if (result.guide !== undefined)
|
|
127
|
+
out?.(`guide: ${result.guide}\n`);
|
|
128
|
+
if (result.screenshotIndex !== undefined)
|
|
129
|
+
out?.(formatScreenshotsLine(result));
|
|
130
|
+
}
|
|
131
|
+
process.exitCode = exit;
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
if (err instanceof SiteGateRefusedError || isEnvironmentError(err))
|
|
135
|
+
emitJson(program, fail(err.code, err.message));
|
|
136
|
+
else if (err instanceof DemoArgsError || err instanceof DemoOutputError)
|
|
137
|
+
emitJson(program, fail(err.code, err.message));
|
|
138
|
+
else if (err instanceof UnknownJourneyError)
|
|
139
|
+
emitJson(program, fail("E_UNKNOWN_JOURNEY", err.message));
|
|
140
|
+
else if (err instanceof JourneyRequiresAuthError)
|
|
141
|
+
emitJson(program, fail("E_JOURNEY_REQUIRES_AUTH", err.message));
|
|
142
|
+
else if (err instanceof ParamValidationError)
|
|
143
|
+
emitJson(program, fail("E_INVALID_PARAMS", err.message));
|
|
144
|
+
else if (err instanceof FixtureSpecError || err instanceof UnboundSetupRefError)
|
|
145
|
+
emitJson(program, fail(err.code, err.message));
|
|
146
|
+
else if (err instanceof FixtureSetupError)
|
|
147
|
+
emitJson(program, fail("E_JOURNEY_DEMO", err.message));
|
|
148
|
+
else if (err instanceof SecretLeakError)
|
|
149
|
+
emitJson(program, fail("E_JOURNEY_DEMO_SECRET", err.message));
|
|
150
|
+
else
|
|
151
|
+
emitJson(program, fail("E_JOURNEY_DEMO", String(err instanceof Error ? err.message : err)));
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=journey-demo-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journey-demo-cli.js","sourceRoot":"","sources":["../src/journey-demo-cli.ts"],"names":[],"mappings":"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"}
|