@outerlayer/cli 0.33.0-next.20261022004023 → 0.33.0-next.20261022124145

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 (94) hide show
  1. package/README.md +12 -11
  2. package/dist/{agent-setup-UY5NBT7C.js → agent-setup-2MJXGAZ5.js} +10 -10
  3. package/dist/{artifact-link-cmd-2MBHG3PO.js → artifact-link-cmd-6FF2Y6QI.js} +2 -2
  4. package/dist/build-disk-5GIWYDOB.js +18 -0
  5. package/dist/build-info.json +1 -1
  6. package/dist/{builder-VR55L4PV.js → builder-EELBB7SI.js} +4 -4
  7. package/dist/{check-XGBAFJPP.js → check-EJKRXI2N.js} +36 -34
  8. package/dist/{chunk-N3KK5BKF.js → chunk-2GHI2J26.js} +7 -7
  9. package/dist/{chunk-AKR32WHV.js → chunk-5DNCFOXA.js} +9 -7
  10. package/dist/{chunk-UIBTEDLA.js → chunk-6JNCNHSV.js} +5 -5
  11. package/dist/{chunk-GHQFV3TS.js → chunk-6WUQSARX.js} +11 -10
  12. package/dist/{chunk-EG7KPSSP.js → chunk-72BIONOT.js} +6 -6
  13. package/dist/{chunk-XNGS6LUK.js → chunk-AESNEWYR.js} +1 -1
  14. package/dist/{chunk-LN4WDONI.js → chunk-AVTI3FL5.js} +1 -1
  15. package/dist/{chunk-5RUH3PCG.js → chunk-B3EE7OKK.js} +4 -4
  16. package/dist/{chunk-Y3LIJIRH.js → chunk-BJQ25STI.js} +4 -4
  17. package/dist/{chunk-6TFTRVOA.js → chunk-C3XLVHN6.js} +2 -2
  18. package/dist/{chunk-OEITN64Z.js → chunk-D7ECJX4J.js} +15 -38
  19. package/dist/{chunk-UWEJ6HGB.js → chunk-DY7Y7UT4.js} +2 -2
  20. package/dist/{chunk-AKHGQKNR.js → chunk-E6CO3MJE.js} +34 -2
  21. package/dist/{chunk-DM4EGXDO.js → chunk-EWVYQLD3.js} +1 -1
  22. package/dist/{chunk-BUBMAMIP.js → chunk-FQW7TKIU.js} +2 -2
  23. package/dist/{chunk-KUTZ6XLS.js → chunk-G63KT5I5.js} +1 -1
  24. package/dist/{chunk-Q2D4M3GC.js → chunk-GFYEMCPP.js} +1 -1
  25. package/dist/{chunk-4IG6EZHU.js → chunk-HJYBWJAS.js} +2 -2
  26. package/dist/{chunk-CMTRZC23.js → chunk-HVIYKGK5.js} +79 -12
  27. package/dist/{chunk-TNJXCNQ6.js → chunk-JHTJPQSL.js} +4 -4
  28. package/dist/{chunk-RVWADVBN.js → chunk-JZ4FXSLI.js} +3 -3
  29. package/dist/{chunk-HT7LVCTX.js → chunk-L3DUKDTR.js} +2 -2
  30. package/dist/{chunk-KDM77TVX.js → chunk-LCVR4UIS.js} +2 -2
  31. package/dist/{chunk-OGCG5LOX.js → chunk-LJG6EMLJ.js} +1 -1
  32. package/dist/{chunk-HJEZ3D3E.js → chunk-LWODW66U.js} +16 -16
  33. package/dist/chunk-MBE6FEQ3.js +111 -0
  34. package/dist/{chunk-RW52CUFX.js → chunk-NSPRS7WK.js} +1 -1
  35. package/dist/{chunk-DE7YSNDX.js → chunk-OJ63GRZ2.js} +2 -2
  36. package/dist/{chunk-Q4YVHYHT.js → chunk-QJNFO7TQ.js} +3 -3
  37. package/dist/{chunk-NOXK3QW6.js → chunk-QSSYXK6C.js} +3 -3
  38. package/dist/{chunk-UENWEDZ3.js → chunk-S2IJQER5.js} +255 -255
  39. package/dist/{chunk-RQKQTRXM.js → chunk-THTBXIK5.js} +4 -4
  40. package/dist/{chunk-M5OBRUQE.js → chunk-UIUGTW5C.js} +2 -2
  41. package/dist/{chunk-YH2632RT.js → chunk-V2EUC2MJ.js} +43 -20
  42. package/dist/{chunk-SFJD4MRY.js → chunk-WHRR55PC.js} +14 -7
  43. package/dist/{chunk-CALFNNIY.js → chunk-XTBGPISI.js} +17 -6
  44. package/dist/chunk-YYYRBYWG.js +32 -0
  45. package/dist/{claude-launcher-STSKZNW3.js → claude-launcher-IUDNUD2J.js} +17 -6
  46. package/dist/{cli-BMV37UKQ.js → cli-5JSVOAE5.js} +89 -89
  47. package/dist/{command-35IERXEA.js → command-7IY3XGAG.js} +24 -23
  48. package/dist/{connect-cmd-WFHAPGCZ.js → connect-cmd-AQSJVDQU.js} +8 -8
  49. package/dist/{container-start-3FFBFFNK.js → container-start-BPQHJMNF.js} +25 -24
  50. package/dist/{context-cleanup-UBOJHGQM.js → context-cleanup-BX5Y3AFL.js} +3 -3
  51. package/dist/{control-plane-launch-R4X63DYW.js → control-plane-launch-K7YD6KEN.js} +6 -6
  52. package/dist/{dist-ADFLG3AY.js → dist-ACTRIBVW.js} +2 -2
  53. package/dist/{docker-2NN3EKTR.js → docker-UKJBLZLW.js} +4 -4
  54. package/dist/{doctor-CA5QQ5KS.js → doctor-JUR62PMF.js} +48 -25
  55. package/dist/{emit-artifact-cmd-FR5PUUJR.js → emit-artifact-cmd-HI3EYJA3.js} +13 -13
  56. package/dist/{emit-cmd-JOO6ZTEI.js → emit-cmd-OX6LYS6I.js} +6 -6
  57. package/dist/{emit-criteria-cmd-DKPZJTIN.js → emit-criteria-cmd-IC5OIZX2.js} +9 -9
  58. package/dist/{emit-demo-cmd-G2I4SB7A.js → emit-demo-cmd-HWDC3MAK.js} +211 -101
  59. package/dist/{emit-finding-cmd-VM4KIVEM.js → emit-finding-cmd-A7RBLHTN.js} +10 -10
  60. package/dist/{emit-result-cmd-SEKL6HUU.js → emit-result-cmd-2WVVAGST.js} +12 -12
  61. package/dist/{emit-step-cmd-4YAWK4VE.js → emit-step-cmd-KNVHYSXT.js} +10 -10
  62. package/dist/{findings-cmd-RXYIWXY4.js → findings-cmd-ISP3P3UY.js} +10 -10
  63. package/dist/{fleet-readiness-VIX76RNL.js → fleet-readiness-O2WAJJVT.js} +8 -8
  64. package/dist/{governing-source-APGCKDTS.js → governing-source-PMWZJCXJ.js} +13 -13
  65. package/dist/{guest-init-BI7267TB.js → guest-init-3LNAL3TB.js} +2 -2
  66. package/dist/{hook-fast-NVBMSE3N.js → hook-fast-FJ2PMBML.js} +1 -1
  67. package/dist/index.js +4 -4
  68. package/dist/{init-BZMBUTU4.js → init-YRSKJNSB.js} +25 -24
  69. package/dist/{init-VPK3MDM5.js → init-ZXV6LILS.js} +26 -25
  70. package/dist/{init-cmd-PTQ5WSQ5.js → init-cmd-3F436JBW.js} +18 -18
  71. package/dist/{init-update-HOTJISWA.js → init-update-6OPETOBA.js} +17 -17
  72. package/dist/{layout-ZI4RJ6MT.js → layout-JGF7MJHG.js} +4 -4
  73. package/dist/{login-browser-WUSIVD5E.js → login-browser-3RIZQJY2.js} +2 -2
  74. package/dist/{loop-FDFEXDKA.js → loop-MCR3EUSZ.js} +36 -34
  75. package/dist/{machine-ZL72TS6B.js → machine-35YQ7MGN.js} +23 -22
  76. package/dist/{machine-skills-REHDWINX.js → machine-skills-AGERT2HN.js} +4 -4
  77. package/dist/{runner-identity-DSFLFUR2.js → runner-identity-GO762MHZ.js} +4 -4
  78. package/dist/{runner-key-XJ7YSMOF.js → runner-key-BQSR6MK4.js} +25 -24
  79. package/dist/{session-sender-PLQ5NOEW.js → session-sender-ENL3IBVD.js} +13 -13
  80. package/dist/{spec-cmd-NIAQWMLE.js → spec-cmd-SLJT7MRX.js} +10 -10
  81. package/dist/{starter-pack-OESK7UX2.js → starter-pack-UBEC5LTE.js} +5 -5
  82. package/dist/{status-LJ2UBJCE.js → status-GQEAZBUJ.js} +29 -28
  83. package/dist/{sync-cmd-UTESQMDU.js → sync-cmd-Z4BYKM6K.js} +12 -12
  84. package/dist/{watch-4UC4FGI5.js → watch-MBEA6QB4.js} +12 -12
  85. package/dist/{work-claim-cmd-ODYRE44S.js → work-claim-cmd-TLXRPJWO.js} +12 -12
  86. package/dist/{work-cmd-QQDUI3YX.js → work-cmd-DYM67Z3F.js} +10 -10
  87. package/dist/{work-comment-cmd-FIOMDPIZ.js → work-comment-cmd-CRRWP3AH.js} +10 -10
  88. package/dist/{work-logs-cmd-DA6MPQ6O.js → work-logs-cmd-7LFOEVXI.js} +10 -10
  89. package/dist/{work-open-pr-cmd-QG2FT7OW.js → work-open-pr-cmd-XXQ75PSU.js} +11 -11
  90. package/dist/{work-pr-cmd-XNXWWLS5.js → work-pr-cmd-ZVE7EGSC.js} +10 -10
  91. package/dist/{work-stop-cmd-2KLZ2UH2.js → work-stop-cmd-GVFSTGLK.js} +10 -10
  92. package/package.json +1 -1
  93. package/skill-pack/maintained/outerlayer-evidence/SKILL.md +8 -5
  94. package/dist/{chunk-RJYKTWUP.js → chunk-ELYHDWCC.js} +1 -1
