@outerlayer/cli 0.7.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +5 -5
  3. package/dist/{agent-setup-TXLDY5RV.js → agent-setup-K6RD2Z4P.js} +4 -4
  4. package/dist/{build-JF5UOWKJ.js → build-MS34XEGN.js} +2 -1
  5. package/dist/build-info.json +1 -1
  6. package/dist/builder-IG6FNA54.js +13 -0
  7. package/dist/{check-ASZL5BEO.js → check-GX5ND6RO.js} +26 -22
  8. package/dist/chunk-2BRSMBBB.js +264 -0
  9. package/dist/{chunk-PUN7LMNS.js → chunk-4ACZCY4I.js} +2 -2
  10. package/dist/{chunk-2VO25HHO.js → chunk-4FPWKV7L.js} +3 -3
  11. package/dist/{chunk-AII7CKTH.js → chunk-5ODHQP6O.js} +68 -145
  12. package/dist/chunk-7RQ73DLO.js +23 -0
  13. package/dist/{chunk-7FTNIAHS.js → chunk-AX23QKHS.js} +7 -3
  14. package/dist/{chunk-6ZZHWY2Z.js → chunk-BF4KKEFY.js} +4 -4
  15. package/dist/{chunk-5FWNEQNZ.js → chunk-BQFNZOMQ.js} +1 -1
  16. package/dist/chunk-CX22S5BA.js +45 -0
  17. package/dist/{chunk-D6FXM5OW.js → chunk-GAYWY4GI.js} +8 -8
  18. package/dist/{chunk-MQPRB5K7.js → chunk-HSN5QNS5.js} +8 -8
  19. package/dist/chunk-I2UOAV7X.js +133 -0
  20. package/dist/chunk-I7CJIRMM.js +93 -0
  21. package/dist/{chunk-SSU747O6.js → chunk-ILEA3YHM.js} +1 -1
  22. package/dist/{chunk-OUUINEYB.js → chunk-JKIWMRFH.js} +1 -1
  23. package/dist/{chunk-JPR2WHHF.js → chunk-KSLNQOOS.js} +1 -1
  24. package/dist/{chunk-DGAIVMMN.js → chunk-KV47VQJZ.js} +5 -5
  25. package/dist/{chunk-E4PIFIC3.js → chunk-M4ERCYDB.js} +133 -159
  26. package/dist/chunk-PTW6W5NR.js +127 -0
  27. package/dist/{chunk-DTXOJDEH.js → chunk-PWBILI5P.js} +3 -2
  28. package/dist/{chunk-X2FSFU4C.js → chunk-PXFEYBDE.js} +3 -3
  29. package/dist/{chunk-6IYLDODX.js → chunk-Q4432IZT.js} +5 -5
  30. package/dist/{chunk-AJKEHABI.js → chunk-QB5JQH5V.js} +255 -54
  31. package/dist/{chunk-AQ54MKSQ.js → chunk-QNRSFEGY.js} +2 -2
  32. package/dist/{chunk-774HEQL6.js → chunk-TEKZRTM3.js} +91 -8
  33. package/dist/{chunk-CEBIA5FD.js → chunk-TTNFGMHO.js} +42 -50
  34. package/dist/{chunk-F6GFZXZ3.js → chunk-UXYLWVTQ.js} +1 -18
  35. package/dist/{chunk-M5POMKKW.js → chunk-V7NIVOFD.js} +5 -5
  36. package/dist/{chunk-BCLJSQCV.js → chunk-YO4PSLVB.js} +1 -1
  37. package/dist/{chunk-6QWV3YDJ.js → chunk-Z2THOHPP.js} +2 -2
  38. package/dist/{cli-LEVCGAQV.js → cli-X5ONGYNY.js} +128 -78
  39. package/dist/{command-FLSYCGIB.js → command-7NFU3IPO.js} +38 -20
  40. package/dist/{config-I3TVFYLH.js → config-Z3USDBLU.js} +3 -2
  41. package/dist/{connect-cmd-MJMUONDY.js → connect-cmd-PNZ6IJLJ.js} +2 -2
  42. package/dist/{context-adopt-CE4KDXS3.js → context-adopt-D2Z7F7PB.js} +3 -3
  43. package/dist/{context-materialize-QL33HDJN.js → context-materialize-4PMTDS6K.js} +3 -3
  44. package/dist/{dist-PXBSA7QX.js → dist-3ZTZF2TP.js} +1 -1
  45. package/dist/docker-PRHRSJM5.js +15 -0
  46. package/dist/{doctor-FVDT3KJZ.js → doctor-KALLPCRB.js} +39 -16
  47. package/dist/{emit-artifact-cmd-7RPMRSVP.js → emit-artifact-cmd-D5GMVWNC.js} +7 -7
  48. package/dist/{emit-criteria-cmd-MKI7WETO.js → emit-criteria-cmd-IE7VIM64.js} +5 -5
  49. package/dist/{emit-finding-cmd-RMLGZASB.js → emit-finding-cmd-46PTPN3A.js} +5 -5
  50. package/dist/{emit-result-cmd-MTXAZ2GV.js → emit-result-cmd-KXHHP6HX.js} +7 -7
  51. package/dist/{hook-fast-XBOZ3N6L.js → hook-fast-5H5QBJKT.js} +1 -1
  52. package/dist/{host-key-KDYZ5ECC.js → host-key-YMLXY6QB.js} +1 -1
  53. package/dist/index.js +3 -3
  54. package/dist/{init-VLW7H6RW.js → init-B4CECVOX.js} +25 -18
  55. package/dist/{init-BACXESVV.js → init-S4DH6PWW.js} +16 -13
  56. package/dist/{init-cmd-VJFB5L7X.js → init-cmd-P4MVCBCZ.js} +8 -8
  57. package/dist/{install-NMAPLLBQ.js → install-FHTVJZS6.js} +5 -4
  58. package/dist/{install-cmd-B5SEU3G7.js → install-cmd-BEC7XTNG.js} +3 -1
  59. package/dist/{loop-D3243JKT.js → loop-ODMRE3CW.js} +26 -22
  60. package/dist/{machine-EB3GEVI4.js → machine-J4SAB3Z2.js} +15 -12
  61. package/dist/{mcp-serve-cmd-N6UD2KBX.js → mcp-serve-cmd-CT47P4YQ.js} +2 -2
  62. package/dist/{session-sender-LMACEJJS.js → session-sender-V46VPWQ5.js} +6 -6
  63. package/dist/{status-F4THTJJK.js → status-QBKSH3QE.js} +19 -16
  64. package/dist/{sync-cmd-M6JA3OEE.js → sync-cmd-RJR77V4O.js} +5 -5
  65. package/dist/{watch-NB5TGPEZ.js → watch-YNZTFLEY.js} +5 -5
  66. package/dist/{work-claim-cmd-UHMWOS3G.js → work-claim-cmd-KAD3ZAH7.js} +10 -9
  67. package/dist/{work-cmd-6UMCFTAW.js → work-cmd-CNWPTH7W.js} +6 -6
  68. package/dist/{work-comment-cmd-E4LEUIXZ.js → work-comment-cmd-HH45S6UE.js} +6 -6
  69. package/dist/{work-open-pr-cmd-OPZWGSEQ.js → work-open-pr-cmd-5KR3KFCN.js} +7 -7
  70. package/dist/{work-pr-cmd-IDIAFFRU.js → work-pr-cmd-TTEGCP76.js} +6 -6
  71. package/package.json +2 -2
  72. package/skill-pack/maintained/amend/SKILL.md +22 -6
  73. package/dist/chunk-Q5G2ODUZ.js +0 -54
  74. package/dist/docker-NEGDLU6D.js +0 -7
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from 'node:module';
3
+ import { currentLink } from './chunk-TI7B7UEO.js';
4
+ import { readFileSync, statSync, chmodSync, mkdirSync, writeFileSync, renameSync, rmSync, existsSync, lstatSync, accessSync, constants, realpathSync } from 'fs';
5
+ import { randomBytes } from 'crypto';
6
+ import { join, dirname, delimiter, resolve } from 'path';
7
+
8
+ createRequire(import.meta.url);
9
+ var LAUNCHER_MARKER = "# outerlayer-runner-launcher";
10
+ var LauncherWriteError = class extends Error {
11
+ };
12
+ var PATH_LINE = 'export PATH="$HOME/.local/bin:$PATH"';
13
+ var ADD_TO_PATH = `${PATH_LINE} (in ~/.profile, ~/.bashrc or your shell's startup file; the runner never edits those)`;
14
+ function launcherPath(home) {
15
+ return join(home, ".local", "bin", "outerlayer");
16
+ }
17
+ function quoted(text) {
18
+ return `'${text.replace(/'/g, `'\\''`)}'`;
19
+ }
20
+ function launcherText(configPath, nodePath) {
21
+ const entry = join(currentLink(configPath), "node_modules", "@outerlayer", "cli", "dist", "index.js");
22
+ return [
23
+ "#!/bin/sh",
24
+ LAUNCHER_MARKER,
25
+ "# Written by `outerlayer runner install`. Runs the CLI the runner's `current` link names, so a self-update changes",
26
+ "# what this runs without changing this file.",
27
+ `exec ${quoted(nodePath)} ${quoted(entry)} "$@"`,
28
+ ""
29
+ ].join("\n");
30
+ }
31
+ function ownerOf(path) {
32
+ try {
33
+ lstatSync(path);
34
+ } catch {
35
+ return "absent";
36
+ }
37
+ try {
38
+ return readFileSync(path, "utf8").includes(LAUNCHER_MARKER) ? "ours" : "foreign";
39
+ } catch {
40
+ return "foreign";
41
+ }
42
+ }
43
+ function writeLauncher(input) {
44
+ const path = launcherPath(input.home);
45
+ const text = launcherText(input.configPath, input.nodePath);
46
+ const owner = ownerOf(path);
47
+ if (owner === "foreign" && input.replace !== true) return { path, state: "foreign" };
48
+ if (owner === "ours" && readFileSync(path, "utf8") === text) {
49
+ if ((statSync(path).mode & 493) !== 493) chmodSync(path, 493);
50
+ return { path, state: "unchanged" };
51
+ }
52
+ try {
53
+ mkdirSync(dirname(path), { recursive: true });
54
+ const temporary = `${path}.${process.pid}.${randomBytes(6).toString("hex")}.new`;
55
+ try {
56
+ writeFileSync(temporary, text, { mode: 493, flag: "wx" });
57
+ chmodSync(temporary, 493);
58
+ renameSync(temporary, path);
59
+ } catch (error) {
60
+ rmSync(temporary, { force: true });
61
+ throw error;
62
+ }
63
+ } catch (error) {
64
+ throw new LauncherWriteError(`cannot write the outerlayer command at ${path}: ${error instanceof Error ? error.message : String(error)}`);
65
+ }
66
+ return { path, state: "written" };
67
+ }
68
+ function firstOnPath(PATH) {
69
+ for (const dir of (PATH ?? "").split(delimiter)) {
70
+ if (dir === "") continue;
71
+ const candidate = join(dir, "outerlayer");
72
+ try {
73
+ if (!statSync(candidate).isFile()) continue;
74
+ accessSync(candidate, constants.X_OK);
75
+ return candidate;
76
+ } catch {
77
+ continue;
78
+ }
79
+ }
80
+ return void 0;
81
+ }
82
+ function sameFile(a, b) {
83
+ try {
84
+ return realpathSync(a) === realpathSync(b);
85
+ } catch {
86
+ return false;
87
+ }
88
+ }
89
+ function onPath(PATH, dir) {
90
+ return (PATH ?? "").split(delimiter).some((entry) => entry !== "" && resolve(entry) === resolve(dir));
91
+ }
92
+ function pathNotes(input) {
93
+ const notes = [];
94
+ if (input.state === "foreign") {
95
+ notes.push(`${input.launcher} exists and the runner did not write it, so it was left alone. Run \`outerlayer runner install --replace\` to replace it`);
96
+ return notes;
97
+ }
98
+ if (!onPath(input.PATH, dirname(input.launcher))) {
99
+ notes.push(`${dirname(input.launcher)} is not on PATH, so a shell will not find the launcher. Add it with: ${ADD_TO_PATH}`);
100
+ return notes;
101
+ }
102
+ const first = firstOnPath(input.PATH);
103
+ if (first !== void 0 && !sameFile(first, input.launcher)) {
104
+ notes.push(`${first} comes before ${input.launcher} on PATH, so a shell runs that one instead. Put the launcher's directory first with: ${ADD_TO_PATH}`);
105
+ }
106
+ return notes;
107
+ }
108
+ function launcherCheck(input) {
109
+ const name = "outerlayer on PATH";
110
+ const launcher = launcherPath(input.home);
111
+ if (!existsSync(launcher) || ownerOf(launcher) !== "ours") return void 0;
112
+ const first = firstOnPath(input.PATH);
113
+ if (first === void 0) {
114
+ return { name, status: "warn", detail: `no outerlayer is on PATH; the launcher is at ${launcher}`, fix: `add its directory to PATH: ${ADD_TO_PATH}` };
115
+ }
116
+ if (sameFile(first, launcher)) {
117
+ return { name, status: "pass", detail: `${launcher} is the first outerlayer on PATH, so it runs the version the runner runs` };
118
+ }
119
+ return {
120
+ name,
121
+ status: "warn",
122
+ detail: `${first} comes before ${launcher} on PATH, so a shell runs that one, which may not be the version the runner runs`,
123
+ fix: `remove ${first}, or put the launcher's directory first: ${ADD_TO_PATH}`
124
+ };
125
+ }
126
+
127
+ export { LauncherWriteError, launcherCheck, launcherPath, pathNotes, writeLauncher };
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { parseSize, MAX_ALLOW_HOSTS, allowHostProblem } from './chunk-F6GFZXZ3.js';
3
+ import { MAX_ALLOW_HOSTS, allowHostProblem } from './chunk-UXYLWVTQ.js';
4
+ import { parseSize } from './chunk-7RQ73DLO.js';
4
5
  import { isRefusedInConfig, resolveDestinations, isReservedVariable } from './chunk-OD2VTIHN.js';
