@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
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { RecipeError } from './chunk-QOZKPLVJ.js';
4
+ import { trackImageBuild, isOutOfMemory, ensureBuilder } from './chunk-2BRSMBBB.js';
4
5
  import { spawn } from 'child_process';
5
- import { existsSync, mkdirSync, createWriteStream, readFileSync } from 'fs';
6
+ import { existsSync, mkdirSync, createWriteStream, rmSync, readFileSync } from 'fs';
6
7
  import { join, dirname } from 'path';
7
8
  import { createRequire as createRequire$1 } from 'module';
8
9
  import { fileURLToPath } from 'url';
@@ -48,7 +49,9 @@ function devcontainerBuildInvocation(cli, req) {
48
49
  req.imageName,
49
50
  ...Object.entries(req.labels).flatMap(([key, value]) => ["--label", `${key}=${value}`]),
50
51
  "--log-format",
51
- "text"
52
+ "text",
53
+ // Written as an OCI layout instead of loaded into Docker: the runner's builder cannot read Docker's image store, so the next layer starts FROM the layout.
54
+ ...req.layoutOut === void 0 ? [] : ["--output", `type=oci,dest=${req.layoutOut},tar=false`]
52
55
  ]
53
56
  };
54
57
  }
@@ -69,6 +72,14 @@ var CHILD_ENVIRONMENT_NAMES = [
69
72
  "DOCKER_TLS_VERIFY",
70
73
  "DOCKER_API_VERSION",
71
74
  "DOCKER_BUILDKIT",
75
+ // `docker buildx build` fetches registry tokens in the client and hands them to the builder, so a host that reaches
76
+ // registries through a proxy needs it here as well as in the builder.
77
+ "HTTP_PROXY",
78
+ "HTTPS_PROXY",
79
+ "NO_PROXY",
80
+ "http_proxy",
81
+ "https_proxy",
82
+ "no_proxy",
72
83
  "XDG_RUNTIME_DIR",
73
84
  "XDG_CONFIG_HOME",
74
85
  "XDG_DATA_HOME",
@@ -103,6 +114,7 @@ var spawnRun = (command, args, opts = {}) => new Promise((resolve) => {
103
114
  if (extra) log.write(extra);
104
115
  log.end(() => resolve(result));
105
116
  };
117
+ let timer;
106
118
  const child = spawn(command, args, {
107
119
  env: { ...childEnvironment(process.env), ...opts.env },
108
120
  stdio: [opts.input === void 0 ? "ignore" : "pipe", "pipe", "pipe"]
@@ -115,9 +127,20 @@ var spawnRun = (command, args, opts = {}) => new Promise((resolve) => {
115
127
  stderr += chunk.toString();
116
128
  log?.write(chunk);
117
129
  });
130
+ if (opts.timeoutMs !== void 0) {
131
+ timer = setTimeout(() => {
132
+ child.kill("SIGKILL");
133
+ finish(124, `${command}: no answer within ${Math.round(opts.timeoutMs / 1e3)}s
134
+ `);
135
+ }, opts.timeoutMs);
136
+ timer.unref();
137
+ }
118
138
  child.on("error", (err) => finish(127, `${command}: ${err.message}
119
139
  `));
120
- child.on("close", (code, signal) => finish(code ?? (signal ? 128 : 1)));
140
+ child.on("close", (code, signal) => {
141
+ if (timer !== void 0) clearTimeout(timer);
142
+ finish(code ?? (signal ? 128 : 1));
143
+ });
121
144
  if (opts.input !== void 0) {
122
145
  child.stdin.on("error", () => void 0);
123
146
  child.stdin.end(opts.input);
@@ -127,9 +150,28 @@ function toInfo(row) {
127
150
  return { id: row.Id, createdAt: row.Created, labels: row.Config?.Labels ?? {} };
128
151
  }
129
152
  var lines = (text) => [...new Set(text.split("\n").map((l) => l.trim()).filter(Boolean))];
153
+ function layoutDigest(layout) {
154
+ const index = JSON.parse(readFileSync(join(layout, "index.json"), "utf8"));
155
+ const digest = index.manifests?.[0]?.digest;
156
+ if (digest === void 0) throw new Error(`${join(layout, "index.json")} lists no image`);
157
+ return digest;
158
+ }
159
+ function outOfMemory(builder, logPath) {
160
+ return new RecipeError(
161
+ "image_build_out_of_memory",
162
+ `the image build ran out of memory: the kernel stopped a build step at the limit of runner.build.memory (${builder.memory}). Raise runner.build.memory, or lower what the recipe's build steps use; the build log is at ${logPath}`,
163
+ logPath
164
+ );
165
+ }
130
166
  function createDockerHost(deps = {}) {
131
167
  const run = deps.run ?? spawnRun;
132
168
  const cli = deps.cli ?? resolveDevcontainerCli;
169
+ const builderFor = () => {
170
+ if (deps.builder === void 0) {
171
+ throw new Error("no image builder is configured, so the image build was not started: every image build runs in the runner's builder, which carries runner.build.memory");
172
+ }
173
+ return deps.builder;
174
+ };
133
175
  const inspectMany = async (refs) => {
134
176
  const result = await run("docker", ["image", "inspect", ...refs]);
135
177
  return result.status === 0 ? JSON.parse(result.stdout).map(toInfo) : [];
@@ -156,17 +198,58 @@ function createDockerHost(deps = {}) {
156
198
  if (containers.length === 0) return [];
157
199
  return lines((await run("docker", ["inspect", "--format", "{{.Image}}", ...containers])).stdout);
158
200
  },
201
+ async ensureBuilder() {
202
+ const builder = builderFor();
203
+ const result = await ensureBuilder(run, builder, { waitForIdle: true, replaceStale: deps.replaceStaleBuilder });
204
+ if (!result.ok) throw new RecipeError("image_builder_unavailable", `the image builder is unavailable: ${result.problem}`);
205
+ return { name: builder.name, memory: builder.memory };
206
+ },
207
+ async exportLayout(ref, dir) {
208
+ rmSync(dir, { recursive: true, force: true });
209
+ mkdirSync(dir, { recursive: true });
210
+ const archive = join(dir, ".image.tar");
211
+ const saved = await run("docker", ["save", "--output", archive, ref]);
212
+ if (saved.status !== 0) throw new Error(saved.stderr.trim() || `docker save ${ref} exited ${saved.status}`);
213
+ const unpacked = await run("tar", ["-xf", archive, "-C", dir]);
214
+ rmSync(archive, { force: true });
215
+ if (unpacked.status !== 0) throw new Error(unpacked.stderr.trim() || `tar exited ${unpacked.status}`);
216
+ },
159
217
  async buildDockerfile(req) {
218
+ const builder = builderFor();
219
+ if (req.layoutOut !== void 0) {
220
+ rmSync(req.layoutOut, { recursive: true, force: true });
221
+ }
160
222
  const labels = Object.entries(req.labels).flatMap(([key, value]) => ["--label", `${key}=${value}`]);
161
- const result = await run("docker", ["build", "--tag", req.tag, ...labels, "--file", "-", req.context], {
162
- logPath: req.logPath,
163
- input: req.dockerfile
164
- });
223
+ const args = [
224
+ "buildx",
225
+ "build",
226
+ "--builder",
227
+ builder.name,
228
+ "--load",
229
+ ...req.layoutOut === void 0 ? [] : ["--output", `type=oci,dest=${req.layoutOut},tar=false`],
230
+ ...req.base === void 0 ? [] : ["--build-context", `${req.base.ref}=oci-layout://${req.base.layout}@${layoutDigest(req.base.layout)}`],
231
+ "--tag",
232
+ req.tag,
233
+ ...labels,
234
+ "--file",
235
+ "-",
236
+ req.context
237
+ ];
238
+ const result = await trackImageBuild(() => run("docker", args, { logPath: req.logPath, input: req.dockerfile }));
239
+ if (result.status !== 0 && isOutOfMemory(`${result.stdout}
240
+ ${result.stderr}`)) throw outOfMemory(builder, req.logPath);
165
241
  return result.status;
166
242
  },
167
243
  async devcontainerBuild(req) {
244
+ const builder = builderFor();
168
245
  const { command, args } = devcontainerBuildInvocation(cli(), req);
169
- return (await run(command, args, { logPath: req.logPath })).status;
246
+ if (req.layoutOut !== void 0) {
247
+ rmSync(req.layoutOut, { recursive: true, force: true });
248
+ }
249
+ const result = await trackImageBuild(() => run(command, args, { logPath: req.logPath, env: { BUILDX_BUILDER: builder.name } }));
250
+ if (result.status !== 0 && isOutOfMemory(`${result.stdout}
251
+ ${result.stderr}`)) throw outOfMemory(builder, req.logPath);
252
+ return result.status;
170
253
  },
171
254
  async remove(id) {
172
255
  const result = await run("docker", ["rmi", id]);
@@ -2,6 +2,7 @@
2
2
  import { createRequire } from 'node:module';
3
3
  import { startTimeOf, claimPidFile, RunnerAlreadyRunningError, releasePidFile } from './chunk-N5FOE5PS.js';
4
4
  import { RecipeError, locateRecipe, readRecipe, assertBuildable, writeSanitizedRecipe, classifyProperties, SANITIZED_NAME } from './chunk-QOZKPLVJ.js';
5
+ import { CLAUDE_CODE_VERSION, NODE_IMAGE, DEFAULT_BASE_IMAGE, TINI_VERSION, GH_VERSION, GH_SHA256, TINI_SHA256 } from './chunk-CX22S5BA.js';
5
6
  import { withGitConfig } from './chunk-HKMPVPO7.js';
6
7
  import { RUNNER_DIR_MODE, repoCacheDir, imagesDir, attemptStamp, runnerDir, rootfsPathFor, RUNNER_FILE_MODE } from './chunk-ZM2IMMYN.js';
7
8
  import { mkdirSync, rmSync, existsSync, mkdtempSync, cpSync, readFileSync, writeFileSync, readdirSync, lstatSync, readlinkSync } from 'fs';
@@ -123,44 +124,6 @@ async function cloneRepository(remote, dest, timeoutMs = CLONE_TIMEOUT_MS) {
123
124
  }
124
125
  }
125
126
 
126
- // src/runner/image/pins.ts
127
- var CLAUDE_CODE_VERSION = "2.1.284";
128
- var DEFAULT_BASE_IMAGE = "ubuntu:24.04@sha256:008173c23f95b170204355c12626cb5a965d779a7e1283b09e9cffbb1bf33ca3";
129
- var NODE_IMAGE = "node:22-bookworm-slim@sha256:43ac6c60b8f89723f746e8a92ce91abd5017e627ce1ddfe4238355d3a30b772c";
130
- var GH_VERSION = "2.101.0";
131
- var GH_SHA256 = {
132
- amd64: "9bca2d1c16825f109907a23307628a2f0698fbf99662b73a5cf0b020293072b8",
133
- arm64: "b57e8063f18862647c9d22727c32e9da1b963f8bf9db648fe123a6975695640f"
134
- };
135
- var TINI_VERSION = "0.19.0";
136
- var TINI_SHA256 = {
137
- amd64: "c5b0666b4cb676901f90dfcb37106783c5fe2077b04590973b885950611b30ee",
138
- arm64: "eae1d3aa50c48fb23b8cbdf4e369d0910dfc538566bfd09df89a774aa84a48b9"
139
- };
140
- var MICROVM_ARCHES = ["x86_64"];
141
- function firecrackerArch(nodeArch) {
142
- return nodeArch === "x64" ? "x86_64" : nodeArch === "arm64" ? "aarch64" : nodeArch;
143
- }
144
- var FIRECRACKER_VERSION = "1.13.1";
145
- var FIRECRACKER_SHA256 = {
146
- x86_64: "59450b9171ff2ebdf2f9a25be3a248a7ba79fb6371aec51a9d6d8eefca7b4faf"
147
- };
148
- var FIRECRACKER_BINARY_SHA256 = {
149
- x86_64: "7d3924e0c8761edafbf85cb2a94c268ffad249644a40fd02d4e15cde4c206f6e"
150
- };
151
- var GUEST_ASSETS_VERSION = "1";
152
- var GUEST_ASSETS_BASE_URL = `https://github.com/outerlayerai/guest-assets/releases/download/guest-${GUEST_ASSETS_VERSION}`;
153
- var GUEST_KERNEL_SHA256 = {
154
- x86_64: "5a2d716d301615c69fefc2f9574954e838269f14d5e8b0d1bad88b680cd372ee"
155
- };
156
- var GUEST_HELPER_SHA256 = {
157
- x86_64: "4175e89ae8cb633113b5f69ef8b6e206093954411fe53edf86357bc1b7e822f9"
158
- };
159
- function guestAssetsPinned(arch) {
160
- const zero = "0".repeat(64);
161
- return GUEST_KERNEL_SHA256[arch] !== zero && GUEST_HELPER_SHA256[arch] !== zero;
162
- }
163
-
164
127
  // src/runner/image/dockerfiles.ts
165
128
  function plain(name, value, allowed) {
166
129
  if (!allowed.test(value)) throw new Error(`${name} holds a character a Dockerfile line cannot carry safely: ${JSON.stringify(value)}`);
@@ -307,6 +270,7 @@ var KEEP_BUILD_IMAGES = 3;
307
270
  var TAG_HOST = "outerlayer.invalid";
308
271
  var KEY_PREFIX = 12;
309
272
  var LOCK_NAME = "build.lock";
273
+ var LAYOUTS_DIR = "layouts";
310
274
  function splitRepository(repository) {
311
275
  const full = repository.toLowerCase();
312
276
  const parts = full.split("/");
@@ -388,33 +352,56 @@ async function buildRepositoryImage(opts, ports) {
388
352
  (i) => i.labels[KIND2] === "build" && i.labels[RECIPE_KEY2] === rKey && i.labels[TOOLS_KEY] === tKey
389
353
  );
390
354
  const failed = (what, status) => new RecipeError("build_failed", `${what} failed (exit ${status}); the build log is at ${logPath}`, logPath);
355
+ let builderReady = false;
356
+ const ensureBuilder = async () => {
357
+ if (builderReady) return;
358
+ const builder = await host.ensureBuilder();
359
+ opts.log?.(`image build in builder ${builder.name} at ${builder.memory}`);
360
+ builderReady = true;
361
+ };
362
+ const keptLayout = join(repoRecords, LAYOUTS_DIR, rKey.slice(0, KEY_PREFIX));
363
+ const layoutKept = () => existsSync(join(keptLayout, "index.json"));
391
364
  let recipeImage = recipeImageBefore;
392
365
  let recipeBuilt = false;
393
366
  if (recipeImage === void 0 && buildImageBefore === void 0) {
367
+ await ensureBuilder();
368
+ mkdirSync(join(repoRecords, LAYOUTS_DIR), { recursive: true, mode: RUNNER_DIR_MODE });
394
369
  const labels = { [REPOSITORY]: repository, [KIND2]: "recipe", [RECIPE_KEY2]: rKey };
395
370
  if (location.kind === "default") {
396
371
  const context = mkdtempSync(join(scratchRoot, "ol-image-default-"));
397
372
  try {
398
- const status = await host.buildDockerfile({ dockerfile: defaultText, context, tag: recipeTag, labels, logPath });
373
+ const status = await host.buildDockerfile({ dockerfile: defaultText, context, tag: recipeTag, labels, logPath, layoutOut: keptLayout });
399
374
  if (status !== 0) throw failed("the docker build of the default image", status);
400
375
  } finally {
401
376
  rmSync(context, { recursive: true, force: true });
402
377
  }
403
378
  } else {
404
379
  const config = writeSanitizedRecipe(checkout.dir, location, recipe);
380
+ const scratchLayouts = mkdtempSync(join(scratchRoot, "ol-image-layout-"));
381
+ const scratchLayout = join(scratchLayouts, "layout");
405
382
  try {
406
- const status = await host.devcontainerBuild({ workspace: checkout.dir, config, imageName: recipeTag, labels, logPath });
383
+ const status = await host.devcontainerBuild({ workspace: checkout.dir, config, imageName: recipeTag, labels, logPath, layoutOut: scratchLayout });
407
384
  if (status !== 0) throw failed("devcontainer build", status);
385
+ if (!existsSync(join(scratchLayout, "index.json"))) throw failed("devcontainer build, which left no image to label,", 0);
386
+ const context = mkdtempSync(join(scratchRoot, "ol-image-label-"));
387
+ try {
388
+ const relabel = await host.buildDockerfile({
389
+ dockerfile: `FROM ${recipeTag}
390
+ `,
391
+ context,
392
+ tag: recipeTag,
393
+ labels,
394
+ logPath,
395
+ base: { ref: recipeTag, layout: scratchLayout },
396
+ layoutOut: keptLayout
397
+ });
398
+ if (relabel !== 0) throw failed("labelling the recipe image", relabel);
399
+ } finally {
400
+ rmSync(context, { recursive: true, force: true });
401
+ }
408
402
  } finally {
409
403
  rmSync(config, { force: true });
410
- }
411
- const context = mkdtempSync(join(scratchRoot, "ol-image-label-"));
412
- try {
413
- const status = await host.buildDockerfile({ dockerfile: `FROM ${recipeTag}
414
- `, context, tag: recipeTag, labels, logPath });
415
- if (status !== 0) throw failed("labelling the recipe image", status);
416
- } finally {
417
- rmSync(context, { recursive: true, force: true });
404
+ rmSync(scratchLayouts, { recursive: true, force: true });
418
405
  }
419
406
  }
420
407
  recipeImage = await host.inspect(recipeTag) ?? void 0;
@@ -423,6 +410,8 @@ async function buildRepositoryImage(opts, ports) {
423
410
  }
424
411
  let buildImage = buildImageBefore;
425
412
  if (buildImage === void 0) {
413
+ await ensureBuilder();
414
+ if (!layoutKept()) await host.exportLayout(recipeTag, keptLayout);
426
415
  const context = mkdtempSync(join(scratchRoot, "ol-image-tools-"));
427
416
  try {
428
417
  cpSync(opts.cli.distDir, join(context, "dist"), { recursive: true });
@@ -433,7 +422,7 @@ async function buildRepositoryImage(opts, ports) {
433
422
  }
434
423
  const dockerfile = toolsDockerfile({ recipeImage: recipeTag, nodeImage, claudeCodeVersion, buildId: opts.cli.buildId, guestHelper: opts.guestHelper !== void 0 });
435
424
  const labels = { [REPOSITORY]: repository, [KIND2]: "build", [RECIPE_KEY2]: rKey, [TOOLS_KEY]: tKey };
436
- const status = await host.buildDockerfile({ dockerfile, context, tag: buildTag, labels, logPath });
425
+ const status = await host.buildDockerfile({ dockerfile, context, tag: buildTag, labels, logPath, base: { ref: recipeTag, layout: keptLayout } });
437
426
  if (status !== 0) throw failed("the docker build of the tools layer", status);
438
427
  } finally {
439
428
  rmSync(context, { recursive: true, force: true });
@@ -486,6 +475,9 @@ async function prune(host, repository, repoRecords, keep, runnerDirPath) {
486
475
  rmSync(rootfsPathFor(runnerDirPath, image.id), { force: true });
487
476
  const recipeKeyLabel = image.labels[RECIPE_KEY2];
488
477
  const toolsKeyLabel = image.labels[TOOLS_KEY];
478
+ if (image.labels[KIND2] === "recipe" && recipeKeyLabel !== void 0) {
479
+ rmSync(join(repoRecords, LAYOUTS_DIR, recipeKeyLabel.slice(0, KEY_PREFIX)), { recursive: true, force: true });
480
+ }
489
481
  if (image.labels[KIND2] === "build" && recipeKeyLabel !== void 0 && toolsKeyLabel !== void 0) {
490
482
  rmSync(join(repoRecords, `${recipeKeyLabel.slice(0, KEY_PREFIX)}-${toolsKeyLabel.slice(0, KEY_PREFIX)}`), { recursive: true, force: true });
491
483
  }
@@ -493,4 +485,4 @@ async function prune(host, repository, repoRecords, keep, runnerDirPath) {
493
485
  return removed;
494
486
  }
495
487
 
496
- export { CLAUDE_CODE_VERSION, DEFAULT_BASE_IMAGE, FIRECRACKER_BINARY_SHA256, FIRECRACKER_SHA256, FIRECRACKER_VERSION, GUEST_ASSETS_BASE_URL, GUEST_ASSETS_VERSION, GUEST_HELPER_SHA256, GUEST_KERNEL_SHA256, MICROVM_ARCHES, buildRepositoryImage, cloneRepository, fetchCommit, firecrackerArch, guestAssetsPinned, readBranchHead, readDefaultBranchHead };
488
+ export { buildRepositoryImage, cloneRepository, fetchCommit, readBranchHead, readDefaultBranchHead };
@@ -3,23 +3,6 @@ import { createRequire } from 'node:module';
3
3
 
4
4
  createRequire(import.meta.url);
5
5
 
6
- // src/runner/container/disk.ts
7
- var UNITS = { "": 1, k: 1024, m: 1024 ** 2, g: 1024 ** 3 };
8
- function parseSize(text) {
9
- const match = /^(\d+(?:\.\d+)?)([kKmMgG]?)$/.exec(text);
10
- if (match === null) return void 0;
11
- const bytes = Number(match[1]) * UNITS[match[2].toLowerCase()];
12
- return bytes > 0 ? bytes : void 0;
13
- }
14
- function parseDuKilobytes(output) {
15
- const match = /^(\d+)\s/.exec(output);
16
- return match === null ? void 0 : Number(match[1]);
17
- }
18
- function exceedsDisk(usedKilobytes, limit) {
19
- const bytes = parseSize(limit);
20
- return usedKilobytes * 1024 > (bytes ?? Number.POSITIVE_INFINITY);
21
- }
22
-
23
6
  // src/runner/allow-hosts.ts
24
7
  var MAX_ALLOW_HOSTS = 500;
25
8
  var LABEL = /^(?!-)[a-z0-9-]{1,63}(?<!-)$/;
@@ -57,4 +40,4 @@ function hostAllowed(host, allowHosts) {
57
40
  });
58
41
  }
59
42
 
60
- export { MAX_ALLOW_HOSTS, allowHostProblem, exceedsDisk, hostAllowed, parseDuKilobytes, parseSize };
43
+ export { MAX_ALLOW_HOSTS, allowHostProblem, hostAllowed };
@@ -6,7 +6,7 @@ import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
6
6
 
7
7
  createRequire(import.meta.url);
8
8
 
9
- // ../../node_modules/structured-headers/dist/util.js
9
+ // ../../node_modules/http-message-sig/node_modules/structured-headers/dist/util.js
10
10
  var asciiRe = /^[\x20-\x7E]*$/;
11
11
  var tokenRe = /^[a-zA-Z*][:/!#$%&'*+\-.^_`|~A-Za-z0-9]*$/;
12
12
  var keyRe = /^[a-z*][*\-_.a-z0-9]*$/;
@@ -40,7 +40,7 @@ function base64ToArrayBuffer(b64) {
40
40
  return bytes.buffer;
41
41
  }
42
42
 
43
- // ../../node_modules/structured-headers/dist/token.js
43
+ // ../../node_modules/http-message-sig/node_modules/structured-headers/dist/token.js
44
44
  var Token = class {
45
45
  constructor(value) {
46
46
  if (!isValidTokenStr(value)) {
@@ -53,7 +53,7 @@ var Token = class {
53
53
  }
54
54
  };
55
55
 
56
- // ../../node_modules/structured-headers/dist/displaystring.js
56
+ // ../../node_modules/http-message-sig/node_modules/structured-headers/dist/displaystring.js
57
57
  var DisplayString = class {
58
58
  constructor(value) {
59
59
  this.value = value;
@@ -63,7 +63,7 @@ var DisplayString = class {
63
63
  }
64
64
  };
65
65
 
66
- // ../../node_modules/structured-headers/dist/serializer.js
66
+ // ../../node_modules/http-message-sig/node_modules/structured-headers/dist/serializer.js
67
67
  var SerializeError = class extends Error {
68
68
  };
69
69
  function serializeDictionary(input) {
@@ -186,7 +186,7 @@ function serializeKey(input) {
186
186
  return input;
187
187
  }
188
188
 
189
- // ../../node_modules/structured-headers/dist/parser.js
189
+ // ../../node_modules/http-message-sig/node_modules/structured-headers/dist/parser.js
190
190
  function parseDictionary(input) {
191
191
  const parser = new Parser(input);
192
192
  return parser.parseDictionary();
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { readCloudConfig, cloudConfigPath } from './chunk-EABW6AJQ.js';
4
- import { signRunnerRequest, signerFor } from './chunk-M5POMKKW.js';
4
+ import { signRunnerRequest, signerFor } from './chunk-V7NIVOFD.js';
5
5
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
6
6
 
7
7
  createRequire(import.meta.url);
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { detectMachine, supportsContainerBuilds, reachDockerStep, describeMachineDocker, supportsMicroVmBuilds } from './chunk-AQ54MKSQ.js';
4
- import { MIN_ENGINE_MAJOR } from './chunk-E4PIFIC3.js';
3
+ import { detectMachine, supportsContainerBuilds, reachDockerStep, describeMachineDocker, supportsMicroVmBuilds } from './chunk-QNRSFEGY.js';
4
+ import { MIN_ENGINE_MAJOR } from './chunk-M4ERCYDB.js';
5
5
  import { RUNNER_DIR_MODE, runnerDir, RUNNER_FILE_MODE } from './chunk-ZM2IMMYN.js';
6
6
  import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
7
7
  import { dirname } from 'path';