@@ -1,22 +1,272 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { parseSize } from './chunk-YJLHUKYS.js';
4
3
  import { RecipeError } from './chunk-3Z3MPR55.js';
5
4
  import { BUILDKIT_IMAGE } from './chunk-R6QCSHKC.js';
6
- import { compareVersions } from './chunk-AKR32WHV.js';
5
+ import { parseSize } from './chunk-YJLHUKYS.js';
6
+ import { compareVersions } from './chunk-5DNCFOXA.js';
7
7
  import { ensureHostKey } from './chunk-JT3YO5MH.js';
8
8
  import { RUNNER_DIR_MODE, RUNNER_FILE_MODE, runnerDir, jobsDir } from './chunk-ESP5VZBD.js';
9
9
  import { CLAUDE_PORT, JOB_MOUNT, GATEWAY_PORT, GATEWAY_SOCKET, CLAUDE_SOCKET, RELAY_PORT, DESTINATION_BASE_PORT } from './chunk-HDSDUTX4.js';
10
10
  import { JOIN_DIR, RELAY_ID, JOIN_SOCKET, TARGET_GATEWAY, TARGET_CLAUDE, destinationTarget, RELAY_USER } from './chunk-MESOOLF4.js';
11
+ import { createHash } from 'crypto';
12
+ import { existsSync, mkdirSync, createWriteStream, rmSync, readFileSync, chmodSync, writeFileSync, realpathSync, readdirSync, renameSync } from 'fs';
13
+ import { join, dirname, resolve } from 'path';
11
14
  import { StringDecoder } from 'string_decoder';