5
6
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
6
7
  import { existsSync, statSync, accessSync, constants, readFileSync } from 'fs';
@@ -358,4 +359,4 @@ function resolveBuild(configPath, block) {
358
359
  };
359
360
  }
360
361
 
361
- export { DEFAULT_CHECK_TIME_LIMIT_MINUTES, RunnerConfigError, builtinKind, checkHooks, defaultRunnerConfigPath, hasRunnerBlock, isBuiltinContainer, isBuiltinProcess, isBuiltinVm, loadRunnerConfig, resolveBuild, runnerVmOf };
362
+ export { DEFAULT_CHECK_TIME_LIMIT_MINUTES, RunnerConfigError, builtinKind, checkHooks, defaultRunnerConfigPath, hasRunnerBlock, isBuiltinContainer, isBuiltinProcess, isBuiltinVm, loadRunnerConfig, resolveBuild, resolveHousekeeping, runnerVmOf };
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { autoConnect } from './chunk-PUN7LMNS.js';
3
+ import { autoConnect } from './chunk-4ACZCY4I.js';
4
4
  import { detectActiveSession } from './chunk-BFESLKPP.js';
5
- import { resolveRepoIdentity } from './chunk-D6FXM5OW.js';
5
+ import { resolveRepoIdentity } from './chunk-GAYWY4GI.js';
6
6
  import { parseTrackerNumber, trackerNumberError } from './chunk-WZBHBH3J.js';
