@outerlayer/cli 0.34.0-next.20261026214534 → 0.34.0-next.20261026230708
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 +12 -4
- package/dist/{build-BBWAD5LR.js → build-M4UYZAFH.js} +3 -2
- package/dist/{build-disk-TGLM5XK7.js → build-disk-ZDVSSHO2.js} +3 -2
- package/dist/build-info.json +1 -1
- package/dist/{builder-FD53GTWL.js → builder-IORYS76D.js} +2 -1
- package/dist/{check-FOWN6M3C.js → check-V66LZDNK.js} +15 -14
- package/dist/{chunk-T2HH7IHT.js → chunk-63A6NUEZ.js} +1 -1
- package/dist/{chunk-3HJMY3H5.js → chunk-6NXBXWOP.js} +1 -1
- package/dist/{chunk-3PUOHONX.js → chunk-DFBY6LX3.js} +6 -5
- package/dist/{chunk-RNMCFAYH.js → chunk-F5H3LVHR.js} +2 -2
- package/dist/chunk-HDLON3RJ.js +274 -0
- package/dist/{chunk-FVF2LMVG.js → chunk-IZVDQXTC.js} +9 -9
- package/dist/{chunk-LY62UHRR.js → chunk-JZLMFYFM.js} +1 -1
- package/dist/{chunk-XYLHSCLR.js → chunk-KOZ6IBEI.js} +8 -279
- package/dist/{chunk-K3ACC2CV.js → chunk-MIRCFK4X.js} +2 -33
- package/dist/{chunk-5ZBVKRDK.js → chunk-PN7RMFPP.js} +2 -2
- package/dist/{chunk-BQQPDBSF.js → chunk-Q3L5AC75.js} +2 -2
- package/dist/{chunk-2GDKM2O4.js → chunk-T6HSNQAT.js} +4 -4
- package/dist/{chunk-KR2TIRNQ.js → chunk-T7HUNNJ2.js} +30 -16
- package/dist/{chunk-JKLSQOYO.js → chunk-TGBST2QL.js} +11 -7
- package/dist/{chunk-3NCWHEGM.js → chunk-TLIZ7FY4.js} +2 -2
- package/dist/{chunk-XHZBLIB2.js → chunk-XDJ376OP.js} +7 -1
- package/dist/{chunk-ZADRW2V2.js → chunk-XLJXO4QC.js} +4 -4
- package/dist/{cli-3RDQSLYI.js → cli-HQWQEHXJ.js} +79 -44
- package/dist/{command-C5YKBTK4.js → command-TONUMZ2A.js} +8 -7
- package/dist/{config-EBT5VYPX.js → config-4K6OG2SZ.js} +4 -3
- package/dist/{container-start-RLX2PL3C.js → container-start-R74IO7CI.js} +12 -11
- package/dist/demo-record-cmd-7HJ5C7KM.js +208 -0
- package/dist/{demo-voice-cmd-DF6C7EST.js → demo-voice-cmd-MBK3BGHZ.js} +1 -2
- package/dist/{docker-CP656XNO.js → docker-XWQM4F7B.js} +2 -1
- package/dist/{doctor-EQIAHHZD.js → doctor-SF4GAWAO.js} +9 -8
- package/dist/{emit-demo-cmd-YKTL6XWP.js → emit-demo-cmd-6VTA5BSJ.js} +1 -2
- package/dist/{find-unit-O6WL6UIW.js → find-unit-I4GWKY4T.js} +6 -5
- package/dist/{host-checks-V25YUP4Q.js → host-checks-FKLQST3J.js} +10 -9
- package/dist/index.js +1 -1
- package/dist/{init-KO3FT2XP.js → init-3MO5WCU3.js} +8 -7
- package/dist/{init-YYZ7B4ZD.js → init-TDLUTI6F.js} +8 -7
- package/dist/{init-cmd-D3BDS7KY.js → init-cmd-MQ5R35O2.js} +1 -1
- package/dist/{loop-UVONXWXB.js → loop-NNNDBFAS.js} +14 -13
- package/dist/{machine-2BI76JZO.js → machine-GCW2GGI2.js} +8 -7
- package/dist/recorder.cjs +916 -0
- package/dist/{runner-env-QN4BLTVZ.js → runner-env-LVVLUHY2.js} +6 -5
- package/dist/{runner-identity-53I4UTVY.js → runner-identity-73F2IWBT.js} +2 -1
- package/dist/{runner-key-JKXJWGGY.js → runner-key-ASPZ7TQH.js} +8 -7
- package/dist/{status-YCQHAY45.js → status-35Z3TW42.js} +10 -9
- package/dist/{update-steps-MC3IUHW7.js → update-steps-ZTNIK7LA.js} +11 -10
- package/dist/{work-claim-cmd-O54L5DSL.js → work-claim-cmd-QPYCZUMI.js} +4 -3
- package/dist/{work-proofs-cmd-LIXV252G.js → work-proofs-cmd-56EY7O45.js} +1 -1
- package/dist/{work-proofs-record-MCSA56F5.js → work-proofs-record-SPGI47OS.js} +2 -3
- package/package.json +5 -4
- package/skill-pack/maintained/outerlayer-amend/SKILL.md +2 -2
- package/skill-pack/maintained/outerlayer-build/references/evidence.md +12 -11
- package/skill-pack/maintained/outerlayer-evidence/SKILL.md +6 -6
- package/skill-pack/maintained/outerlayer-evidence/references/demo.md +12 -11
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { placeholderQueues, placeholderProblem } from './chunk-
|
|
4
|
-
import { checkFit, RUNNER_RESERVE_BYTES } from './chunk-
|
|
5
|
-
import { builtinKind, imageBuildOf, keepsHostBuilder } from './chunk-
|
|
6
|
-
import { realBuildDiskProbe, checkDiskFit, DEFAULT_CACHE_DISK, DEFAULT_BUILD_DISK } from './chunk-
|
|
3
|
+
import { placeholderQueues, placeholderProblem } from './chunk-DFBY6LX3.js';
|
|
4
|
+
import { checkFit, RUNNER_RESERVE_BYTES } from './chunk-TLIZ7FY4.js';
|
|
5
|
+
import { builtinKind, imageBuildOf, keepsHostBuilder } from './chunk-Q3L5AC75.js';
|
|
6
|
+
import { realBuildDiskProbe, checkDiskFit, DEFAULT_CACHE_DISK, DEFAULT_BUILD_DISK } from './chunk-6NXBXWOP.js';
|
|
7
7
|
import { builderDiskPinned } from './chunk-4UPET3R7.js';
|
|
8
8
|
import { BUILD_SLICE_MEMORY_ENV, FORWARDED_CLAUDE_CREDENTIAL_VARIABLES, claudeCredentialVariablesSet, claudeCredential, claudeEnvPath, parseRunnerEnv } from './chunk-SDAEXUIX.js';
|
|
9
9
|
import { closeSync, openSync, constants, readFileSync } from 'fs';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { gatherDoctorChecks, doctorExitCode, summarizeChecks, renderDoctorText, recordWrapped, recordUnwrapped, recordRemoval, readManifest, recordInstall, recordStatusline } from './chunk-
|
|
3
|
+
import { gatherDoctorChecks, doctorExitCode, summarizeChecks, renderDoctorText, recordWrapped, recordUnwrapped, recordRemoval, readManifest, recordInstall, recordStatusline } from './chunk-T6HSNQAT.js';
|
|
4
4
|
import './chunk-TZMDRHWB.js';
|
|
5
5
|
import './chunk-KT4CN6OU.js';
|
|
6
6
|
import './chunk-J7EJMIDR.js';
|
|
@@ -3926,13 +3926,13 @@ what CLIs older than ${FIRST_VERSION_READING_AGENTS_SKILLS} do. \`` + cliInvocat
|
|
|
3926
3926
|
if (changed.length > 0 && !opts.json) process.stdout.write(`Removed the claude function from ${changed.join(", ")}.
|
|
3927
3927
|
`);
|
|
3928
3928
|
}
|
|
3929
|
-
const shell = !opts.remove && opts.shellFunction !== void 0 ? (await import('./init-cmd-
|
|
3929
|
+
const shell = !opts.remove && opts.shellFunction !== void 0 ? (await import('./init-cmd-MQ5R35O2.js')).applyShellFunctionFlag(opts.shellFunction, { home: homeFromEnv(), shellPath: process.env.SHELL }) : void 0;
|
|
3930
3930
|
if (opts.json) writeJson(shell === void 0 ? outcome.result : { ...outcome.result, shellFunction: { outcome: shell.outcome, reason: shell.reason } });
|
|
3931
3931
|
else process.stdout.write(outcome.text + skillsLine + (shell?.text ?? ""));
|
|
3932
3932
|
return;
|
|
3933
3933
|
}
|
|
3934
3934
|
await installMachineSkillsForSetup();
|
|
3935
|
-
const { runInitCommand } = await import('./init-cmd-
|
|
3935
|
+
const { runInitCommand } = await import('./init-cmd-MQ5R35O2.js');
|
|
3936
3936
|
const code = await runInitCommand(
|
|
3937
3937
|
{ json: opts.json, factory: opts.factory, shellFunction: opts.shellFunction },
|
|
3938
3938
|
{
|
|
@@ -4394,7 +4394,7 @@ its criterion, and the new record retires the old record. The id must be the ite
|
|
|
4394
4394
|
as \`work demo --item <n> --json\` prints it.
|
|
4395
4395
|
`
|
|
4396
4396
|
).action(async (manifest, opts) => {
|
|
4397
|
-
const { runEmitDemo, EmitDemoError } = await import('./emit-demo-cmd-
|
|
4397
|
+
const { runEmitDemo, EmitDemoError } = await import('./emit-demo-cmd-6VTA5BSJ.js');
|
|
4398
4398
|
let item;
|
|
4399
4399
|
if (opts.item !== void 0) {
|
|
4400
4400
|
item = parseTrackerNumber(opts.item);
|
|
@@ -4437,9 +4437,44 @@ as \`work demo --item <n> --json\` prints it.
|
|
|
4437
4437
|
}
|
|
4438
4438
|
});
|
|
4439
4439
|
program2.command("demo-voice", { hidden: true }).description("Speak demo lines for a recorder: JSON lines in on stdin, out on stdout").action(async () => {
|
|
4440
|
-
const { runDemoVoice } = await import('./demo-voice-cmd-
|
|
4440
|
+
const { runDemoVoice } = await import('./demo-voice-cmd-MBK3BGHZ.js');
|
|
4441
4441
|
await runDemoVoice();
|
|
4442
4442
|
});
|
|
4443
|
+
const demoCmd = program2.command("demo").description("Record demos with the recorder this CLI carries");
|
|
4444
|
+
demoCmd.command("record <file>").description("Record a demo script with the recorder and Playwright this CLI carries").option("--config <file>", "the repository's Playwright config, to reuse its setup and projects").option("--project <name>", "with --config: the one project to record in").option("--base-url <url>", "without --config: where relative page.goto() paths start").option("--output-dir <dir>", "where the video and manifest go (default: test-results/outerlayer-demo)").option("--no-voice", "time each beat by an estimate of its line; needs no voice pack").option("--json", "machine-readable JSON output").addHelpText(
|
|
4445
|
+
"after",
|
|
4446
|
+
`
|
|
4447
|
+
${cliInvocation()} demo record e2e/save-variable.demo.ts --base-url http://localhost:3000
|
|
4448
|
+
${cliInvocation()} demo record e2e/tests/save-variable.demo.ts --config e2e/playwright.config.ts --project chromium
|
|
4449
|
+
|
|
4450
|
+
The script imports test and expect from @outerlayer/playwright. This command runs it on the Playwright
|
|
4451
|
+
release this CLI depends on, and maps that import to the recorder this CLI carries, so the repository
|
|
4452
|
+
installs neither. With --config, the script must be inside that config's testDir, and the config's own
|
|
4453
|
+
imports of @playwright/test load the same Playwright. The recorder writes the video and manifest.json,
|
|
4454
|
+
and the command prints the manifest's path for \`emit demo\`. Under \`work proofs --record\`, the demo goes
|
|
4455
|
+
to OUTERLAYER_PROOF_OUT instead. Exit 1 means the demo's test failed; its manifest is written all the same.
|
|
4456
|
+
`
|
|
4457
|
+
).action(async (file, opts) => {
|
|
4458
|
+
const { runDemoRecord, DemoRecordError } = await import('./demo-record-cmd-7HJ5C7KM.js');
|
|
4459
|
+
try {
|
|
4460
|
+
const result = await runDemoRecord({
|
|
4461
|
+
file,
|
|
4462
|
+
config: opts.config,
|
|
4463
|
+
project: opts.project,
|
|
4464
|
+
baseUrl: opts.baseUrl,
|
|
4465
|
+
outputDir: opts.outputDir,
|
|
4466
|
+
voice: opts.voice,
|
|
4467
|
+
json: opts.json
|
|
4468
|
+
});
|
|
4469
|
+
if (result.exitCode !== 0) process.exitCode = result.exitCode;
|
|
4470
|
+
} catch (err) {
|
|
4471
|
+
if (err instanceof DemoRecordError) {
|
|
4472
|
+
fail(err.message);
|
|
4473
|
+
return;
|
|
4474
|
+
}
|
|
4475
|
+
throw err;
|
|
4476
|
+
}
|
|
4477
|
+
});
|
|
4443
4478
|
emitCmd.command("finding").description("Record one finding: a problem you hit in the factory").requiredOption("--id <id>", "client id \u2014 re-emitting the same id replaces it").option("--category <context|flaky-test|tooling|environment|defect|other>", "what kind of problem this is").requiredOption("--title <text>", "one sentence").requiredOption("--file <path>", "the file the problem is in, or the instruction's own path").option("--line <number>", "line number in --file").option("--rule-path <path>", "the instruction's own path \u2014 required for a context finding").option("--rule-line <number>", "line number in --rule-path").option("--rule-quote <text>", "the instruction's quoted sentence \u2014 required unless --rule-relation is missing").option("--rule-relation <wrong|broken|missing>", "how the instruction fails \u2014 required for a context finding").requiredOption("--where <label>", 'where this was recorded, e.g. "build session"').option("--detail <text>", "what happened, a few paragraphs").option("--cause <text>", 'what is actually wrong, or "unknown"').option("--suggestion <text>", "what would help").option("--command <text>", "the command that misbehaved").option("--error <text>", "the first error line").option("--test <name>", "the test name, for a flaky test").option("--symbol <name>", "the function the problem is in, for a defect").option("--started-at <event>", "event id where you hit the problem (default: first output showing --error)").option("--ended-at <event>", "event id where you got past it (default: the newest event)").option("--untimed", "record no time, only when the problem cost none in this session").option("--find <text>", "list this session's events that contain the text, and record nothing").option("--problem <id>", "a problem this finding reports; repeat for each one (needs --link-reason)", (value, previous = []) => [...previous, value]).option("--link-reason <text>", "why the finding reports each --problem").option("--new", "record a new problem instead of linking an existing one").option("--trace-id <id>", "the session's trace id, when there is one").option("--turn <number>", "turn index within the session").option("--round <number>", "round number, when there is one").addOption(new Option("--subject <value>").hideHelp()).addOption(new Option("--kind <value>").hideHelp()).addOption(new Option("--severity <value>").hideHelp()).addOption(new Option("--verdict <value>").hideHelp()).addOption(new Option("--fixed").hideHelp()).addOption(new Option("--source <value>").hideHelp()).option("--head-sha <sha>", "the commit this batch was recorded against").option("--context-source-sha <sha>", "the context-source commit this batch was recorded against").option("--item <number>", "work item to record on directly, by its number in this factory").option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").addHelpText(
|
|
4444
4479
|
"after",
|
|
4445
4480
|
`
|
|
@@ -4964,7 +4999,7 @@ differs from HEAD.
|
|
|
4964
4999
|
fail(trackerNumberError("--pr", opts.pr));
|
|
4965
5000
|
return;
|
|
4966
5001
|
}
|
|
4967
|
-
const { runWorkProofsCommand } = await import('./work-proofs-cmd-
|
|
5002
|
+
const { runWorkProofsCommand } = await import('./work-proofs-cmd-56EY7O45.js');
|
|
4968
5003
|
await runWorkProofsCommand({ ...opts, ...pr === void 0 ? {} : { pr } });
|
|
4969
5004
|
});
|
|
4970
5005
|
workCmd.command("list").description("List live work items for this factory").option("--stage <spec|build|review>", "filter by stage").option("--section <attention|waiting|flowing>", "filter by Queue section").option("--repo <owner/name>", "repository (default: the current checkout's remote)").option("--unclaimed", "only items with no live lease").option("--claimed", "only items with a live lease, held by a host or a local session").option("--startable", "only items a host can start: a build request, no open PR, no live lease").option("--needs <amend>", "only items with a thread waiting on an agent").option("--json", "machine-readable JSON output").option("--url <url>", "cloud base URL (or OUTERLAYER_URL / config)").addOption(apiKeyOption()).option("--app-id <id>", "factory id the key is bound to (or OUTERLAYER_APP_ID / config)").action(async (opts) => {
|
|
@@ -4989,7 +5024,7 @@ by a different key is refused; claiming again with the same key extends
|
|
|
4989
5024
|
it. --host is a label only.
|
|
4990
5025
|
`
|
|
4991
5026
|
).action(async (opts) => {
|
|
4992
|
-
const { runWorkClaim, WorkCommandError } = await import('./work-claim-cmd-
|
|
5027
|
+
const { runWorkClaim, WorkCommandError } = await import('./work-claim-cmd-QPYCZUMI.js');
|
|
4993
5028
|
try {
|
|
4994
5029
|
await runWorkClaim(opts);
|
|
4995
5030
|
} catch (err) {
|
|
@@ -5009,7 +5044,7 @@ Extends the live lease this API key holds. Refused with a 410 if the
|
|
|
5009
5044
|
lease has expired, or a 403 if a different key holds it.
|
|
5010
5045
|
`
|
|
5011
5046
|
).action(async (opts) => {
|
|
5012
|
-
const { runWorkRenew, WorkCommandError } = await import('./work-claim-cmd-
|
|
5047
|
+
const { runWorkRenew, WorkCommandError } = await import('./work-claim-cmd-QPYCZUMI.js');
|
|
5013
5048
|
try {
|
|
5014
5049
|
await runWorkRenew(opts);
|
|
5015
5050
|
} catch (err) {
|
|
@@ -5041,7 +5076,7 @@ applies to a host's lease only. A later tool call in the session
|
|
|
5041
5076
|
takes the lease again.
|
|
5042
5077
|
`
|
|
5043
5078
|
).action(async (opts) => {
|
|
5044
|
-
const { runWorkRelease, WorkCommandError } = await import('./work-claim-cmd-
|
|
5079
|
+
const { runWorkRelease, WorkCommandError } = await import('./work-claim-cmd-QPYCZUMI.js');
|
|
5045
5080
|
try {
|
|
5046
5081
|
await runWorkRelease(opts);
|
|
5047
5082
|
} catch (err) {
|
|
@@ -5110,8 +5145,8 @@ function registerRunnerCommands(program2) {
|
|
|
5110
5145
|
const runnerCmd = program2.command("runner").description("Take work from the implement and amend queues on this machine");
|
|
5111
5146
|
const configOption = "the cloud config file to run against (default: ~/.outerlayer/config.json)";
|
|
5112
5147
|
runnerCmd.command("start").description("Run the loop: claim work, run it, report, clean up, repeat").option("--config <path>", configOption).action(async (opts) => {
|
|
5113
|
-
const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-
|
|
5114
|
-
const { start, RunnerStartError } = await import('./loop-
|
|
5148
|
+
const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-4K6OG2SZ.js');
|
|
5149
|
+
const { start, RunnerStartError } = await import('./loop-NNNDBFAS.js');
|
|
5115
5150
|
const { RunnerAlreadyRunningError } = await import('./pidfile-PCG2H5T4.js');
|
|
5116
5151
|
const configPath = opts.config ?? defaultRunnerConfigPath();
|
|
5117
5152
|
try {
|
|
@@ -5129,9 +5164,9 @@ function registerRunnerCommands(program2) {
|
|
|
5129
5164
|
"after",
|
|
5130
5165
|
"\nReads OUTERLAYER_URL, OUTERLAYER_APP_ID, OUTERLAYER_API_KEY, OUTERLAYER_RUNNER_NAME and one Claude credential\n(CLAUDE_CODE_OAUTH_TOKEN or ANTHROPIC_API_KEY) from the environment. OUTERLAYER_AGENT\nis optional and defaults to claude. On a later start it refuses variables that disagree with the config in the volume.\nThe image sets OUTERLAYER_RUNNER_IMAGE; outside the image, use `runner start`.\n"
|
|
5131
5166
|
).action(async () => {
|
|
5132
|
-
const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-
|
|
5133
|
-
const { containerStart } = await import('./container-start-
|
|
5134
|
-
const { start, RunnerStartError } = await import('./loop-
|
|
5167
|
+
const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-4K6OG2SZ.js');
|
|
5168
|
+
const { containerStart } = await import('./container-start-R74IO7CI.js');
|
|
5169
|
+
const { start, RunnerStartError } = await import('./loop-NNNDBFAS.js');
|
|
5135
5170
|
const { RunnerAlreadyRunningError } = await import('./pidfile-PCG2H5T4.js');
|
|
5136
5171
|
try {
|
|
5137
5172
|
const result = await containerStart({
|
|
@@ -5153,16 +5188,16 @@ function registerRunnerCommands(program2) {
|
|
|
5153
5188
|
"after",
|
|
5154
5189
|
"\nIn the runner image, run it with `docker exec <container> outerlayer runner update-steps`. It reads the\ncontainer with `docker inspect` and changes nothing. The steps rename the old container and never remove it\nbefore the new one runs. They name the container's variables and never print a value.\n"
|
|
5155
5190
|
).action(async (opts) => {
|
|
5156
|
-
const { defaultRunnerConfigPath } = await import('./config-
|
|
5191
|
+
const { defaultRunnerConfigPath } = await import('./config-4K6OG2SZ.js');
|
|
5157
5192
|
const { runnerDir } = await import('./paths-AQ47ZRHK.js');
|
|
5158
|
-
const { runUpdateSteps } = await import('./update-steps-
|
|
5193
|
+
const { runUpdateSteps } = await import('./update-steps-ZTNIK7LA.js');
|
|
5159
5194
|
const text = await runUpdateSteps({ runnerDirPath: runnerDir(opts.config ?? defaultRunnerConfigPath()) });
|
|
5160
5195
|
process.stdout.write(`${text}
|
|
5161
5196
|
`);
|
|
5162
5197
|
});
|
|
5163
5198
|
runnerCmd.command("check").description("Validate the config, the hooks and the key, and print the effective settings").option("--config <path>", configOption).action(async (opts) => {
|
|
5164
|
-
const { defaultRunnerConfigPath } = await import('./config-
|
|
5165
|
-
const { runRunnerCheck } = await import('./check-
|
|
5199
|
+
const { defaultRunnerConfigPath } = await import('./config-4K6OG2SZ.js');
|
|
5200
|
+
const { runRunnerCheck } = await import('./check-V66LZDNK.js');
|
|
5166
5201
|
const configPath = opts.config ?? defaultRunnerConfigPath();
|
|
5167
5202
|
const result = await runRunnerCheck(configPath);
|
|
5168
5203
|
if (!result.ok) {
|
|
@@ -5183,7 +5218,7 @@ function registerRunnerCommands(program2) {
|
|
|
5183
5218
|
`);
|
|
5184
5219
|
});
|
|
5185
5220
|
runnerCmd.command("install").description("Put this CLI in the runner's install layout; --service adds its service").option("--config <path>", configOption).option("--service", "set up the service that keeps the runner running").option("--print", "with --service, print the unit and set up nothing").option("--user <account>", "with --service, the account the service runs as").option("--replace", "replace a unit or launcher file this command did not write").option("--allow-downgrade", "install this CLI even when it is older than the version the runner runs").option("--unit-name <name>", "with --service, the unit's name, to run a second runner beside the first").option("--build-memory-max <size>", "with --service, memory all builds may use together, such as 16g").option("--build-cpus-max <n>", "with --service, CPUs all builds may use together, such as 4").action(async (opts) => {
|
|
5186
|
-
const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-
|
|
5221
|
+
const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-4K6OG2SZ.js');
|
|
5187
5222
|
const { runRunnerInstall, RunnerInstallError, launcherSummary, restartNote } = await import('./install-cmd-RGO7NWKP.js');
|
|
5188
5223
|
const configPath = opts.config ?? defaultRunnerConfigPath();
|
|
5189
5224
|
if (opts.service !== true) {
|
|
@@ -5196,13 +5231,13 @@ function registerRunnerCommands(program2) {
|
|
|
5196
5231
|
}
|
|
5197
5232
|
}
|
|
5198
5233
|
const buildCpusMax = opts.buildCpusMax === void 0 ? void 0 : Number(opts.buildCpusMax);
|
|
5199
|
-
if (buildCpusMax !== void 0 && !(await import('./command-
|
|
5234
|
+
if (buildCpusMax !== void 0 && !(await import('./command-TONUMZ2A.js')).cpusAreValid(buildCpusMax)) {
|
|
5200
5235
|
fail(`--build-cpus-max ${opts.buildCpusMax} is not a number of CPUs from 0.01 to 1024.`);
|
|
5201
5236
|
return;
|
|
5202
5237
|
}
|
|
5203
5238
|
try {
|
|
5204
5239
|
if (opts.service === true) {
|
|
5205
|
-
const { installServiceCommand } = await import('./command-
|
|
5240
|
+
const { installServiceCommand } = await import('./command-TONUMZ2A.js');
|
|
5206
5241
|
const result2 = await installServiceCommand({
|
|
5207
5242
|
configPath,
|
|
5208
5243
|
print: opts.print,
|
|
@@ -5259,8 +5294,8 @@ To keep it running, run ${C.yellow}${cliInvocation()} runner install --service${
|
|
|
5259
5294
|
fail(`pass --service: \`${cliInvocation()} runner uninstall --service\` removes the runner's service.`);
|
|
5260
5295
|
return;
|
|
5261
5296
|
}
|
|
5262
|
-
const { defaultRunnerConfigPath } = await import('./config-
|
|
5263
|
-
const { uninstallServiceCommand } = await import('./command-
|
|
5297
|
+
const { defaultRunnerConfigPath } = await import('./config-4K6OG2SZ.js');
|
|
5298
|
+
const { uninstallServiceCommand } = await import('./command-TONUMZ2A.js');
|
|
5264
5299
|
const result = await uninstallServiceCommand({ configPath: opts.config ?? defaultRunnerConfigPath(), unitName: opts.unitName, home: homeFromEnv() });
|
|
5265
5300
|
if (result.ok) for (const line of result.lines) process.stdout.write(`${C.green}\u2713${C.reset} ${line}
|
|
5266
5301
|
`);
|
|
@@ -5287,12 +5322,12 @@ already in claude.env is used.
|
|
|
5287
5322
|
printf '%s' "$CLAUDE_CODE_OAUTH_TOKEN" | ${cliInvocation()} runner init --agent claude --factory <org>/<factory>
|
|
5288
5323
|
`
|
|
5289
5324
|
).action(async (opts) => {
|
|
5290
|
-
const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-
|
|
5291
|
-
const { prepareRunnerInit, runRunnerInit, RunnerInitError, writeRunnerInit } = await import('./init-
|
|
5292
|
-
const { obtainRunnerKey, runnerKeyLogin } = await import('./runner-key-
|
|
5293
|
-
const { detectMachine } = await import('./machine-
|
|
5294
|
-
const { chooseVm, runVmInit, VmInitError } = await import('./init-
|
|
5295
|
-
const { AGENT_COMMANDS, credentialFromStdin, isAgentName, restartForCredential, RunnerEnvError } = await import('./runner-env-
|
|
5325
|
+
const { defaultRunnerConfigPath, RunnerConfigError } = await import('./config-4K6OG2SZ.js');
|
|
5326
|
+
const { prepareRunnerInit, runRunnerInit, RunnerInitError, writeRunnerInit } = await import('./init-3MO5WCU3.js');
|
|
5327
|
+
const { obtainRunnerKey, runnerKeyLogin } = await import('./runner-key-ASPZ7TQH.js');
|
|
5328
|
+
const { detectMachine } = await import('./machine-GCW2GGI2.js');
|
|
5329
|
+
const { chooseVm, runVmInit, VmInitError } = await import('./init-TDLUTI6F.js');
|
|
5330
|
+
const { AGENT_COMMANDS, credentialFromStdin, isAgentName, restartForCredential, RunnerEnvError } = await import('./runner-env-LVVLUHY2.js');
|
|
5296
5331
|
const configPath = opts.config ?? defaultRunnerConfigPath();
|
|
5297
5332
|
if (opts.agent !== void 0 && !isAgentName(opts.agent)) {
|
|
5298
5333
|
fail(`--agent ${opts.agent}: runner init writes commands for ${Object.keys(AGENT_COMMANDS).join(", ")}. For another agent, leave --agent out and edit runner.commands.`);
|
|
@@ -5442,7 +5477,7 @@ ${C.yellow}The runner will not update itself: ${installErr.message}${C.reset}
|
|
|
5442
5477
|
let serviceUp = false;
|
|
5443
5478
|
let restart;
|
|
5444
5479
|
if (installedLayout) {
|
|
5445
|
-
const { installServiceCommand } = await import('./command-
|
|
5480
|
+
const { installServiceCommand } = await import('./command-TONUMZ2A.js');
|
|
5446
5481
|
const service = await installServiceCommand({
|
|
5447
5482
|
configPath,
|
|
5448
5483
|
entryPath: process.argv[1] ?? "",
|
|
@@ -5486,12 +5521,12 @@ Next:
|
|
|
5486
5521
|
"after",
|
|
5487
5522
|
"\nA repository governed by a control plane builds the control plane's image, at the commit\nthe gateway has stored for it. A repository that governs itself fetches the head of its\ndefault branch into the runner's cache. Either way it reads .devcontainer/devcontainer.json\nand builds the image with the devcontainer CLI. Settings\nthat reach the host or widen the container's privileges are ignored and listed. The\nimage holds this CLI and a pinned Claude Code. Nothing runs inside the image.\n"
|
|
5488
5523
|
).action(async (opts) => {
|
|
5489
|
-
const { defaultRunnerConfigPath } = await import('./config-
|
|
5490
|
-
const { buildRepositoryImage, RecipeError } = await import('./build-
|
|
5524
|
+
const { defaultRunnerConfigPath } = await import('./config-4K6OG2SZ.js');
|
|
5525
|
+
const { buildRepositoryImage, RecipeError } = await import('./build-M4UYZAFH.js');
|
|
5491
5526
|
const { currentCliBuild } = await import('./cli-build-K56DK4DS.js');
|
|
5492
|
-
const { createDockerHost } = await import('./docker-
|
|
5493
|
-
const { builderSpec } = await import('./builder-
|
|
5494
|
-
const { loadRunnerConfig } = await import('./config-
|
|
5527
|
+
const { createDockerHost } = await import('./docker-XWQM4F7B.js');
|
|
5528
|
+
const { builderSpec } = await import('./builder-IORYS76D.js');
|
|
5529
|
+
const { loadRunnerConfig } = await import('./config-4K6OG2SZ.js');
|
|
5495
5530
|
const configPath = opts.config ?? defaultRunnerConfigPath();
|
|
5496
5531
|
const loaded = (() => {
|
|
5497
5532
|
try {
|
|
@@ -5502,7 +5537,7 @@ Next:
|
|
|
5502
5537
|
})();
|
|
5503
5538
|
const memory = loaded?.build?.memory ?? "8g";
|
|
5504
5539
|
try {
|
|
5505
|
-
const { ensureRunnerIdentity } = await import('./runner-identity-
|
|
5540
|
+
const { ensureRunnerIdentity } = await import('./runner-identity-73F2IWBT.js');
|
|
5506
5541
|
await ensureRunnerIdentity(configPath, { log: (line) => console.error(line) }).catch((err) => {
|
|
5507
5542
|
console.error(`the runner's Docker identity could not be stored: ${err instanceof Error ? err.message : String(err)}`);
|
|
5508
5543
|
});
|
|
@@ -5569,17 +5604,17 @@ Next:
|
|
|
5569
5604
|
}
|
|
5570
5605
|
});
|
|
5571
5606
|
runnerCmd.command("stop").description("Take no more work; finish running jobs, then exit").option("--config <path>", "the cloud config file naming the runner to stop").option("--now", "end running jobs immediately, with outcome stopped").action(async (opts) => {
|
|
5572
|
-
const { defaultRunnerConfigPath } = await import('./config-
|
|
5573
|
-
const { requestStop } = await import('./loop-
|
|
5607
|
+
const { defaultRunnerConfigPath } = await import('./config-4K6OG2SZ.js');
|
|
5608
|
+
const { requestStop } = await import('./loop-NNNDBFAS.js');
|
|
5574
5609
|
const configPath = opts.config ?? defaultRunnerConfigPath();
|
|
5575
5610
|
const { runnerImageVersion } = await import('./image-tag-BTXKIH73.js');
|
|
5576
5611
|
await requestStop(configPath, Boolean(opts.now), void 0, { image: runnerImageVersion() !== void 0 });
|
|
5577
5612
|
});
|
|
5578
5613
|
runnerCmd.command("status").description("List running jobs; with --recent, finished ones too").option("--config <path>", "the cloud config file naming the runner to inspect").option("--recent", "also list finished jobs, newest first, capped at 20").option("--json", "machine-readable JSON output").action(async (opts) => {
|
|
5579
|
-
const { defaultRunnerConfigPath, loadRunnerConfig } = await import('./config-
|
|
5614
|
+
const { defaultRunnerConfigPath, loadRunnerConfig } = await import('./config-4K6OG2SZ.js');
|
|
5580
5615
|
const { jobsDir, runnerDir } = await import('./paths-AQ47ZRHK.js');
|
|
5581
|
-
const { listJobFiles, runnerProcessState } = await import('./loop-
|
|
5582
|
-
const { renderStatus } = await import('./status-
|
|
5616
|
+
const { listJobFiles, runnerProcessState } = await import('./loop-NNNDBFAS.js');
|
|
5617
|
+
const { renderStatus } = await import('./status-35Z3TW42.js');
|
|
5583
5618
|
const { readHousekeepingRecord } = await import('./record-SVCNFCGQ.js');
|
|
5584
5619
|
const path2 = await import('path');
|
|
5585
5620
|
const configPath = opts.config ?? defaultRunnerConfigPath();
|
|
@@ -5600,7 +5635,7 @@ Next:
|
|
|
5600
5635
|
const processState = runnerProcessState(configPath);
|
|
5601
5636
|
const service = await (async () => {
|
|
5602
5637
|
if (process.platform !== "linux" || !existsSync("/run/systemd/system")) return void 0;
|
|
5603
|
-
const { inspectRunnerService } = await import('./find-unit-
|
|
5638
|
+
const { inspectRunnerService } = await import('./find-unit-I4GWKY4T.js');
|
|
5604
5639
|
const facts = inspectRunnerService(configPath);
|
|
5605
5640
|
return facts === void 0 ? void 0 : { unit: facts.unit, running: facts.mainPid !== void 0, delegated: facts.delegate };
|
|
5606
5641
|
})();
|
|
@@ -5637,8 +5672,8 @@ Next:
|
|
|
5637
5672
|
);
|
|
5638
5673
|
});
|
|
5639
5674
|
runnerCmd.command("logs").argument("<item>", "the work item's number in the factory").description("Print the newest attempt's log for one item").option("--config <path>", "the cloud config file naming the runner to inspect").option("-f, --follow", "keep printing as the log grows").action(async (itemArg, opts) => {
|
|
5640
|
-
const { defaultRunnerConfigPath } = await import('./config-
|
|
5641
|
-
const { listJobFiles } = await import('./loop-
|
|
5675
|
+
const { defaultRunnerConfigPath } = await import('./config-4K6OG2SZ.js');
|
|
5676
|
+
const { listJobFiles } = await import('./loop-NNNDBFAS.js');
|
|
5642
5677
|
const { newestAttempt, logPathFor, tail, RunnerLogsError } = await import('./logs-LEVH6VAI.js');
|
|
5643
5678
|
const configPath = opts.config ?? defaultRunnerConfigPath();
|
|
5644
5679
|
const item = parseTrackerNumber(itemArg);
|
|
@@ -3,21 +3,22 @@ import { createRequire } from 'node:module';
|
|
|
3
3
|
import { realOwnership, accountNamed, handOver, runRunnerInstall, launcherSummary, restartNote, accountIdentity } from './chunk-RR3VDM7M.js';
|
|
4
4
|
import './chunk-MN3PP45X.js';
|
|
5
5
|
import { currentLink, execStartCommand } from './chunk-YL3RWW7X.js';
|
|
6
|
-
import { detectMachine, helperSocketPath, ensureFirecrackerAndJailer } from './chunk-
|
|
6
|
+
import { detectMachine, helperSocketPath, ensureFirecrackerAndJailer } from './chunk-DFBY6LX3.js';
|
|
7
7
|
import './chunk-2PGI6RDE.js';
|
|
8
|
-
import './chunk-
|
|
8
|
+
import './chunk-XDJ376OP.js';
|
|
9
9
|
import './chunk-OGFGZQA3.js';
|
|
10
10
|
import './chunk-3VZTNXK5.js';
|
|
11
11
|
import './chunk-6KFJIU73.js';
|
|
12
12
|
import './chunk-77VBS2RT.js';
|
|
13
13
|
import './chunk-SDELQEG4.js';
|
|
14
14
|
import './chunk-TQMI335S.js';
|
|
15
|
-
import './chunk-
|
|
16
|
-
import { unitNameProblem, DEFAULT_UNIT_NAME, checkFit, installService, uninstallService, realTaskScheduler, UNIT_MARKER } from './chunk-
|
|
17
|
-
import { runnerVmOf, loadRunnerConfig, builtinKind } from './chunk-
|
|
18
|
-
import './chunk-
|
|
19
|
-
import { parseSize, readJobFile } from './chunk-
|
|
15
|
+
import './chunk-63A6NUEZ.js';
|
|
16
|
+
import { unitNameProblem, DEFAULT_UNIT_NAME, checkFit, installService, uninstallService, realTaskScheduler, UNIT_MARKER } from './chunk-TLIZ7FY4.js';
|
|
17
|
+
import { runnerVmOf, loadRunnerConfig, builtinKind } from './chunk-Q3L5AC75.js';
|
|
18
|
+
import './chunk-6NXBXWOP.js';
|
|
19
|
+
import { parseSize, readJobFile } from './chunk-KOZ6IBEI.js';
|
|
20
20
|
import { HOST_HELPER_ASSETS_VERSION, builderDiskPinned, hostHelperSupportsSlice, HOST_HELPER_SLICE_SINCE, firecrackerArch, MICROVM_ARCHES, FIRECRACKER_VERSION, FIRECRACKER_BINARY_SHA256, JAILER_BINARY_SHA256, HOST_HELPER_SHA256, HOST_HELPER_BASE_URL, hostHelperPinned } from './chunk-4UPET3R7.js';
|
|
21
|
+
import './chunk-HDLON3RJ.js';
|
|
21
22
|
import { realLima } from './chunk-77MM5RYD.js';
|
|
22
23
|
import { writeLaunchAgent, launchAgentPath } from './chunk-LF6MLJCY.js';
|
|
23
24
|
import './chunk-LQHCNXPK.js';
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
export { DEFAULT_CHECK_TIME_LIMIT_MINUTES, DEFAULT_UPDATE_MAX_WAIT_HOURS, RunnerConfigError, builtinKind, checkHooks, defaultRunnerConfigPath, hasRunnerBlock, imageBuildOf, isBuiltinContainer, isBuiltinProcess, isBuiltinVm, keepsHostBuilder, loadRunnerConfig, resolveBuild, resolveHousekeeping, runnerCredentialProblem, runnerVmOf } from './chunk-
|
|
4
|
-
import './chunk-
|
|
5
|
-
import './chunk-
|
|
3
|
+
export { DEFAULT_CHECK_TIME_LIMIT_MINUTES, DEFAULT_UPDATE_MAX_WAIT_HOURS, RunnerConfigError, builtinKind, checkHooks, defaultRunnerConfigPath, hasRunnerBlock, imageBuildOf, isBuiltinContainer, isBuiltinProcess, isBuiltinVm, keepsHostBuilder, loadRunnerConfig, resolveBuild, resolveHousekeeping, runnerCredentialProblem, runnerVmOf } from './chunk-Q3L5AC75.js';
|
|
4
|
+
import './chunk-6NXBXWOP.js';
|
|
5
|
+
import './chunk-KOZ6IBEI.js';
|
|
6
6
|
import './chunk-4UPET3R7.js';
|
|
7
|
+
import './chunk-HDLON3RJ.js';
|
|
7
8
|
import './chunk-L5VHGRQE.js';
|
|
8
9
|
import './chunk-OOD5NDQA.js';
|
|
9
10
|
import './chunk-DINRXUQA.js';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { reportFailedStart, BUILD_MEMORY_VARIABLE } from './chunk-
|
|
4
|
-
import { readOwnContainer } from './chunk-
|
|
5
|
-
import './chunk-
|
|
6
|
-
import './chunk-ZVB57WI6.js';
|
|
3
|
+
import { reportFailedStart, BUILD_MEMORY_VARIABLE } from './chunk-F5H3LVHR.js';
|
|
4
|
+
import { readOwnContainer } from './chunk-PN7RMFPP.js';
|
|
5
|
+
import './chunk-TGBST2QL.js';
|
|
7
6
|
import './chunk-6CK2OC4Q.js';
|
|
7
|
+
import './chunk-ZVB57WI6.js';
|
|
8
8
|
import './chunk-P3NPTFLF.js';
|
|
9
9
|
import './chunk-I3LTIAOR.js';
|
|
10
10
|
import './chunk-WBTPI5MP.js';
|
|
@@ -14,21 +14,22 @@ import './chunk-ESVW4MJY.js';
|
|
|
14
14
|
import './chunk-CFFVCI2I.js';
|
|
15
15
|
import './chunk-TBT347UY.js';
|
|
16
16
|
import './chunk-TZMDRHWB.js';
|
|
17
|
-
import { detectMachine, supportsContainerBuilds, MIN_ENGINE_MAJOR, describeMachineDocker, RunnerInitError, prepareRunnerInit, writeRunnerInit } from './chunk-
|
|
17
|
+
import { detectMachine, supportsContainerBuilds, MIN_ENGINE_MAJOR, describeMachineDocker, RunnerInitError, prepareRunnerInit, writeRunnerInit } from './chunk-DFBY6LX3.js';
|
|
18
18
|
import './chunk-2PGI6RDE.js';
|
|
19
|
-
import './chunk-
|
|
19
|
+
import './chunk-XDJ376OP.js';
|
|
20
20
|
import './chunk-OGFGZQA3.js';
|
|
21
21
|
import './chunk-3VZTNXK5.js';
|
|
22
22
|
import './chunk-6KFJIU73.js';
|
|
23
23
|
import './chunk-77VBS2RT.js';
|
|
24
24
|
import { runnerImageVersion, IMAGE_VERSION_VARIABLE } from './chunk-SDELQEG4.js';
|
|
25
25
|
import './chunk-TQMI335S.js';
|
|
26
|
-
import { isAgentName, AGENT_COMMANDS } from './chunk-
|
|
27
|
-
import './chunk-
|
|
28
|
-
import './chunk-
|
|
29
|
-
import './chunk-
|
|
30
|
-
import { parseSize } from './chunk-
|
|
26
|
+
import { isAgentName, AGENT_COMMANDS } from './chunk-63A6NUEZ.js';
|
|
27
|
+
import './chunk-TLIZ7FY4.js';
|
|
28
|
+
import './chunk-Q3L5AC75.js';
|
|
29
|
+
import './chunk-6NXBXWOP.js';
|
|
30
|
+
import { parseSize } from './chunk-KOZ6IBEI.js';
|
|
31
31
|
import './chunk-4UPET3R7.js';
|
|
32
|
+
import './chunk-HDLON3RJ.js';
|
|
32
33
|
import './chunk-LQHCNXPK.js';
|
|
33
34
|
import './chunk-JBJTC3UU.js';
|
|
34
35
|
import './chunk-KT4CN6OU.js';
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { buildRootFromDist } from './chunk-HDLON3RJ.js';
|
|
4
|
+
import { C } from './chunk-ANPNT6PM.js';
|
|
5
|
+
import './chunk-CRB3POP4.js';
|
|
6
|
+
import './chunk-VNVZDWO3.js';
|
|
7
|
+
import './chunk-Z5GEFMRW.js';
|
|
8
|
+
import { spawn } from 'child_process';
|
|
9
|
+
import { randomBytes } from 'crypto';
|
|
10
|
+
import { mkdtempSync, writeFileSync, rmSync, statSync, existsSync, readFileSync, readdirSync } from 'fs';
|
|
11
|
+
import { tmpdir } from 'os';
|
|
12
|
+
import { join, resolve, dirname, relative } from 'path';
|
|
13
|
+
import { createRequire as createRequire$1 } from 'module';
|
|
14
|
+
import { fileURLToPath } from 'url';
|
|
15
|
+
|
|
16
|
+
createRequire(import.meta.url);
|
|
17
|
+
var RECORDER_IMPORT = "@outerlayer/playwright";
|
|
18
|
+
var DEMO_FOLDER = "demo";
|
|
19
|
+
var MAX_DEPTH = 6;
|
|
20
|
+
function findPlaywright(opts = {}) {
|
|
21
|
+
const buildRoot = opts.buildRoot ?? buildRootFromDist();
|
|
22
|
+
const candidates = [besideThisPackage(opts.resolve ?? createRequire$1(import.meta.url).resolve), buildRoot === void 0 ? void 0 : join(buildRoot, "node_modules", "@playwright", "test")];
|
|
23
|
+
for (const dir of candidates) {
|
|
24
|
+
if (dir === void 0 || !existsSync(join(dir, "cli.js")) || !existsSync(join(dir, "package.json"))) continue;
|
|
25
|
+
const version = JSON.parse(readFileSync(join(dir, "package.json"), "utf8")).version;
|
|
26
|
+
if (typeof version === "string") return { dir, version };
|
|
27
|
+
}
|
|
28
|
+
return void 0;
|
|
29
|
+
}
|
|
30
|
+
function besideThisPackage(resolve2) {
|
|
31
|
+
let dir;
|
|
32
|
+
try {
|
|
33
|
+
dir = dirname(resolve2("@playwright/test/package.json"));
|
|
34
|
+
} catch {
|
|
35
|
+
}
|
|
36
|
+
return dir;
|
|
37
|
+
}
|
|
38
|
+
function recorderPath(moduleDir = dirname(fileURLToPath(import.meta.url))) {
|
|
39
|
+
return join(moduleDir, "recorder.cjs");
|
|
40
|
+
}
|
|
41
|
+
function mappingTsconfig(recorder, playwright) {
|
|
42
|
+
return {
|
|
43
|
+
compilerOptions: {
|
|
44
|
+
baseUrl: dirname(recorder),
|
|
45
|
+
paths: {
|
|
46
|
+
[RECORDER_IMPORT]: [recorder],
|
|
47
|
+
"@playwright/test": [join(playwright.dir, "index.js")]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
var escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
53
|
+
function defaultConfigSource(params) {
|
|
54
|
+
const use = params.baseUrl === void 0 ? `{ browserName: "chromium" }` : `{ browserName: "chromium", baseURL: ${JSON.stringify(params.baseUrl)} }`;
|
|
55
|
+
return [
|
|
56
|
+
"module.exports = {",
|
|
57
|
+
` testDir: ${JSON.stringify(dirname(params.file))},`,
|
|
58
|
+
` testMatch: new RegExp(${JSON.stringify(`${escapeRegExp(params.file)}$`)}),`,
|
|
59
|
+
" timeout: 0,",
|
|
60
|
+
" retries: 0,",
|
|
61
|
+
" workers: 1,",
|
|
62
|
+
` use: ${use},`,
|
|
63
|
+
"};",
|
|
64
|
+
""
|
|
65
|
+
].join("\n");
|
|
66
|
+
}
|
|
67
|
+
function wrapperConfigSource(params) {
|
|
68
|
+
return [
|
|
69
|
+
"// Written by `outerlayer demo record` for one run, and removed after it.",
|
|
70
|
+
`const loaded = require(${JSON.stringify(params.config)});`,
|
|
71
|
+
"const base = loaded.default ?? loaded;",
|
|
72
|
+
`const only = (project) => ({ ...project, testDir: ${JSON.stringify(dirname(params.file))}, testMatch: new RegExp(${JSON.stringify(`${escapeRegExp(params.file)}$`)}), testIgnore: [] });`,
|
|
73
|
+
`const wanted = ${JSON.stringify(params.project ?? null)};`,
|
|
74
|
+
"let projects = base.projects;",
|
|
75
|
+
"if (Array.isArray(projects)) {",
|
|
76
|
+
" if (wanted === null && projects.length > 1) throw new Error(`this config has ${projects.length} projects: pass --project with the one to record in`);",
|
|
77
|
+
" projects = projects.map((project) => (wanted === null || project.name === wanted ? only(project) : project));",
|
|
78
|
+
"}",
|
|
79
|
+
"module.exports = Array.isArray(projects) ? { ...base, projects } : only(base);",
|
|
80
|
+
""
|
|
81
|
+
].join("\n");
|
|
82
|
+
}
|
|
83
|
+
function playwrightArgs(params) {
|
|
84
|
+
return [
|
|
85
|
+
params.cli,
|
|
86
|
+
"test",
|
|
87
|
+
"--config",
|
|
88
|
+
params.config,
|
|
89
|
+
"--tsconfig",
|
|
90
|
+
params.tsconfig,
|
|
91
|
+
"--output",
|
|
92
|
+
params.outputDir,
|
|
93
|
+
"--workers",
|
|
94
|
+
"1",
|
|
95
|
+
"--retries",
|
|
96
|
+
"0",
|
|
97
|
+
...params.project === void 0 ? [] : ["--project", params.project]
|
|
98
|
+
];
|
|
99
|
+
}
|
|
100
|
+
function findDemoManifests(roots, since) {
|
|
101
|
+
const found = /* @__PURE__ */ new Set();
|
|
102
|
+
const walk = (dir, depth) => {
|
|
103
|
+
const names = depth > MAX_DEPTH ? void 0 : entriesOf(dir);
|
|
104
|
+
if (names === void 0) return;
|
|
105
|
+
for (const name of names) {
|
|
106
|
+
const path = join(dir, name);
|
|
107
|
+
if (name !== DEMO_FOLDER) {
|
|
108
|
+
walk(path, depth + 1);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
const manifest = join(path, "manifest.json");
|
|
112
|
+
if (existsSync(manifest) && statSync(manifest).mtimeMs >= since) found.add(manifest);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
for (const root of roots) walk(root, 0);
|
|
116
|
+
return [...found].sort();
|
|
117
|
+
}
|
|
118
|
+
function entriesOf(dir) {
|
|
119
|
+
try {
|
|
120
|
+
return readdirSync(dir);
|
|
121
|
+
} catch (error) {
|
|
122
|
+
const code = error.code;
|
|
123
|
+
if (code === "ENOENT" || code === "ENOTDIR") return void 0;
|
|
124
|
+
throw error;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// src/demo-record-cmd.ts
|
|
129
|
+
var DemoRecordError = class extends Error {
|
|
130
|
+
};
|
|
131
|
+
var DEFAULT_OUTPUT_DIR = join("test-results", "outerlayer-demo");
|
|
132
|
+
var MTIME_SLACK_MS = 2e3;
|
|
133
|
+
var isFile = (path) => {
|
|
134
|
+
try {
|
|
135
|
+
return statSync(path).isFile();
|
|
136
|
+
} catch {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
var runInherited = (command, args, opts) => new Promise((done, fail) => {
|
|
141
|
+
const child = spawn(command, args, { cwd: opts.cwd, env: opts.env, stdio: ["inherit", opts.stdout === "stderr" ? 2 : "inherit", "inherit"] });
|
|
142
|
+
child.on("error", fail);
|
|
143
|
+
child.on("exit", (code, signal) => done(code ?? (signal === null ? 1 : 128)));
|
|
144
|
+
});
|
|
145
|
+
async function runDemoRecord(opts) {
|
|
146
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
147
|
+
const env = opts.env ?? process.env;
|
|
148
|
+
const file = resolve(cwd, opts.file);
|
|
149
|
+
if (!isFile(file)) throw new DemoRecordError(`cannot find the demo script ${file}`);
|
|
150
|
+
const config = opts.config === void 0 ? void 0 : resolve(cwd, opts.config);
|
|
151
|
+
if (config !== void 0 && !isFile(config)) throw new DemoRecordError(`cannot find the Playwright config ${config}`);
|
|
152
|
+
if (opts.project !== void 0 && config === void 0) throw new DemoRecordError("--project needs --config: without one, the demo runs in a single Chromium project");
|
|
153
|
+
if (opts.baseUrl !== void 0 && config !== void 0) throw new DemoRecordError("--base-url applies only without --config: set baseURL in that config instead");
|
|
154
|
+
const playwright = (opts.findPlaywright ?? findPlaywright)();
|
|
155
|
+
if (playwright === void 0) {
|
|
156
|
+
throw new DemoRecordError("this CLI has no Playwright beside it. Install the CLI with npm install --global @outerlayer/cli, not through npx.");
|
|
157
|
+
}
|
|
158
|
+
const recorder = opts.recorder ?? recorderPath();
|
|
159
|
+
if (!isFile(recorder)) throw new DemoRecordError(`this CLI has no recorder at ${recorder}. Build the CLI again.`);
|
|
160
|
+
const outputDir = resolve(cwd, opts.outputDir ?? DEFAULT_OUTPUT_DIR);
|
|
161
|
+
const work = mkdtempSync(join(tmpdir(), "outerlayer-demo-record-"));
|
|
162
|
+
const own = config === void 0 ? void 0 : { config, wrapper: join(dirname(config), `.outerlayer-demo-${process.pid}-${randomBytes(4).toString("hex")}.config.cjs`) };
|
|
163
|
+
try {
|
|
164
|
+
const tsconfig = join(work, "tsconfig.json");
|
|
165
|
+
writeFileSync(tsconfig, `${JSON.stringify(mappingTsconfig(recorder, playwright), null, 2)}
|
|
166
|
+
`);
|
|
167
|
+
let configPath;
|
|
168
|
+
if (own === void 0) {
|
|
169
|
+
configPath = join(work, "playwright.config.cjs");
|
|
170
|
+
writeFileSync(configPath, defaultConfigSource({ file, baseUrl: opts.baseUrl }));
|
|
171
|
+
} else {
|
|
172
|
+
configPath = own.wrapper;
|
|
173
|
+
writeFileSync(configPath, wrapperConfigSource({ config: own.config, file, project: opts.project }));
|
|
174
|
+
}
|
|
175
|
+
const args = playwrightArgs({ cli: join(playwright.dir, "cli.js"), config: configPath, tsconfig, outputDir, project: opts.project });
|
|
176
|
+
const started = (opts.now ?? Date.now)();
|
|
177
|
+
const { OUTERLAYER_CLI: _ignored, ...rest } = env;
|
|
178
|
+
const runEnv = opts.voice === false ? rest : { ...rest, OUTERLAYER_CLI: opts.cliEntry ?? process.argv[1] };
|
|
179
|
+
const exitCode = await (opts.run ?? runInherited)(process.execPath, args, { cwd, env: runEnv, stdout: opts.json === true ? "stderr" : "inherit" });
|
|
180
|
+
const proofOut = env.OUTERLAYER_PROOF_OUT;
|
|
181
|
+
const manifests = findDemoManifests(proofOut === void 0 ? [outputDir] : [outputDir, proofOut], started - MTIME_SLACK_MS);
|
|
182
|
+
if (manifests.length === 0) {
|
|
183
|
+
throw new DemoRecordError(
|
|
184
|
+
exitCode === 0 ? `the run wrote no demo. A demo script imports test from ${RECORDER_IMPORT} and tells at least one demo.chapter().` : `Playwright exited with ${exitCode} before the demo wrote its manifest. Its output above says why.`
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
const output = opts.json === true ? JSON.stringify({ exitCode, manifests, playwright: playwright.version }) : humanOutput(manifests, exitCode, cwd);
|
|
188
|
+
if (opts.quiet !== true) process.stdout.write(`${output}
|
|
189
|
+
`);
|
|
190
|
+
return { exitCode, manifests, output };
|
|
191
|
+
} finally {
|
|
192
|
+
rmSync(work, { recursive: true });
|
|
193
|
+
if (own !== void 0) rmSync(own.wrapper, { force: true });
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function humanOutput(manifests, exitCode, cwd) {
|
|
197
|
+
const shown = manifests.map((manifest) => {
|
|
198
|
+
const rel = relative(cwd, manifest);
|
|
199
|
+
return rel.startsWith("..") ? manifest : rel;
|
|
200
|
+
});
|
|
201
|
+
return [
|
|
202
|
+
...shown.map((path) => `${C.green}\u2713${C.reset} recorded ${path}`),
|
|
203
|
+
...exitCode === 0 ? [] : [`${C.yellow}!${C.reset} the demo's test failed with exit ${exitCode}; Playwright's output above says why`],
|
|
204
|
+
`Next: outerlayer emit demo ${shown[0]} --output demo.webm`
|
|
205
|
+
].join("\n");
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export { DEFAULT_OUTPUT_DIR, DemoRecordError, runDemoRecord };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { realSpeaker } from './chunk-
|
|
3
|
+
import { realSpeaker } from './chunk-MIRCFK4X.js';
|
|
4
4
|
import './chunk-ER6KQCVJ.js';
|
|
5
5
|
import './chunk-QWXBWOVV.js';
|
|
6
6
|
import './chunk-QRJIBTNQ.js';
|
|
@@ -8,7 +8,6 @@ import './chunk-7DK2FOZ4.js';
|
|
|
8
8
|
import './chunk-ESVW4MJY.js';
|
|
9
9
|
import './chunk-TBT347UY.js';
|
|
10
10
|
import './chunk-2PGI6RDE.js';
|
|
11
|
-
import './chunk-TQMI335S.js';
|
|
12
11
|
import './chunk-4UPET3R7.js';
|
|
13
12
|
import './chunk-IP7BIBXJ.js';
|
|
14
13
|
import './chunk-OKGHWCSK.js';
|