12
15
  import { spawn } from 'child_process';
13
- import { existsSync, readFileSync, mkdirSync, createWriteStream, rmSync, chmodSync, writeFileSync, realpathSync, readdirSync, renameSync } from 'fs';
14
- import { dirname, join, resolve } from 'path';
15
- import { createHash } from 'crypto';
16
16
  import { createRequire as createRequire$1 } from 'module';
17
17
  import { fileURLToPath } from 'url';
18
18
 
19
19
  createRequire(import.meta.url);
20
+ var PACKAGE = "@devcontainers/cli";
21
+ function buildRootFromDist(moduleDir = dirname(fileURLToPath(import.meta.url))) {
22
+ try {
23
+ const info = JSON.parse(readFileSync(join(moduleDir, "build-info.json"), "utf8"));
24
+ return typeof info.root === "string" ? info.root : void 0;
25
+ } catch {
26
+ return void 0;
27
+ }
28
+ }
29
+ function resolveDevcontainerCli(opts = {}) {
30
+ const resolve2 = opts.resolve ?? createRequire$1(import.meta.url).resolve;
31
+ try {
32
+ const bin = join(dirname(resolve2(`${PACKAGE}/package.json`)), "devcontainer.js");
33
+ if (existsSync(bin)) return { command: process.execPath, args: [bin] };
34
+ } catch {
35
+ }
36
+ const buildRoot = opts.buildRoot ?? buildRootFromDist();
37
+ const fallback = buildRoot === void 0 ? void 0 : join(buildRoot, "node_modules", PACKAGE);
38
+ if (fallback !== void 0 && existsSync(join(fallback, "devcontainer.js"))) {
39
+ return { command: process.execPath, args: [join(fallback, "devcontainer.js")] };
40
+ }
41
+ throw new RecipeError(
42
+ "devcontainer_cli_missing",
43
+ `the devcontainer CLI is not installed: looked beside this package and in ${fallback ?? "the checkout this build came from (unknown)"}. Run yarn install in that checkout.`
44
+ );
45
+ }
46
+ function devcontainerBuildInvocation(cli, req) {
47
+ return {
48
+ command: cli.command,
49
+ args: [
50
+ ...cli.args,
51
+ "build",
52
+ "--workspace-folder",
53
+ req.workspace,
54
+ "--config",
55
+ req.config,
56
+ "--image-name",
57
+ req.imageName,
58
+ ...Object.entries(req.labels).flatMap(([key, value]) => ["--label", `${key}=${value}`]),
59
+ "--log-format",
60
+ "text",
61
+ // 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.
62
+ ...req.layoutOut === void 0 ? [] : ["--output", `type=oci,dest=${req.layoutOut},tar=false`]
63
+ ]
64
+ };
65
+ }
66
+
67
+ // src/runner/image/docker.ts
68
+ var CHILD_ENVIRONMENT_NAMES = [
69
+ "PATH",
70
+ "HOME",
71
+ "USER",
72
+ "LOGNAME",
73
+ "TMPDIR",
74
+ "LANG",
75
+ "LC_ALL",
76
+ "DOCKER_HOST",
77
+ "DOCKER_CONFIG",
78
+ "DOCKER_CONTEXT",
79
+ "DOCKER_CERT_PATH",
80
+ "DOCKER_TLS_VERIFY",
81
+ "DOCKER_API_VERSION",
82
+ "DOCKER_BUILDKIT",
83
+ // `docker buildx build` fetches registry tokens in the client and hands them to the builder, so a host that reaches
84
+ // registries through a proxy needs it here as well as in the builder.
85
+ "HTTP_PROXY",
86
+ "HTTPS_PROXY",
87
+ "NO_PROXY",
88
+ "http_proxy",
89
+ "https_proxy",
90
+ "no_proxy",
91
+ "XDG_RUNTIME_DIR",
92
+ "XDG_CONFIG_HOME",
93
+ "XDG_DATA_HOME",
94
+ "XDG_CACHE_HOME",
95
+ "XDG_STATE_HOME"
96
+ ];
97
+ function childEnvironment(base) {
98
+ const env = {};
99
+ for (const name of CHILD_ENVIRONMENT_NAMES) {
100
+ const value = base[name];
101
+ if (value !== void 0) env[name] = value;
102
+ }
103
+ return env;
104
+ }
105
+ var spawnRun = (command, args, opts = {}) => new Promise((resolve2) => {
106
+ let log;
107
+ if (opts.logPath !== void 0) {
108
+ mkdirSync(dirname(opts.logPath), { recursive: true });
109
+ log = createWriteStream(opts.logPath, { flags: "a" });
110
+ }
111
+ const stdoutDecoder = new StringDecoder("utf8");
112
+ const stderrDecoder = new StringDecoder("utf8");
113
+ let stdout = "";
114
+ let stderr = "";
115
+ let settled = false;
116
+ const finish = (status, extra = "") => {
117
+ if (settled) return;
118
+ settled = true;
119
+ const result = { status, stdout: stdout + stdoutDecoder.end(), stderr: stderr + stderrDecoder.end() + extra };
120
+ if (log === void 0) {
121
+ resolve2(result);
122
+ return;
123
+ }
124
+ if (extra) log.write(extra);
125
+ log.end(() => resolve2(result));
126
+ };
127
+ let timer;
128
+ const child = spawn(command, args, {
129
+ env: { ...childEnvironment(process.env), ...opts.env },
130
+ stdio: [opts.input === void 0 ? "ignore" : "pipe", "pipe", "pipe"]
131
+ });
132
+ child.stdout.on("data", (chunk) => {
133
+ stdout += stdoutDecoder.write(chunk);
134
+ log?.write(chunk);
135
+ });
136
+ child.stderr.on("data", (chunk) => {
137
+ stderr += stderrDecoder.write(chunk);
138
+ log?.write(chunk);
139
+ });
140
+ if (opts.timeoutMs !== void 0) {
141
+ timer = setTimeout(() => {
142
+ child.kill("SIGKILL");
143
+ finish(124, `${command}: no answer within ${Math.round(opts.timeoutMs / 1e3)}s
144
+ `);
145
+ }, opts.timeoutMs);
146
+ timer.unref();
147
+ }
148
+ child.on("error", (err) => finish(127, `${command}: ${err.message}
149
+ `));
150
+ child.on("close", (code, signal) => {
151
+ if (timer !== void 0) clearTimeout(timer);
152
+ finish(code ?? (signal ? 128 : 1));
153
+ });
154
+ if (opts.input !== void 0) {
155
+ child.stdin.on("error", () => void 0);
156
+ child.stdin.end(opts.input);
157
+ }
158
+ });
159
+ function toInfo(row) {
160
+ return { id: row.Id, createdAt: row.Created, labels: row.Config?.Labels ?? {} };
161
+ }
162
+ var lines = (text) => [...new Set(text.split("\n").map((l) => l.trim()).filter(Boolean))];
163
+ function layoutDigest(layout) {
164
+ const index = JSON.parse(readFileSync(join(layout, "index.json"), "utf8"));
165
+ const digest = index.manifests?.[0]?.digest;
166
+ if (digest === void 0) throw new Error(`${join(layout, "index.json")} lists no image`);
167
+ return digest;
168
+ }
169
+ function outOfMemory(builder, logPath) {
170
+ return new RecipeError(
171
+ "image_build_out_of_memory",
172
+ `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}`,
173
+ logPath
174
+ );
175
+ }
176
+ function createDockerHost(deps = {}) {
177
+ const run = deps.run ?? spawnRun;
178
+ const cli = deps.cli ?? resolveDevcontainerCli;
179
+ const builderFor = () => {
180
+ if (deps.builder === void 0) {
181
+ 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");
182
+ }
183
+ return deps.builder;
184
+ };
185
+ const inspectMany = async (refs) => {
186
+ const result = await run("docker", ["image", "inspect", ...refs]);
187
+ return result.status === 0 ? JSON.parse(result.stdout).map(toInfo) : [];
188
+ };
189
+ return {
190
+ async inspect(ref) {
191
+ return (await inspectMany([ref]))[0] ?? null;
192
+ },
193
+ async list(repository) {
194
+ const ids = await run("docker", [
195
+ "image",
196
+ "ls",
197
+ "--all",
198
+ "--no-trunc",
199
+ "--quiet",
200
+ "--filter",
201
+ `label=ai.outerlayer.repository=${repository}`
202
+ ]);
203
+ const found = lines(ids.stdout);
204
+ return found.length === 0 ? [] : inspectMany(found);
205
+ },
206
+ async inUse() {
207
+ const containers = lines((await run("docker", ["ps", "--all", "--no-trunc", "--quiet"])).stdout);
208
+ if (containers.length === 0) return [];
209
+ return lines((await run("docker", ["inspect", "--format", "{{.Image}}", ...containers])).stdout);
210
+ },
211
+ async ensureBuilder() {
212
+ const builder = builderFor();
213
+ const result = await ensureBuilder(run, builder, { waitForIdle: true, replaceStale: deps.replaceStaleBuilder });
214
+ if (!result.ok) throw new RecipeError("image_builder_unavailable", `the image builder is unavailable: ${result.problem}`);
215
+ return { name: builder.name, memory: builder.memory };
216
+ },
217
+ async exportLayout(ref, dir) {
218
+ rmSync(dir, { recursive: true, force: true });
219
+ mkdirSync(dir, { recursive: true });
220
+ const archive = join(dir, ".image.tar");
221
+ const saved = await run("docker", ["save", "--output", archive, ref]);
222
+ if (saved.status !== 0) throw new Error(saved.stderr.trim() || `docker save ${ref} exited ${saved.status}`);
223
+ const unpacked = await run("tar", ["-xf", archive, "-C", dir]);
224
+ rmSync(archive, { force: true });
225
+ if (unpacked.status !== 0) throw new Error(unpacked.stderr.trim() || `tar exited ${unpacked.status}`);
226
+ },
227
+ async buildDockerfile(req) {
228
+ const builder = builderFor();
229
+ if (req.layoutOut !== void 0) {
230
+ rmSync(req.layoutOut, { recursive: true, force: true });
231
+ }
232
+ const labels = Object.entries(req.labels).flatMap(([key, value]) => ["--label", `${key}=${value}`]);
233
+ const args = [
234
+ "buildx",
235
+ "build",
236
+ "--builder",
237
+ builder.name,
238
+ "--load",
239
+ ...req.layoutOut === void 0 ? [] : ["--output", `type=oci,dest=${req.layoutOut},tar=false`],
240
+ ...req.base === void 0 ? [] : ["--build-context", `${req.base.ref}=oci-layout://${req.base.layout}@${layoutDigest(req.base.layout)}`],
241
+ "--tag",
242
+ req.tag,
243
+ ...labels,
244
+ "--file",
245
+ "-",
246
+ req.context
247
+ ];
248
+ const result = await trackImageBuild(() => run("docker", args, { logPath: req.logPath, input: req.dockerfile }));
249
+ if (result.status !== 0 && isOutOfMemory(`${result.stdout}
250
+ ${result.stderr}`)) throw outOfMemory(builder, req.logPath);
251
+ return result.status;
252
+ },
253
+ async devcontainerBuild(req) {
254
+ const builder = builderFor();
255
+ const { command, args } = devcontainerBuildInvocation(cli(), req);
256
+ if (req.layoutOut !== void 0) {
257
+ rmSync(req.layoutOut, { recursive: true, force: true });
258
+ }
259
+ const result = await trackImageBuild(() => run(command, args, { logPath: req.logPath, env: { BUILDX_BUILDER: builder.name } }));
260
+ if (result.status !== 0 && isOutOfMemory(`${result.stdout}
261
+ ${result.stderr}`)) throw outOfMemory(builder, req.logPath);
262
+ return result.status;
263
+ },
264
+ async remove(id) {
265
+ const result = await run("docker", ["rmi", id]);
266
+ if (result.status !== 0) throw new Error(result.stderr.trim() || `docker rmi ${id} exited ${result.status}`);
267
+ }
268
+ };
269
+ }
20
270
  var ITEM_KEY_FILE = "item-key";