7
- import { defaultFetch } from './chunk-BCLJSQCV.js';
7
+ import { defaultFetch } from './chunk-YO4PSLVB.js';
8
8
  import { unauthorizedMessage, resolveGatewayCredentials } from './chunk-BOLTI6LR.js';
9
9
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
10
10
 
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { isPlaceholderCommand } from './chunk-6QWV3YDJ.js';
4
- import { describeCallFailure } from './chunk-E4PIFIC3.js';
5
- import { WorkCommandError, getJson } from './chunk-DGAIVMMN.js';
3
+ import { isPlaceholderCommand } from './chunk-Z2THOHPP.js';
4
+ import { describeCallFailure } from './chunk-M4ERCYDB.js';
5
+ import { WorkCommandError, getJson } from './chunk-KV47VQJZ.js';
6
6
  import { sanitizeTerminal } from './chunk-ZYHKJKSU.js';
7
- import { builtinKind } from './chunk-DTXOJDEH.js';
7
+ import { builtinKind } from './chunk-PWBILI5P.js';
8
8
  import { CLAUDE_CREDENTIAL_VARIABLES, claudeCredential } from './chunk-OD2VTIHN.js';
9
- import { signerFor } from './chunk-M5POMKKW.js';
9
+ import { signerFor } from './chunk-V7NIVOFD.js';
10
10
 
11
11
  createRequire(import.meta.url);
12
12
 
@@ -1,26 +1,27 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { writeJobFile, readJobFile } from './chunk-T6OIJQRT.js';
4
- import { senderPidfile } from './chunk-2VO25HHO.js';
4
+ import { senderPidfile } from './chunk-4FPWKV7L.js';
5
5
  import { DOCKERD_LOG } from './chunk-WVGSB3Z2.js';
6
- import { installScrubContext } from './chunk-6ZZHWY2Z.js';
7
- import { AssetError, describeCallFailure, obtainImage, ensureRootfs, gitRemoteFor, startServicesFor, createBuildDisk, machineConfig, refusalCode, resolveAgentUser, AgentUserError, runBuildSteps, removeStagedContext, stageGovernedContext, shellQuote, createRunnerLog, createContainerRuntime, stopContainer, cleanupContainer, outOfMemoryReason, syncInContainer, formatDuration, retrySend, formatClock, containerSenderCommand, GH_CONFIG_YML, ghHostsYml, ADDED_USER, isLiteralAddress, signalInContainer, startCheckContainer, lifecycleSteps, lifecycleFailureReason, deleteBuildDisk, senderSignalScript } from './chunk-E4PIFIC3.js';
8
- import { CLAUDE_CODE_VERSION, readBranchHead, fetchCommit } from './chunk-CEBIA5FD.js';
6
+ import { installScrubContext } from './chunk-BF4KKEFY.js';
7
+ import { AssetError, describeCallFailure, obtainImage, ensureRootfs, gitRemoteFor, startServicesFor, createBuildDisk, machineConfig, refusalCode, resolveAgentUser, AgentUserError, runBuildSteps, removeStagedContext, stageGovernedContext, shellQuote, createRunnerLog, createContainerRuntime, stopContainer, cleanupContainer, outOfMemoryReason, formatDuration, retrySend, formatClock, containerSenderCommand, syncInContainer, GH_CONFIG_YML, ghHostsYml, ADDED_USER, isLiteralAddress, signalInContainer, deleteBuildDisk, startCheckContainer, lifecycleSteps, lifecycleFailureReason, senderSignalScript } from './chunk-M4ERCYDB.js';
8
+ import { readBranchHead, fetchCommit } from './chunk-TTNFGMHO.js';
9
9
  import { isSameProcess, startTimeOf } from './chunk-N5FOE5PS.js';