21
271
  function itemKeyPath(jobPath) {
22
272
  return join(dirname(jobPath), ITEM_KEY_FILE);
@@ -481,255 +731,5 @@ function ensureBuilder(rawRun, spec, options = {}) {
481
731
  }
482
732
  );
483
733
  }
484
- var PACKAGE = "@devcontainers/cli";
485
- function buildRootFromDist(moduleDir = dirname(fileURLToPath(import.meta.url))) {
486
- try {
487
- const info = JSON.parse(readFileSync(join(moduleDir, "build-info.json"), "utf8"));
488
- return typeof info.root === "string" ? info.root : void 0;
489
- } catch {
490
- return void 0;
491
- }
492
- }
493
- function resolveDevcontainerCli(opts = {}) {
494
- const resolve2 = opts.resolve ?? createRequire$1(import.meta.url).resolve;
495
- try {
496
- const bin = join(dirname(resolve2(`${PACKAGE}/package.json`)), "devcontainer.js");
497
- if (existsSync(bin)) return { command: process.execPath, args: [bin] };
498
- } catch {
499
- }
500
- const buildRoot = opts.buildRoot ?? buildRootFromDist();
501
- const fallback = buildRoot === void 0 ? void 0 : join(buildRoot, "node_modules", PACKAGE);
502
- if (fallback !== void 0 && existsSync(join(fallback, "devcontainer.js"))) {
503
- return { command: process.execPath, args: [join(fallback, "devcontainer.js")] };
504
- }
505
- throw new RecipeError(
506
- "devcontainer_cli_missing",
507
- `the devcontainer CLI is not installed: looked beside this package and in ${fallback ?? "the checkout this build came from (unknown)"}. Run yarn install in that checkout.`
508
- );
509
- }
510
- function devcontainerBuildInvocation(cli, req) {
511
- return {
512
- command: cli.command,
513
- args: [
514
- ...cli.args,
515
- "build",
516
- "--workspace-folder",
517
- req.workspace,
518
- "--config",
519
- req.config,
520
- "--image-name",
521
- req.imageName,
522
- ...Object.entries(req.labels).flatMap(([key, value]) => ["--label", `${key}=${value}`]),
523
- "--log-format",
524
- "text",
525
- // 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.
526
- ...req.layoutOut === void 0 ? [] : ["--output", `type=oci,dest=${req.layoutOut},tar=false`]
527
- ]
528
- };
529
- }
530
-
531
- // src/runner/image/docker.ts
532
- var CHILD_ENVIRONMENT_NAMES = [
533
- "PATH",
534
- "HOME",
535
- "USER",
536
- "LOGNAME",
537
- "TMPDIR",
538
- "LANG",
539
- "LC_ALL",
540
- "DOCKER_HOST",
541
- "DOCKER_CONFIG",
542
- "DOCKER_CONTEXT",
543
- "DOCKER_CERT_PATH",
544
- "DOCKER_TLS_VERIFY",
545
- "DOCKER_API_VERSION",
546
- "DOCKER_BUILDKIT",
547
- // `docker buildx build` fetches registry tokens in the client and hands them to the builder, so a host that reaches
548
- // registries through a proxy needs it here as well as in the builder.
549
- "HTTP_PROXY",
550
- "HTTPS_PROXY",
551
- "NO_PROXY",
552
- "http_proxy",
553
- "https_proxy",
554
- "no_proxy",
555
- "XDG_RUNTIME_DIR",
556
- "XDG_CONFIG_HOME",
557
- "XDG_DATA_HOME",
558
- "XDG_CACHE_HOME",
559
- "XDG_STATE_HOME"
560
- ];
561
- function childEnvironment(base) {
562
- const env = {};
563
- for (const name of CHILD_ENVIRONMENT_NAMES) {
564
- const value = base[name];
565
- if (value !== void 0) env[name] = value;
566
- }
567
- return env;
568
- }
569
- var spawnRun = (command, args, opts = {}) => new Promise((resolve2) => {
570
- let log;
571
- if (opts.logPath !== void 0) {
572
- mkdirSync(dirname(opts.logPath), { recursive: true });
573
- log = createWriteStream(opts.logPath, { flags: "a" });
574
- }
575
- const stdoutDecoder = new StringDecoder("utf8");
576
- const stderrDecoder = new StringDecoder("utf8");
577
- let stdout = "";
578
- let stderr = "";
579
- let settled = false;
580
- const finish = (status, extra = "") => {
581
- if (settled) return;
582
- settled = true;
583
- const result = { status, stdout: stdout + stdoutDecoder.end(), stderr: stderr + stderrDecoder.end() + extra };
584
- if (log === void 0) {
585
- resolve2(result);
586
- return;
587
- }
588
- if (extra) log.write(extra);
589
- log.end(() => resolve2(result));
590
- };
591
- let timer;
592
- const child = spawn(command, args, {
593
- env: { ...childEnvironment(process.env), ...opts.env },
594
- stdio: [opts.input === void 0 ? "ignore" : "pipe", "pipe", "pipe"]
595
- });
596
- child.stdout.on("data", (chunk) => {
597
- stdout += stdoutDecoder.write(chunk);
598
- log?.write(chunk);
599
- });
600
- child.stderr.on("data", (chunk) => {
601
- stderr += stderrDecoder.write(chunk);
602
- log?.write(chunk);
603
- });
604
- if (opts.timeoutMs !== void 0) {
605
- timer = setTimeout(() => {
606
- child.kill("SIGKILL");
607
- finish(124, `${command}: no answer within ${Math.round(opts.timeoutMs / 1e3)}s
608
- `);
609
- }, opts.timeoutMs);
610
- timer.unref();
611
- }
612
- child.on("error", (err) => finish(127, `${command}: ${err.message}
613
- `));
614
- child.on("close", (code, signal) => {
615
- if (timer !== void 0) clearTimeout(timer);
616
- finish(code ?? (signal ? 128 : 1));
617
- });
618
- if (opts.input !== void 0) {
619
- child.stdin.on("error", () => void 0);
620
- child.stdin.end(opts.input);
621
- }
622
- });
623
- function toInfo(row) {
624
- return { id: row.Id, createdAt: row.Created, labels: row.Config?.Labels ?? {} };
625
- }
626
- var lines = (text) => [...new Set(text.split("\n").map((l) => l.trim()).filter(Boolean))];
627
- function layoutDigest(layout) {
628
- const index = JSON.parse(readFileSync(join(layout, "index.json"), "utf8"));
629
- const digest = index.manifests?.[0]?.digest;
630
- if (digest === void 0) throw new Error(`${join(layout, "index.json")} lists no image`);
631
- return digest;
632
- }
633
- function outOfMemory(builder, logPath) {
634
- return new RecipeError(
635
- "image_build_out_of_memory",
636
- `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}`,
637
- logPath
638
- );
639
- }
640
- function createDockerHost(deps = {}) {
641
- const run = deps.run ?? spawnRun;
642
- const cli = deps.cli ?? resolveDevcontainerCli;
643
- const builderFor = () => {
644
- if (deps.builder === void 0) {
645
- 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");
646
- }
647
- return deps.builder;
648
- };
649
- const inspectMany = async (refs) => {
650
- const result = await run("docker", ["image", "inspect", ...refs]);
651
- return result.status === 0 ? JSON.parse(result.stdout).map(toInfo) : [];
652
- };
653
- return {
654
- async inspect(ref) {
655
- return (await inspectMany([ref]))[0] ?? null;
656
- },
657
- async list(repository) {
658
- const ids = await run("docker", [
659
- "image",
660
- "ls",
661
- "--all",
662
- "--no-trunc",
663
- "--quiet",
664
- "--filter",
665
- `label=ai.outerlayer.repository=${repository}`
666
- ]);
667
- const found = lines(ids.stdout);
668
- return found.length === 0 ? [] : inspectMany(found);
669
- },
670
- async inUse() {
671
- const containers = lines((await run("docker", ["ps", "--all", "--no-trunc", "--quiet"])).stdout);
672
- if (containers.length === 0) return [];
673
- return lines((await run("docker", ["inspect", "--format", "{{.Image}}", ...containers])).stdout);
674
- },
675
- async ensureBuilder() {
676
- const builder = builderFor();
677
- const result = await ensureBuilder(run, builder, { waitForIdle: true, replaceStale: deps.replaceStaleBuilder });
678
- if (!result.ok) throw new RecipeError("image_builder_unavailable", `the image builder is unavailable: ${result.problem}`);
679
- return { name: builder.name, memory: builder.memory };
680
- },
681
- async exportLayout(ref, dir) {
682
- rmSync(dir, { recursive: true, force: true });
683
- mkdirSync(dir, { recursive: true });
684
- const archive = join(dir, ".image.tar");
685
- const saved = await run("docker", ["save", "--output", archive, ref]);
686
- if (saved.status !== 0) throw new Error(saved.stderr.trim() || `docker save ${ref} exited ${saved.status}`);
687
- const unpacked = await run("tar", ["-xf", archive, "-C", dir]);
688
- rmSync(archive, { force: true });
689
- if (unpacked.status !== 0) throw new Error(unpacked.stderr.trim() || `tar exited ${unpacked.status}`);
690
- },
691
- async buildDockerfile(req) {
692
- const builder = builderFor();
693
- if (req.layoutOut !== void 0) {
694
- rmSync(req.layoutOut, { recursive: true, force: true });
695
- }
696
- const labels = Object.entries(req.labels).flatMap(([key, value]) => ["--label", `${key}=${value}`]);
697
- const args = [
698
- "buildx",
699
- "build",
700
- "--builder",
701
- builder.name,
702
- "--load",
703
- ...req.layoutOut === void 0 ? [] : ["--output", `type=oci,dest=${req.layoutOut},tar=false`],
704
- ...req.base === void 0 ? [] : ["--build-context", `${req.base.ref}=oci-layout://${req.base.layout}@${layoutDigest(req.base.layout)}`],
705
- "--tag",
706
- req.tag,
707
- ...labels,
708
- "--file",
709
- "-",
710
- req.context
711
- ];
712
- const result = await trackImageBuild(() => run("docker", args, { logPath: req.logPath, input: req.dockerfile }));
713
- if (result.status !== 0 && isOutOfMemory(`${result.stdout}
714
- ${result.stderr}`)) throw outOfMemory(builder, req.logPath);
715
- return result.status;
716
- },
717
- async devcontainerBuild(req) {
718
- const builder = builderFor();
719
- const { command, args } = devcontainerBuildInvocation(cli(), req);
720
- if (req.layoutOut !== void 0) {
721
- rmSync(req.layoutOut, { recursive: true, force: true });
722
- }
723
- const result = await trackImageBuild(() => run(command, args, { logPath: req.logPath, env: { BUILDX_BUILDER: builder.name } }));
724
- if (result.status !== 0 && isOutOfMemory(`${result.stdout}
725
- ${result.stderr}`)) throw outOfMemory(builder, req.logPath);
726
- return result.status;
727
- },
728
- async remove(id) {
729
- const result = await run("docker", ["rmi", id]);
730
- if (result.status !== 0) throw new Error(result.stderr.trim() || `docker rmi ${id} exited ${result.status}`);
731
- }
732
- };
733
- }
734
734
 
735
735
  export { BUILD_LABEL, COMMAND_DIR, HASH_ARGV, JUDGE_DIR, JUDGE_ITEMS, JUDGE_MAX_TURNS, JUDGE_PROGRAM, JUDGE_REPORT, MAX_ITEMS_BYTES, MAX_REPORT_BYTES, MIN_BUILDX_VERSION, RUNNER_LABEL, builderName, builderNameFor, builderSpec, buildxState, childEnvironment, containerExecArgs, containerRunArgs, createDockerHost, dockerIdentity, ensureBuilder, ensureFailureCount, ensureRunnerIdentity, isOutOfMemory, judgeCommand, parseProgramHash, pathLabelValue, prepareRunArgs, proxyEnvironment, readJobFile, readJobFileChecked, readRunnerIdentity, resolveDevcontainerCli, runnerLabelValue, spawnRun, trackImageBuild, withAnswerProtocol, writeJobFile };
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
3
  import { launchRefusalForSession } from './chunk-ESVW4MJY.js';
4
- import { autoConnect, detectActiveSession } from './chunk-6TFTRVOA.js';
5
- import { acquireSpoolLockAt } from './chunk-DM4EGXDO.js';
6
- import { resolveRepoIdentity } from './chunk-AKR32WHV.js';
4
+ import { autoConnect, detectActiveSession } from './chunk-C3XLVHN6.js';
5
+ import { acquireSpoolLockAt } from './chunk-EWVYQLD3.js';
6
+ import { resolveRepoIdentity } from './chunk-5DNCFOXA.js';
7
7
  import { C } from './chunk-ANPNT6PM.js';