10
- import { childEnvironment } from './chunk-774HEQL6.js';
10
+ import { childEnvironment } from './chunk-TEKZRTM3.js';
11
+ import { CLAUDE_CODE_VERSION } from './chunk-CX22S5BA.js';
11
12
  import { waitForAgent, vmExecArgs } from './chunk-ZOAEPWGL.js';
12
13
  import { socketPathProblem, vsockLinks, linkVsockSockets } from './chunk-R7STSBLC.js';
13
- import { WorkCommandError, postJson, isSignatureRefusal, getJson } from './chunk-DGAIVMMN.js';
14
+ import { WorkCommandError, postJson, isSignatureRefusal, getJson } from './chunk-KV47VQJZ.js';
14
15
  import { planArtifactUpload } from './chunk-ZYHKJKSU.js';
15
- import { scrubText } from './chunk-D6FXM5OW.js';
16
- import { isBuiltinContainer, isBuiltinProcess, isBuiltinVm, DEFAULT_CHECK_TIME_LIMIT_MINUTES } from './chunk-DTXOJDEH.js';
17
- import { parseSize } from './chunk-F6GFZXZ3.js';
18
- import { claudeCredential, buildEnvironment, JOB_MOUNT, CHECKOUT_DIR, parseIsolation, proxyEnvironment, containerLocalAddress, destinationEnvironment, CLAUDE_CREDENTIAL_VARIABLES, builtInEnvironment, startBuildServices, BUILT_IN_NAMES, AGENT_CREDENTIAL_MISSING, sharedUserEnvironment, headerVariables, withTunnelRecord, RELAY_PORT } from './chunk-OD2VTIHN.js';
16
+ import { scrubText } from './chunk-GAYWY4GI.js';
17
+ import { isBuiltinContainer, isBuiltinProcess, isBuiltinVm, DEFAULT_CHECK_TIME_LIMIT_MINUTES } from './chunk-PWBILI5P.js';
18
+ import { parseSize } from './chunk-7RQ73DLO.js';
19
+ import { claudeCredential, buildEnvironment, JOB_MOUNT, CHECKOUT_DIR, parseIsolation, proxyEnvironment, containerLocalAddress, destinationEnvironment, CLAUDE_CREDENTIAL_VARIABLES, builtInEnvironment, startBuildServices, BUILT_IN_NAMES, AGENT_CREDENTIAL_MISSING, sharedUserEnvironment, headerVariables, withTunnelRecord, RELAY_PORT, checkEnvironment } from './chunk-OD2VTIHN.js';
19
20
  import { withHooksPath, authorEnvironment, commitIdentityRecord } from './chunk-HKMPVPO7.js';
20
21
  import { parsePolicy } from './chunk-7ZR5UPMB.js';
21
22
  import { readCloudConfig } from './chunk-EABW6AJQ.js';
22
23
  import { resolveVersion } from './chunk-RA3O54FC.js';
23
- import { signerFor } from './chunk-M5POMKKW.js';
24
+ import { signerFor } from './chunk-V7NIVOFD.js';
24
25
  import { runnerDir, buildDir, vsockPath, RUNNER_FILE_MODE } from './chunk-ZM2IMMYN.js';
25
26
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
26
27
  import { spawn, spawnSync } from 'child_process';
@@ -42,6 +43,9 @@ var DOCKER_LOG_LINES = 20;
42
43
  var GUEST_GH_DIR = `${JOB_MOUNT}/gh`;
43
44
  var GUEST_HOOKS_DIR = `${JOB_MOUNT}/git-hooks`;
44
45
  var GUEST_CONTEXT_DIR = `${JOB_MOUNT}/context`;
46
+ function buildMemoryBytes(config) {
47
+ return parseSize(config.build?.memory ?? DEFAULT_MEMORY) ?? parseSize(DEFAULT_MEMORY);
48
+ }
45
49
  function firstLine(text2) {
46
50
  return text2.trim().split("\n")[0] ?? "";
47
51
  }
@@ -121,7 +125,9 @@ async function provisionMicroVm(input) {
121
125
  repository,
122
126
  imageId: report.imageId,
123
127
  containerEnv: report.apply.containerEnv,
124
- builtIns: true
128
+ builtIns: true,
129
+ lifecycle: report.apply.lifecycle,
130
+ ...report.docker === true ? { docker: true } : {}
125
131
  };