8
8
  import { resolveGatewayCredentials, defaultFetch, unauthorizedMessage } from './chunk-VQ2JGZSC.js';
9
9
  import { launchedItemForSession } from './chunk-T2Q7ISPE.js';
10
10
  import { parseTrackerNumber, trackerNumberError } from './chunk-WZBHBH3J.js';
11
- import { StepNameSchema, StepBodySchema } from './chunk-AKHGQKNR.js';
11
+ import { StepNameSchema, StepBodySchema } from './chunk-E6CO3MJE.js';
12
12
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
13
13
  import { randomUUID } from 'crypto';
14
14
  import { readFileSync, existsSync, mkdirSync, writeFileSync, renameSync, appendFileSync } from 'fs';
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { skillDir, FORMER_MAINTAINED_NAMES, isMaintainedCopy } from './chunk-KUTZ6XLS.js';
3
+ import { skillDir, FORMER_MAINTAINED_NAMES, isMaintainedCopy } from './chunk-G63KT5I5.js';
4
4
  import { cliInvocation } from './chunk-CRB3POP4.js';
5
- import { emitTree, ALL_TARGET_IDS, classifyTree } from './chunk-OGCG5LOX.js';
5
+ import { emitTree, ALL_TARGET_IDS, classifyTree } from './chunk-LJG6EMLJ.js';
6
6
  import { readFileSync, existsSync, unlinkSync, rmdirSync, readdirSync } from 'fs';
7
7
  import { join, dirname, relative, sep } from 'path';
8
8
 
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'node:module';
3
- import { staleBuildRefusal, staleBuildWarning, detectCi } from './chunk-SFJD4MRY.js';
3
+ import { staleBuildRefusal, staleBuildWarning, detectCi } from './chunk-WHRR55PC.js';
4
4
  import { launchRefusalForSession } from './chunk-ESVW4MJY.js';
5
- import { detectActiveSession, autoConnect } from './chunk-6TFTRVOA.js';
6
- import { readEffectiveArtifactSpoolState, localArtifactIds, isArtifactTombstoned, artifactBlobsDir, appendArtifactRecord, artifactsSpoolPath, findPendingArtifactRecord, sanitizeTerminal, appendArtifactTombstone } from './chunk-DM4EGXDO.js';
7
- import { resolveRepoIdentity } from './chunk-AKR32WHV.js';
5
+ import { detectActiveSession, autoConnect } from './chunk-C3XLVHN6.js';
6
+ import { readEffectiveArtifactSpoolState, localArtifactIds, isArtifactTombstoned, artifactBlobsDir, appendArtifactRecord, artifactsSpoolPath, findPendingArtifactRecord, sanitizeTerminal, appendArtifactTombstone } from './chunk-EWVYQLD3.js';
7
+ import { resolveRepoIdentity } from './chunk-5DNCFOXA.js';
8
8
  import { C } from './chunk-ANPNT6PM.js';
9
9
  import { resolveGatewayCredentials, defaultFetch, unauthorizedMessage } from './chunk-VQ2JGZSC.js';
10
10
  import { parseTrackerNumber, trackerNumberError } from './chunk-WZBHBH3J.js';
11
11
  import { cliInvocation } from './chunk-CRB3POP4.js';