126
132
  const env = buildEnvironment({
127
133
  config,
@@ -163,7 +169,7 @@ async function provisionMicroVm(input) {
163
169
  if (input.aborted()) return bail("", true);
164
170
  let imageConfig;
165
171
  try {
166
- state.rootfs = await ensureRootfs({ host: vm.rootfs, runnerDir: runnerDirPath, imageId: report.imageId });
172
+ state.rootfs = await ensureRootfs({ host: vm.rootfs, runnerDir: runnerDirPath, imageId: report.imageId, memoryBytes: buildMemoryBytes(config) });
167
173
  imageConfig = await vm.rootfs.imageConfig(report.imageId);
168
174
  } catch (err) {
169
175
  return bail(`the image could not be converted to a root disk: ${describeCallFailure(err)}`);
@@ -183,14 +189,14 @@ async function provisionMicroVm(input) {
183
189
  }
184
190
  const limits = {
185
191
  cpus: config.build?.cpus ?? DEFAULT_CPUS,
186
- memoryBytes: parseSize(config.build?.memory ?? DEFAULT_MEMORY) ?? parseSize(DEFAULT_MEMORY),
192
+ memoryBytes: buildMemoryBytes(config),
187
193
  diskBytes: parseSize(config.build?.disk ?? DEFAULT_DISK) ?? parseSize(DEFAULT_DISK)
188
194
  };
189
195
  const links = vsockLinks({ destinations: config.build?.destinations?.length ?? 0, builtIns: true });
190
196
  const configPath = join(buildDir2, "vm.json");
191
197
  try {
192
198
  linkVsockSockets({ buildDir: buildDir2, vsockPath: state.vsockPath, links });
193
- await createBuildDisk({ host: vm.rootfs, runnerDir: runnerDirPath, bytes: limits.diskBytes, dest: state.buildDisk });
199
+ await createBuildDisk({ host: vm.rootfs, runnerDir: runnerDirPath, bytes: limits.diskBytes, dest: state.buildDisk, memoryBytes: limits.memoryBytes });
194
200
  writeFileSync(
195
201
  configPath,
196
202
  JSON.stringify(
@@ -403,6 +409,147 @@ async function copyHookErrors(runtime, state, jobDir) {
403
409
  } catch {
404
410
  }
405
411
  }
412
+ async function startCheckMicroVm(input) {
413
+ const { config, runtime, job, jobDir, tokens, log } = input;
414
+ const { vm } = runtime;
415
+ const tag = `#${job.item}`;
416
+ const built = job.microvm;
417
+ const repository = built?.repository ?? job.repository;
418
+ if (built === void 0 || built.imageId === void 0 || repository === void 0 || job.branch === void 0) {
419
+ return { ok: false, reason: "the build's image, repository or branch is not recorded" };
420
+ }
421
+ const branch = job.branch;
422
+ const runnerDirPath = runnerDir(config.configPath);
423
+ const tooDeep = socketPathProblem(buildDir(config.configPath, "0".repeat(12)));
424
+ if (tooDeep !== void 0) return { ok: false, reason: tooDeep };
425
+ const buildId = randomBytes(6).toString("hex");
426
+ const buildDir2 = buildDir(config.configPath, buildId);
427
+ const agentUser = built.agentUser ?? ADDED_USER;
428
+ const state = {
429
+ buildId,
430
+ buildDir: buildDir2,
431
+ repository,
432
+ imageId: built.imageId,
433
+ agentUser,
434
+ containerEnv: built.containerEnv,
435
+ imageEnv: built.imageEnv,
436
+ lifecycle: built.lifecycle,
437
+ ...built.docker === true ? { docker: true } : {}
438
+ };
439
+ const checksDir = join(jobDir, "checks");
440
+ mkdirSync(checksDir, { recursive: true });
441
+ const consolePath = join(checksDir, "vm-console.log");
442
+ input.save(state);
443
+ const fail = async (reason) => {
444
+ try {
445
+ await cleanupMicroVm(runtime, state);
446
+ } catch (err) {
447
+ log.error(`${tag} cleanup of the check environment failed: ${describeCallFailure(err)}`);
448
+ }
449
+ return { ok: false, reason };
450
+ };
451
+ const abandoned = () => input.aborted?.() === true;
452
+ const ABANDONED = "the check environment was abandoned before it was ready";
453
+ let assets;
454
+ try {
455
+ assets = await vm.assets(runnerDirPath);
456
+ } catch (err) {
457
+ return fail(err instanceof AssetError ? err.message : `the microVM's assets could not be had: ${describeCallFailure(err)}`);
458
+ }
459
+ if (abandoned()) return fail(ABANDONED);
460
+ try {
461
+ state.rootfs = await ensureRootfs({ host: vm.rootfs, runnerDir: runnerDirPath, imageId: built.imageId, memoryBytes: buildMemoryBytes(config) });
462
+ } catch (err) {
463
+ return fail(`the image could not be converted to a root disk: ${describeCallFailure(err)}`);
464
+ }
465
+ if (abandoned()) return fail(ABANDONED);
466
+ state.buildDisk = join(buildDir2, "build.ext4");
467
+ state.vsockPath = vsockPath(buildDir2);
468
+ input.save(state);
469
+ mkdirSync(buildDir2, { recursive: true, mode: 448 });
470
+ try {
471
+ const gitRemote = gitRemoteFor(runtime, { repository, branch, tokens, buildDir: buildDir2, log: (line) => log.line(`${tag} ${line}`), readOnly: true });
472
+ runtime.tunnels.set(buildId, await startServicesFor(runtime, config, buildDir2, checksDir, void 0, false, gitRemote));
473
+ } catch (err) {
474
+ return fail(`the tunnel could not start: ${describeCallFailure(err)}`);
475
+ }
476
+ if (abandoned()) return fail(ABANDONED);
477
+ const limits = {
478
+ cpus: config.build?.cpus ?? DEFAULT_CPUS,
479
+ memoryBytes: buildMemoryBytes(config),
480
+ diskBytes: parseSize(config.build?.disk ?? DEFAULT_DISK) ?? parseSize(DEFAULT_DISK)
481
+ };
482
+ const links = vsockLinks({ destinations: config.build?.destinations?.length ?? 0, builtIns: false });
483
+ const configPath = join(buildDir2, "vm.json");
484
+ try {
485
+ linkVsockSockets({ buildDir: buildDir2, vsockPath: state.vsockPath, links });
486
+ await createBuildDisk({ host: vm.rootfs, runnerDir: runnerDirPath, bytes: limits.diskBytes, dest: state.buildDisk, memoryBytes: limits.memoryBytes });
487
+ writeFileSync(
488
+ configPath,
489
+ JSON.stringify(
490
+ machineConfig(limits, { kernel: assets.kernel, rootfs: state.rootfs, buildDisk: state.buildDisk, vsock: state.vsockPath, relayPorts: links.map((link) => link.port), docker: built.docker }),
491
+ null,
492
+ 2
493
+ ),
494
+ { mode: 384 }
495
+ );
496
+ } catch (err) {
497
+ return fail(`the check environment's disk and machine could not be made: ${describeCallFailure(err)}`);
498
+ }
499
+ if (abandoned()) return fail(ABANDONED);
500
+ try {
501
+ state.cgroup = vm.cgroup.create(buildId, limits.memoryBytes);
502
+ } catch (err) {
503
+ return fail(`the check environment's memory limit could not be set: ${describeCallFailure(err)}`);
504
+ }
505
+ if (state.cgroup !== void 0) input.save(state);
506
+ const boot = async () => {
507
+ try {
508
+ state.firecracker = await vm.firecracker.spawn({ binary: assets.firecracker, configPath, consolePath, cgroup: state.cgroup });
509
+ } catch (err) {
510
+ return `Firecracker did not start: ${describeCallFailure(err)}`;
511
+ }
512
+ input.save(state);
513
+ if (abandoned()) return ABANDONED;
514
+ const ready = await waitForAgent(state.vsockPath, { attempts: BOOT_ATTEMPTS, delayMs: BOOT_POLL_MS, sleep: runtime.sleep });
515
+ if (!ready) {
516
+ const why = vm.firecracker.alive(state.firecracker) ? "its exec agent did not answer" : "it exited before its exec agent answered";
517
+ return `the microVM did not start: ${why}; its console is in ${consolePath}`;
518
+ }
519
+ if (built.docker === true) return waitForDocker(runtime, state, agentUser, () => /* @__PURE__ */ new Date());
520
+ return void 0;
521
+ };
522
+ const failed = await boot();
523
+ if (failed !== void 0) return fail(failed);
524
+ if (abandoned()) return fail(ABANDONED);
525
+ const env = checkEnvironment({ config, item: job.item, repository, hostEnv: runtime.hostEnv, containerEnv: built.containerEnv ?? {} });
526
+ return {
527
+ ok: true,
528
+ environment: {
529
+ state,
530
+ exec: async (argv, workdir, opts) => {
531
+ const ran = await vm.exec(state.vsockPath, { argv, user: agentUser, cwd: workdir, env: execEnvironment(state.imageEnv, env) });
532
+ if (opts?.logPath !== void 0) appendFileSync(opts.logPath, ran.stdout + ran.stderr);
533
+ return ran;
534
+ },
535
+ restart: async () => {
536
+ try {
537
+ await vm.firecracker.stop(state.firecracker);
538
+ rmSync(state.vsockPath, { force: true });
539
+ return await boot() === void 0;
540
+ } catch {
541
+ return false;
542
+ }
543
+ }
544
+ }
545
+ };
546
+ }
547
+ async function stopBuildMicroVm(runtime, state, jobDir) {
548
+ await copyHookErrors(runtime, state, jobDir);
549
+ if (state.firecracker === void 0) return;
550
+ await runtime.vm.firecracker.stop(state.firecracker);
551
+ if (runtime.vm.firecracker.alive(state.firecracker)) throw new Error(`the microVM (pid ${state.firecracker.pid}) is still running after it was stopped`);
552
+ }
406
553
  async function cleanupMicroVm(runtime, state, jobDir) {
407
554
  const failures = [];
408
555
  if (jobDir !== void 0) await copyHookErrors(runtime, state, jobDir);
@@ -432,8 +579,8 @@ async function cleanupMicroVm(runtime, state, jobDir) {
432
579
  async function stopOrphanedMicroVms(input) {
433
580
  const stopped = [];
434
581
  for (const { job } of input.jobs) {
435
- const state = job.microvm;
436
- if (state === void 0) continue;
582
+ const states = [job.microvm, job.checkMicrovm].filter((state) => state !== void 0);
583
+ if (states.length === 0) continue;
437
584
  if (job.pid !== void 0 && job.start !== void 0 && isSameProcess(job.pid, job.start)) {
438
585
  try {
439
586
  process.kill(-job.pid, "SIGKILL");
@@ -442,9 +589,11 @@ async function stopOrphanedMicroVms(input) {
442
589
  const deadline = Date.now() + 2e3;
443
590
  while (isSameProcess(job.pid, job.start) && Date.now() < deadline) await new Promise((resolve) => setTimeout(resolve, 10));
444
591
  }
445
- if (state.firecracker !== void 0 && input.runtime.vm.firecracker.alive(state.firecracker)) {
446
- await input.runtime.vm.firecracker.stop(state.firecracker);
447
- stopped.push(state.buildId);
592
+ for (const state of states) {
593
+ if (state.firecracker !== void 0 && input.runtime.vm.firecracker.alive(state.firecracker)) {
594
+ await input.runtime.vm.firecracker.stop(state.firecracker);
595
+ stopped.push(state.buildId);
596
+ }
448
597
  }
449
598
  }
450
599
  return stopped;
@@ -808,8 +957,8 @@ function timeoutAfter(ms, sleep) {
808
957
  return { done, cancel: () => clearTimeout(timer) };
809
958
  }
810
959
  function noCleanEnvironment(job) {
811
- const ran = job.microvm !== void 0 ? "builtin:vm" : job.build?.workDir !== void 0 ? "builtin:process" : "a provision hook of the host's own";
812
- return `the host has no clean environment for checks: this build ran under ${ran}, and checks run only in a new container from a container build's image`;
960
+ const ran = job.build?.workDir !== void 0 ? "builtin:process" : "a provision hook of the host's own";
961
+ return `the host has no clean environment for checks: this build ran under ${ran}, and checks run only in a new container or microVM from a build's image`;
813
962
  }
814
963
  async function runHostChecks(input) {
815
964
  const { config, job, jobDir, deps } = input;
@@ -874,9 +1023,8 @@ async function runHostChecks(input) {
874
1023
  log.error(`${tag} checks failed: ${reason}${keyTail}`);
875
1024
  for (const check of checks) await record(check, "fail", reason, keyTail);
876
1025
  };
877
- let container;
878
1026
  try {
879
- if (job.container === void 0) return await failAll(noCleanEnvironment(job));
1027
+ if (job.container === void 0 && job.microvm === void 0) return await failAll(noCleanEnvironment(job));
880
1028
  if (tokens === void 0) return await failAll("the build's repository tokens are no longer held, so the branch cannot be fetched");
881
1029
  const branch = job.branch;
882
1030
  if (branch === void 0) return await failAll("the build pushed no branch: the claim names none");
@@ -887,8 +1035,30 @@ async function runHostChecks(input) {
887
1035
  const limitMinutes = config.checks?.timeLimitMinutes ?? DEFAULT_CHECK_TIME_LIMIT_MINUTES;
888
1036
  const minutes = `${limitMinutes} ${limitMinutes === 1 ? "minute" : "minutes"}`;
889
1037
  const environmentLog = join(jobDir, "checks", "environment.log");
1038
+ if (job.microvm !== void 0) {
1039
+ if (deps.endBuildMicroVm === void 0) return await failAll("the runner has no way to stop the build's microVM, so no check environment was made");
1040
+ try {
1041
+ await deps.endBuildMicroVm();
1042
+ } catch (err) {
1043
+ return await failAll(`the build's microVM could not be stopped, so no check environment was made: ${describeCallFailure(err)}`);
1044
+ }
1045
+ }
1046
+ let abandoned = false;
890
1047
  const setup = async () => {
891
- const started = await startCheckContainer({
1048
+ const started = job.microvm !== void 0 ? await startCheckMicroVm({
1049
+ config,
1050
+ runtime,
1051
+ job,
1052
+ jobDir,
1053
+ tokens,
1054
+ log,
1055
+ aborted: () => abandoned,
1056
+ save: (state) => {
1057
+ if (abandoned) return;
1058
+ job.checkMicrovm = state;
1059
+ writeJobFile(jobFilePath, job);
1060
+ }
1061
+ }) : await startCheckContainer({
892
1062
  config,
893
1063
  runtime,
894
1064
  job,
@@ -901,8 +1071,7 @@ async function runHostChecks(input) {
901
1071
  }
902
1072
  });
903
1073
  if (!started.ok) return `the check environment could not be made: ${started.reason}`;
904
- container = started.container;
905
- const made = started.container;
1074
+ const made = "container" in started ? started.container : started.environment;
906
1075
  const steps = [
907
1076
  {
908
1077
  argv: ["git", "config", "--global", `url.http://127.0.0.1:${RELAY_PORT}/github.com/.insteadOf`, "https://github.com/"],
@@ -916,10 +1085,11 @@ async function runHostChecks(input) {
916
1085
  }
917
1086
  ];
918
1087
  for (const step of steps) {
1088
+ if (abandoned) return "the check environment setup ran out of time";
919
1089
  const ran = await made.exec(step.argv, step.workdir, { logPath: environmentLog });
920
1090
  if (ran.status !== 0) return `the check environment could not be prepared: ${step.failed(ran.status)}`;
921
1091
  }
922
- for (const step of lifecycleSteps(job.container?.lifecycle ?? {})) {
1092
+ for (const step of lifecycleSteps((job.container ?? job.microvm)?.lifecycle ?? {})) {
923
1093
  log.line(`${tag} checks lifecycle ${step.name} (${step.source})`);
924
1094
  const ran = await made.exec(step.argv, CHECKOUT_DIR, { logPath: environmentLog });
925
1095
  if (ran.status !== 0) return `the check environment could not be prepared: ${lifecycleFailureReason(step, ran.status)}`;
@@ -929,8 +1099,14 @@ async function runHostChecks(input) {
929
1099
  const setupTimer = timeoutAfter(limitMinutes * 6e4, deps.sleep);
930
1100
  let settled;
931
1101
  try {
932
- const outcome = await Promise.race([setup(), setupTimer.done]);
933
- if (outcome === "timeout") return await failAll(`the check environment setup ran out of time after ${minutes}`, LIMIT_KEY_TAIL);
1102
+ const outcome = await Promise.race([
1103
+ setup().catch((err) => `the check environment could not be made: ${describeCallFailure(err)}`),
1104
+ setupTimer.done
1105
+ ]);
1106
+ if (outcome === "timeout") {
1107
+ abandoned = true;
1108
+ return await failAll(`the check environment setup ran out of time after ${minutes}`, LIMIT_KEY_TAIL);
1109
+ }
934
1110
  settled = outcome;
935
1111
  } finally {
936
1112
  setupTimer.cancel();
@@ -976,12 +1152,16 @@ async function runHostChecks(input) {
976
1152
  } catch (err) {
977
1153
  log.error(`${tag} checks stopped: ${describeCallFailure(err)}`);
978
1154
  } finally {
979
- if (container !== void 0 || job.checkContainer !== void 0) {
980
- const state = container?.state ?? job.checkContainer;
981
- await cleanupContainer(runtime, state).catch((err) => log.error(`${tag} removing the check environment failed: ${describeCallFailure(err)}`));
1155
+ if (job.checkContainer !== void 0) {
1156
+ await cleanupContainer(runtime, job.checkContainer).catch((err) => log.error(`${tag} removing the check environment failed: ${describeCallFailure(err)}`));
982
1157
  delete job.checkContainer;
983
1158
  writeJobFile(jobFilePath, job);
984
1159
  }
1160
+ if (job.checkMicrovm !== void 0) {
1161
+ await cleanupMicroVm(runtime, job.checkMicrovm).catch((err) => log.error(`${tag} removing the check environment failed: ${describeCallFailure(err)}`));
1162
+ delete job.checkMicrovm;
1163
+ writeJobFile(jobFilePath, job);
1164
+ }
985
1165
  rmSync(scratch, { recursive: true, force: true });
986
1166
  if (existsSync(scratch)) log.error(`${tag} the checks' scratch directory could not be removed`);
987
1167
  log.line(`${tag} checks done (${formatDuration(now().getTime() - startedMs)})`);
@@ -1461,6 +1641,36 @@ async function finishJob(job, jobDirPath, outcome, config, deps, ending) {
1461
1641
  job.reason = scrubReason(ending.reason, config);
1462
1642
  writeJobFile(jobFilePath, job);
1463
1643
  }
1644
+ const uploadSessions = async (workdir) => {
1645
+ if (job.container === void 0 && job.microvm === void 0 && job.build?.exec === void 0 && workdirProblem(workdir) !== void 0) {
1646
+ log.line(`${tag} sync skipped: workdir ${workdir} is gone`);
1647
+ } else if (job.itemKey === void 0) {
1648
+ log.line(`${tag} sync skipped: the job file holds no item key`);
1649
+ } else {
1650
+ log.line(`${tag} sync started`);
1651
+ const startedMs = now().getTime();
1652
+ const sync = build !== void 0 ? await syncInContainer({ config, runtime: build.runtime, job, jobDir: jobDirPath }) : vmBuild !== void 0 ? await syncInMicroVm({ config, runtime: vmBuild.runtime, job, jobDir: jobDirPath }) : job.build?.exec !== void 0 ? await runSyncViaExec(config, job, jobDirPath, spawnFn) : await runSync(config, job.item, job.itemKey, workdir, jobDirPath, spawnFn, job.branch, job.commitIdentity?.author);
1653
+ const took = formatDuration(now().getTime() - startedMs);
1654
+ if (sync.ok) log.line(`${tag} sync ok (${took})`);
1655
+ else log.error(`${tag} sync failed: ${sync.reason ?? "no reason given"} \xB7 continuing`);
1656
+ const left = spooledArtifactIds(deps.home ?? homeFromEnv());
1657
+ if (left.length > 0) {
1658
+ job.spooledArtifacts = left.slice(0, MAX_NAMED_SPOOLED);
1659
+ const named = job.spooledArtifacts.join(", ");
1660
+ log.error(
1661
+ `${tag} ${left.length} spooled artifact(s) not uploaded: ${named}${left.length > MAX_NAMED_SPOOLED ? `, and ${left.length - MAX_NAMED_SPOOLED} more` : ""}`
1662
+ );
1663
+ }
1664
+ }
1665
+ };
1666
+ const endBuildMicroVm = vmBuild === void 0 ? void 0 : async () => {
1667
+ if (job.workdir && job.sessionsSynced !== true) {
1668
+ await uploadSessions(job.workdir);
1669
+ job.sessionsSynced = true;
1670
+ writeJobFile(jobFilePath, job);
1671
+ }
1672
+ await stopBuildMicroVm(vmBuild.runtime, vmBuild.state, jobDirPath);
1673
+ };
1464
1674
  if (job.checkContainer !== void 0 && job.checksRan === true) {
1465
1675
  try {
1466
1676
  await cleanupContainer(deps.container ?? createContainerRuntime(), job.checkContainer);
@@ -1470,6 +1680,15 @@ async function finishJob(job, jobDirPath, outcome, config, deps, ending) {
1470
1680
  log.error(`${tag} removing an earlier attempt's check environment failed: ${describeCallFailure(err)} \xB7 continuing`);
1471
1681
  }
1472
1682
  }
1683
+ if (job.checkMicrovm !== void 0 && job.checksRan === true) {
1684
+ try {
1685
+ await cleanupMicroVm(deps.container ?? createContainerRuntime(), job.checkMicrovm);
1686
+ delete job.checkMicrovm;
1687
+ writeJobFile(jobFilePath, job);
1688
+ } catch (err) {
1689
+ log.error(`${tag} removing an earlier attempt's check environment failed: ${describeCallFailure(err)} \xB7 continuing`);
1690
+ }
1691
+ }
1473
1692
  if (outcome === "ok" && !job.cleanupRan && job.checksRan !== true) {
1474
1693
  setStage(job, jobDirPath, "checks");
1475
1694
  job.checksRan = true;
@@ -1479,7 +1698,7 @@ async function finishJob(job, jobDirPath, outcome, config, deps, ending) {
1479
1698
  config,
1480
1699
  job,
1481
1700
  jobDir: jobDirPath,
1482
- deps: { fetchImpl: deps.fetchImpl, runtime: deps.container ?? createContainerRuntime(), log, now: deps.now, ...deps.hostChecks }
1701
+ deps: { fetchImpl: deps.fetchImpl, runtime: deps.container ?? createContainerRuntime(), log, now: deps.now, endBuildMicroVm, ...deps.hostChecks }
1483
1702
  });
1484
1703
  } catch (err) {
1485
1704
  log.error(`${tag} the host's checks stopped: ${describeCallFailure(err)} \xB7 continuing`);
@@ -1504,26 +1723,8 @@ async function finishJob(job, jobDirPath, outcome, config, deps, ending) {
1504
1723
  if (!job.cleanupRan) {
1505
1724
  if (job.workdir) {
1506
1725
  setStage(job, jobDirPath, "sync");
1507
- if (job.container === void 0 && job.microvm === void 0 && job.build?.exec === void 0 && workdirProblem(job.workdir) !== void 0) {
1508
- log.line(`${tag} sync skipped: workdir ${job.workdir} is gone`);
1509
- } else if (job.itemKey === void 0) {
1510
- log.line(`${tag} sync skipped: the job file holds no item key`);
1511
- } else {
1512
- log.line(`${tag} sync started`);
1513
- const startedMs = now().getTime();
1514
- const sync = build !== void 0 ? await syncInContainer({ config, runtime: build.runtime, job, jobDir: jobDirPath }) : vmBuild !== void 0 ? await syncInMicroVm({ config, runtime: vmBuild.runtime, job, jobDir: jobDirPath }) : job.build?.exec !== void 0 ? await runSyncViaExec(config, job, jobDirPath, spawnFn) : await runSync(config, job.item, job.itemKey, job.workdir, jobDirPath, spawnFn, job.branch, job.commitIdentity?.author);
1515
- const took = formatDuration(now().getTime() - startedMs);
1516
- if (sync.ok) log.line(`${tag} sync ok (${took})`);
1517
- else log.error(`${tag} sync failed: ${sync.reason ?? "no reason given"} \xB7 continuing`);
1518
- const left = spooledArtifactIds(deps.home ?? homeFromEnv());
1519
- if (left.length > 0) {
1520
- job.spooledArtifacts = left.slice(0, MAX_NAMED_SPOOLED);
1521
- const named = job.spooledArtifacts.join(", ");
1522
- log.error(
1523
- `${tag} ${left.length} spooled artifact(s) not uploaded: ${named}${left.length > MAX_NAMED_SPOOLED ? `, and ${left.length - MAX_NAMED_SPOOLED} more` : ""}`
1524
- );
1525
- }
1526
- }
1726
+ if (job.sessionsSynced === true) log.line(`${tag} sync done before the build's microVM stopped`);
1727
+ else await uploadSessions(job.workdir);
1527
1728
  }
1528
1729
  setStage(job, jobDirPath, "cleanup");
1529
1730
  try {
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { MIN_ENGINE_MAJOR } from './chunk-E4PIFIC3.js';
4
- import { firecrackerArch, MICROVM_ARCHES, guestAssetsPinned } from './chunk-CEBIA5FD.js';
3
+ import { MIN_ENGINE_MAJOR } from './chunk-M4ERCYDB.js';
4
+ import { firecrackerArch, MICROVM_ARCHES, guestAssetsPinned } from './chunk-CX22S5BA.js';
5
5
  import { spawnSync } from 'child_process';
6
6
  import { existsSync, accessSync, constants, statSync, readFileSync } from 'fs';
7
7