12
- import { ARTIFACT_MAX_CAPTION_LENGTH, ArtifactCriterionIdSchema, ARTIFACT_MAX_BYTES, ARTIFACT_MAX_FILENAME_LENGTH, mediaTypeForArtifactPath, inferArtifactKind, ARTIFACT_MAX_REPLACES_TARGETS, parseTestSelector, parseJunit, bindTests } from './chunk-AKHGQKNR.js';
12
+ import { ARTIFACT_MAX_CAPTION_LENGTH, ArtifactCriterionIdSchema, ARTIFACT_MAX_BYTES, ARTIFACT_MAX_FILENAME_LENGTH, mediaTypeForArtifactPath, inferArtifactKind, ARTIFACT_MAX_REPLACES_TARGETS, parseTestSelector, parseJunit, bindTests } from './chunk-E6CO3MJE.js';
13
13
  import { homeFromEnv } from './chunk-VNVZDWO3.js';
14
14
  import { createHash, randomUUID } from 'crypto';
15
15
  import { statSync, readFileSync, mkdirSync, existsSync, writeFileSync, renameSync, unlinkSync } from 'fs';
@@ -116,6 +116,14 @@ function checkTestResults(params) {
116
116
  }
117
117
  return selection.length > 0 ? selection : void 0;
118
118
  }
119
+ async function refusalCode(response) {
120
+ try {
121
+ const body = await response.clone().json();
122
+ return typeof body.error?.code === "string" ? body.error.code : void 0;
123
+ } catch {
124
+ return void 0;
125
+ }
126
+ }
119
127
  async function runEmitArtifact(opts) {
120
128
  const env = opts.env ?? process.env;
121
129
  const refusal = staleBuildRefusal(env);
@@ -178,7 +186,7 @@ async function runEmitArtifact(opts) {
178
186
  `artifact exceeds 8 MiB (${(bytes.length / (1024 * 1024)).toFixed(1)} MiB) \u2014 the gateway refuses larger uploads`
179
187
  );
180
188
  }
181
- const filename = basename(filePath);
189
+ const filename = opts.filename ?? basename(filePath);
182
190
  if (filename.length > ARTIFACT_MAX_FILENAME_LENGTH) {
183
191
  throw new EmitArtifactError(
184
192
  `filename is ${filename.length} characters \u2014 the cap is ${ARTIFACT_MAX_FILENAME_LENGTH}`
@@ -216,6 +224,9 @@ async function runEmitArtifact(opts) {
216
224
  }
217
225
  const mediaType = opts.mediaType ?? mediaTypeForArtifactPath(filePath);
218
226
  const kind = inferArtifactKind(mediaType);
227
+ if (opts.range !== void 0 && kind !== "video") {
228
+ throw new EmitArtifactError(`a range applies to a video, but ${opts.file} is ${kind === "file" ? "not a video" : `a ${kind}`}`);
229
+ }
219
230
  const tests = checkTestResults({
220
231
  file: opts.file,
221
232
  bytes,
@@ -264,7 +275,9 @@ async function runEmitArtifact(opts) {
264
275
  ...criterionId !== void 0 ? { criterionId } : {},
265
276
  ...replacesTargets !== void 0 ? { replaces: replacesTargets[0] } : {},
266
277
  ...replacesTargets !== void 0 && replacesTargets.length > 1 ? { replacesTargets } : {},
267
- ...tests !== void 0 ? { tests } : {}
278
+ ...tests !== void 0 ? { tests } : {},
279
+ ...opts.range !== void 0 ? { range: opts.range } : {},
280
+ ...opts.blobOptional === true ? { blobOptional: true } : {}
268
281
  };
269
282
  try {
270
283
  appendArtifactRecord(record, home);
@@ -331,25 +344,35 @@ async function runEmitArtifact(opts) {
331
344
  ...commitSha !== void 0 ? { commitSha } : {},
332
345
  ...directTargets !== void 0 && directTargets.length > 0 ? { replaces: directTargets[0] } : {},
333
346
  ...directTargets !== void 0 && directTargets.length > 1 ? { replacesTargets: directTargets } : {},
334
- ...tests !== void 0 ? { tests } : {}
347
+ ...tests !== void 0 ? { tests } : {},
348
+ ...opts.range !== void 0 ? { range: opts.range } : {}
335
349
  },
336
350
  blob: { data: bytes.toString("base64") }
337
351
  };
338
352
  const fetchImpl = opts.fetchImpl ?? defaultFetch;
339
353
  const endpoint = new URL("/v1/artifacts", url).toString();
354
+ const post = async (body) => {
355
+ try {
356
+ return await fetchImpl(endpoint, {
357
+ method: "POST",
358
+ headers: {
359
+ "content-type": "application/json",
360
+ authorization: `Bearer ${apiKey}`,
361
+ "x-outerlayer-app-id": appId
362
+ },
363
+ body: JSON.stringify(body)
364
+ });
365
+ } catch (err) {
366
+ throw new EmitArtifactError(`network error reaching ${endpoint}: ${String(err)}`);
367
+ }
368
+ };
340
369
  let response;
341
- try {
342
- response = await fetchImpl(endpoint, {
343
- method: "POST",
344
- headers: {
345
- "content-type": "application/json",
346
- authorization: `Bearer ${apiKey}`,
347
- "x-outerlayer-app-id": appId
348
- },
349
- body: JSON.stringify(request)
350
- });
351
- } catch (err) {
352
- throw new EmitArtifactError(`network error reaching ${endpoint}: ${String(err)}`);
370
+ if (opts.blobOptional === true) {
371
+ const { blob: _blob, ...withoutBlob } = request;
372
+ response = await post(withoutBlob);
373
+ if (response.status === 409 && await refusalCode(response) === "blob_required") response = await post(request);
374
+ } else {
375
+ response = await post(request);
353
376
  }
354
377
  if (response.status === 401) {
355
378
  throw new EmitArtifactError(