@outerlayer/cli 0.8.0 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/README.md +27 -9
- package/dist/{agent-setup-C7PLRXZO.js → agent-setup-C5X4356W.js} +10 -10
- package/dist/{build-MS34XEGN.js → build-3FSJR5OO.js} +1 -1
- package/dist/build-info.json +1 -1
- package/dist/{builder-G52A6GW2.js → builder-QZA2Z3M3.js} +3 -3
- package/dist/{check-FOF3PUKI.js → check-HQHFAOXW.js} +30 -29
- package/dist/{chunk-R7STSBLC.js → chunk-2E2MG3KW.js} +1 -1
- package/dist/{chunk-OD2VTIHN.js → chunk-2FWL7CE2.js} +3 -2
- package/dist/{chunk-K35RW5HP.js → chunk-33GOCSRO.js} +4 -4
- package/dist/{chunk-4A5E2G4E.js → chunk-3J476JZC.js} +11 -11
- package/dist/{chunk-MQ3IPHIZ.js → chunk-47RS42OZ.js} +6 -3
- package/dist/{chunk-3S4P55NE.js → chunk-4ZZR5SKG.js} +3 -3
- package/dist/{chunk-PWBILI5P.js → chunk-7KI224YS.js} +1 -1
- package/dist/{chunk-5TNS3PL7.js → chunk-CLURXEWV.js} +4 -3
- package/dist/{chunk-7ZR5UPMB.js → chunk-CMFCCIQN.js} +167 -1
- package/dist/{chunk-AX23QKHS.js → chunk-CRLAB4PM.js} +1 -1
- package/dist/{chunk-CM5QTKM4.js → chunk-EQG7L6LM.js} +311 -29
- package/dist/{chunk-OEK4JEB3.js → chunk-ERI5GBNI.js} +18 -3
- package/dist/{chunk-ILEA3YHM.js → chunk-EWBM2USM.js} +2 -2
- package/dist/{chunk-EV3M3EH7.js → chunk-G54QHBTI.js} +2 -2
- package/dist/{chunk-M3SQ4YGD.js → chunk-GXSMDL4M.js} +1 -1
- package/dist/{chunk-GAYWY4GI.js → chunk-HN2JBGSI.js} +2 -1
- package/dist/{chunk-ZOAEPWGL.js → chunk-HWMYGAKF.js} +1 -1
- package/dist/chunk-I2UOAV7X.js +133 -0
- package/dist/{chunk-ABIWDUMS.js → chunk-IS4DIGBQ.js} +13 -1
- package/dist/{chunk-WVGSB3Z2.js → chunk-J5DPVNL3.js} +2 -2
- package/dist/{chunk-VXLJORHL.js → chunk-JXH6LEEH.js} +1 -1
- package/dist/{chunk-JPR2WHHF.js → chunk-KI7VPNKC.js} +1 -1
- package/dist/{chunk-TUUMW4TC.js → chunk-LSPJHYHM.js} +1 -1
- package/dist/{chunk-7VNURP6M.js → chunk-M2F2RAMK.js} +82 -26
- package/dist/{chunk-NALVDFIS.js → chunk-MJLUWGUD.js} +2 -2
- package/dist/{chunk-5FWNEQNZ.js → chunk-NACLOOXP.js} +5 -5
- package/dist/{chunk-U3GOI2B4.js → chunk-NPBLDMSD.js} +1 -1
- package/dist/{chunk-BOLTI6LR.js → chunk-PLMTLGYH.js} +1 -1
- package/dist/{chunk-IRCBTGWF.js → chunk-QJPO42VI.js} +6 -6
- package/dist/{chunk-5QLNZGAQ.js → chunk-R5SPFO6F.js} +6 -6
- package/dist/{chunk-M5POMKKW.js → chunk-V7NIVOFD.js} +5 -5
- package/dist/{chunk-IJBVPLZZ.js → chunk-VUGDEUMM.js} +71 -143
- package/dist/{chunk-4ACZCY4I.js → chunk-WMPO3SKK.js} +3 -3
- package/dist/{chunk-TTNFGMHO.js → chunk-Y7UQHKFY.js} +19 -1
- package/dist/{chunk-BCLJSQCV.js → chunk-YO4PSLVB.js} +1 -1
- package/dist/{chunk-AIL2R4SI.js → chunk-YU4Z2O3W.js} +5 -5
- package/dist/{chunk-ZZXLM64C.js → chunk-ZJ3WRVRG.js} +1 -1
- package/dist/{cli-AOJPAVFX.js → cli-OWM54BIU.js} +120 -93
- package/dist/{command-SY3SVLAI.js → command-LIHTWJHQ.js} +31 -25
- package/dist/{config-Z3USDBLU.js → config-OOBPCY7Q.js} +2 -2
- package/dist/{connect-cmd-PNZ6IJLJ.js → connect-cmd-NV7WVBY7.js} +3 -3
- package/dist/{context-adopt-CE4KDXS3.js → context-adopt-PPCNSN5D.js} +7 -7
- package/dist/{context-materialize-QL33HDJN.js → context-materialize-YR3JQCUF.js} +7 -7
- package/dist/{dist-3ZTZF2TP.js → dist-2LNAXGPZ.js} +1 -1
- package/dist/{docker-676FD3CQ.js → docker-RSALMGPL.js} +4 -4
- package/dist/{doctor-WR6TRPSU.js → doctor-PKT42NOJ.js} +59 -25
- package/dist/{emit-artifact-cmd-AVM4YXMQ.js → emit-artifact-cmd-BZYXRBCV.js} +8 -8
- package/dist/{emit-cmd-2QRMYPYO.js → emit-cmd-IRYNFHPM.js} +3 -3
- package/dist/{emit-criteria-cmd-LDBE4YDS.js → emit-criteria-cmd-PSZYZ32B.js} +6 -6
- package/dist/{emit-finding-cmd-6R5WBPCH.js → emit-finding-cmd-VTSYDJYZ.js} +6 -6
- package/dist/{emit-result-cmd-2DMN6O6U.js → emit-result-cmd-5P7ZFWMZ.js} +8 -8
- package/dist/{exec-client-NPYNUAF3.js → exec-client-2UX6NHAO.js} +3 -3
- package/dist/{guest-init-JWNNAH2H.js → guest-init-VHQNFCFS.js} +3 -3
- package/dist/{hook-fast-XBOZ3N6L.js → hook-fast-OCHVQZTU.js} +1 -1
- package/dist/{host-key-KDYZ5ECC.js → host-key-YMLXY6QB.js} +1 -1
- package/dist/{import-capture-cmd-T4556ELW.js → import-capture-cmd-2QFLZQFY.js} +3 -3
- package/dist/{import-ruler-cmd-SG3UVGI7.js → import-ruler-cmd-BD22GUJS.js} +1 -1
- package/dist/index.js +3 -3
- package/dist/{init-R2FJ5KNS.js → init-CY4IMZE4.js} +22 -22
- package/dist/{init-KDK5QLQZ.js → init-TQUN5RF7.js} +20 -20
- package/dist/{init-cmd-BYZYAJ5P.js → init-cmd-F4TZXQJH.js} +11 -11
- package/dist/{install-FHTVJZS6.js → install-C33LT5KQ.js} +3 -3
- package/dist/{install-cmd-DCF7TVXD.js → install-cmd-5HYMXLEW.js} +2 -1
- package/dist/{loop-AG3PLXPO.js → loop-NZP5FAC3.js} +30 -29
- package/dist/{machine-LV6WBRRK.js → machine-RUSNVLKO.js} +19 -19
- package/dist/{mcp-install-cmd-RLK4SO3N.js → mcp-install-cmd-4AQMSIGY.js} +1 -1
- package/dist/{mcp-serve-cmd-N6UD2KBX.js → mcp-serve-cmd-3KVYEUXG.js} +3 -3
- package/dist/{real-deps-SU24ZA2K.js → real-deps-TK6JMQSW.js} +3 -2
- package/dist/{session-sender-Q5HAMOL2.js → session-sender-EECVKXTC.js} +7 -7
- package/dist/{starter-pack-MUXMAU4S.js → starter-pack-VNWPYP5U.js} +3 -3
- package/dist/{status-HH4OSOHR.js → status-KCONQLOD.js} +31 -25
- package/dist/{sync-cmd-CAEPJR7B.js → sync-cmd-R54ZBHXX.js} +6 -6
- package/dist/{watch-LAAZFBHH.js → watch-YTFNBO3S.js} +6 -6
- package/dist/{work-claim-cmd-ARIYZARE.js → work-claim-cmd-HRPJ4VUF.js} +10 -10
- package/dist/{work-cmd-B3FOXZAL.js → work-cmd-W4GQUUBC.js} +7 -7
- package/dist/{work-comment-cmd-O5WGRI6K.js → work-comment-cmd-DDZ4SZ35.js} +7 -7
- package/dist/{work-open-pr-cmd-M6CQW7KW.js → work-open-pr-cmd-GXULDTSC.js} +8 -8
- package/dist/{work-pr-cmd-C4YEGKD6.js → work-pr-cmd-T6SU4TYN.js} +7 -7
- package/package.json +2 -2
- package/skill-pack/maintained/amend/SKILL.md +22 -6
- package/skill-pack/maintained/outerlayer/SKILL.md +12 -2
- package/skill-pack/maintained/outerlayer/references/open-pull-request.md +29 -0
- package/skill-pack/template/build/SKILL.md +3 -2
- package/skill-pack/template/build/references/release.md +11 -2
|
@@ -1,26 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { readDefaultBranchHead, cloneRepository, buildRepositoryImage } from './chunk-
|
|
3
|
+
import { readDefaultBranchHead, cloneRepository, buildRepositoryImage } from './chunk-Y7UQHKFY.js';
|
|
4
4
|
import { startTimeOf, isSameProcess } from './chunk-N5FOE5PS.js';
|
|
5
5
|
import { currentCliBuild } from './chunk-OGFGZQA3.js';
|
|
6
|
-
import { createDockerHost, childEnvironment, spawnRun } from './chunk-
|
|
6
|
+
import { createDockerHost, childEnvironment, spawnRun } from './chunk-NPBLDMSD.js';
|
|
7
7
|
import { RecipeError } from './chunk-QOZKPLVJ.js';
|
|
8
|
-
import { builderSpec, runnerLabelValue, RUNNER_LABEL, BUILD_LABEL, prepareRunArgs, containerRunArgs, containerExecArgs } from './chunk-
|
|
8
|
+
import { builderSpec, runnerLabelValue, RUNNER_LABEL, BUILD_LABEL, prepareRunArgs, containerRunArgs, containerExecArgs } from './chunk-CLURXEWV.js';
|
|
9
9
|
import { CLAUDE_CODE_VERSION, firecrackerArch, MICROVM_ARCHES, DEFAULT_BASE_IMAGE, GUEST_HELPER_SHA256, GUEST_ASSETS_BASE_URL, GUEST_KERNEL_SHA256, FIRECRACKER_BINARY_SHA256, FIRECRACKER_SHA256, FIRECRACKER_VERSION, GUEST_ASSETS_VERSION } from './chunk-CX22S5BA.js';
|
|
10
|
-
import { execCapture } from './chunk-
|
|
11
|
-
import { GUEST_CID } from './chunk-
|
|
12
|
-
import { WorkCommandError, postJson } from './chunk-
|
|
10
|
+
import { execCapture } from './chunk-HWMYGAKF.js';
|
|
11
|
+
import { GUEST_CID } from './chunk-2E2MG3KW.js';
|
|
12
|
+
import { WorkCommandError, postJson } from './chunk-R5SPFO6F.js';
|
|
13
|
+
import { setCustomScrubbers, setLocalIdentity, setRepoRoot, parseTranscript, scrubDeep, scrubText } from './chunk-HN2JBGSI.js';
|
|
13
14
|
import { hostAllowed } from './chunk-UXYLWVTQ.js';
|
|
14
15
|
import { parseDuKilobytes } from './chunk-7RQ73DLO.js';
|
|
15
|
-
import { RELAY_PORT, CHECKOUT_DIR, JOB_MOUNT, claudeCredential, buildEnvironment, startBuildServices, checkEnvironment, AGENT_CREDENTIAL_MISSING } from './chunk-
|
|
16
|
-
import { defaultGitRunner, materializeContext } from './chunk-
|
|
17
|
-
import { readContextManifest, readSourceCache } from './chunk-
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
16
|
+
import { RELAY_PORT, CHECKOUT_DIR, JOB_MOUNT, claudeCredential, buildEnvironment, startBuildServices, checkEnvironment, AGENT_CREDENTIAL_MISSING } from './chunk-2FWL7CE2.js';
|
|
17
|
+
import { defaultGitRunner, materializeContext } from './chunk-NACLOOXP.js';
|
|
18
|
+
import { readContextManifest, readSourceCache } from './chunk-ZJ3WRVRG.js';
|
|
19
|
+
import { orderSessions, extractFacts, sessionsToTimeline } from './chunk-CMFCCIQN.js';
|
|
20
|
+
import { signingFetchFor } from './chunk-YO4PSLVB.js';
|
|
21
|
+
import { downconvertSession } from './chunk-YNJEOGDL.js';
|
|
22
|
+
import { signerFor } from './chunk-V7NIVOFD.js';
|
|
20
23
|
import { rootfsPathFor, diskTemplatesDir, RUNNER_FILE_MODE, stagedContextDir, contextHomeDir, ghConfigDir, runnerDirOfBuild, spoolDir, mirrorDir, buildDir, RUNNER_DIR_MODE, vmAssetsDir } from './chunk-ZM2IMMYN.js';
|
|
21
24
|
import { relative, join, dirname, basename } from 'path';
|
|
22
25
|
import { readFileSync, existsSync, mkdirSync, chmodSync, truncateSync, rmSync, writeFileSync, accessSync, constants, readdirSync, statSync, rmdirSync, renameSync, lstatSync, unlinkSync, openSync, closeSync, mkdtempSync, createWriteStream, createReadStream } from 'fs';
|
|
23
26
|
import { spawnSync, spawn } from 'child_process';
|
|
27
|
+
import { availableParallelism, networkInterfaces } from 'os';
|
|
24
28
|
import { randomBytes, createHash } from 'crypto';
|
|
25
29
|
import { createServer, request } from 'http';
|
|
26
30
|
import { request as request$1 } from 'https';
|
|
@@ -29,7 +33,6 @@ import { pipeline, finished } from 'stream/promises';
|
|
|
29
33
|
import { createGunzip, gunzipSync, constants as constants$1 } from 'zlib';
|
|
30
34
|
import { isIP, connect, createServer as createServer$1 } from 'net';
|
|
31
35
|
import { lookup } from 'dns/promises';
|
|
32
|
-
import { networkInterfaces } from 'os';
|
|
33
36
|
|
|
34
37
|
createRequire(import.meta.url);
|
|
35
38
|
function logStamp(at) {
|
|
@@ -430,7 +433,11 @@ async function prepareBranch(opts) {
|
|
|
430
433
|
throw new BranchPrepareError(`the pull request's branch ${branch} is not on the remote`);
|
|
431
434
|
}
|
|
432
435
|
await mustGit(git2, workdir, `checking out ${branch}`, ["checkout", "--quiet", "-B", branch, start]);
|
|
433
|
-
return {
|
|
436
|
+
return {
|
|
437
|
+
branch,
|
|
438
|
+
head: await mustGit(git2, workdir, "reading the checked-out commit", ["rev-parse", "HEAD"]),
|
|
439
|
+
startCommit: await mustGit(git2, workdir, `reading the commit of ${defaultBranch}`, ["rev-parse", `origin/${defaultBranch}`])
|
|
440
|
+
};
|
|
434
441
|
}
|
|
435
442
|
async function isMerged(git2, workdir, branch, defaultBranch) {
|
|
436
443
|
const result = await git2(workdir, ["merge-base", "--is-ancestor", `origin/${branch}`, `origin/${defaultBranch}`]);
|
|
@@ -469,6 +476,63 @@ function lifecycleSteps(lifecycle) {
|
|
|
469
476
|
function lifecycleFailureReason(step, exitCode) {
|
|
470
477
|
return `lifecycle command ${step.name} (${step.source}) exited ${exitCode}`;
|
|
471
478
|
}
|
|
479
|
+
function parseCpuList(text) {
|
|
480
|
+
const cores = /* @__PURE__ */ new Set();
|
|
481
|
+
for (const part of text.trim().split(",")) {
|
|
482
|
+
const match = /^(\d+)(?:-(\d+))?$/.exec(part.trim());
|
|
483
|
+
if (match === null) return void 0;
|
|
484
|
+
const low = Number(match[1]);
|
|
485
|
+
const high = match[2] === void 0 ? low : Number(match[2]);
|
|
486
|
+
if (high < low) return void 0;
|
|
487
|
+
for (let core = low; core <= high; core++) cores.add(core);
|
|
488
|
+
}
|
|
489
|
+
return [...cores].sort((a, b) => a - b);
|
|
490
|
+
}
|
|
491
|
+
function formatCpuList(cores) {
|
|
492
|
+
const sorted = [...new Set(cores)].sort((a, b) => a - b);
|
|
493
|
+
const parts = [];
|
|
494
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
495
|
+
const start = sorted[i];
|
|
496
|
+
while (sorted[i + 1] === sorted[i] + 1) i++;
|
|
497
|
+
parts.push(start === sorted[i] ? String(start) : `${start}-${sorted[i]}`);
|
|
498
|
+
}
|
|
499
|
+
return parts.join(",");
|
|
500
|
+
}
|
|
501
|
+
function usableCpus(deps = {}) {
|
|
502
|
+
try {
|
|
503
|
+
const status = (deps.readStatus ?? (() => readFileSync("/proc/self/status", "utf8")))();
|
|
504
|
+
const cores = parseCpuList(/^Cpus_allowed_list:\s*(.+)$/m.exec(status)?.[1] ?? "");
|
|
505
|
+
if (cores !== void 0) return cores;
|
|
506
|
+
} catch {
|
|
507
|
+
}
|
|
508
|
+
return Array.from({ length: Math.max(1, (deps.parallelism ?? availableParallelism)()) }, (_unused, core) => core);
|
|
509
|
+
}
|
|
510
|
+
function createCpuAllocator(cores) {
|
|
511
|
+
const usable = [...new Set(cores)].sort((a, b) => a - b);
|
|
512
|
+
const held = /* @__PURE__ */ new Map();
|
|
513
|
+
const holders = (core) => {
|
|
514
|
+
let count = 0;
|
|
515
|
+
for (const set of held.values()) if (set.includes(core)) count++;
|
|
516
|
+
return count;
|
|
517
|
+
};
|
|
518
|
+
return {
|
|
519
|
+
acquire(buildId, cpus) {
|
|
520
|
+
const existing = held.get(buildId);
|
|
521
|
+
if (existing !== void 0) return existing;
|
|
522
|
+
const wanted = Math.min(Math.ceil(cpus), usable.length);
|
|
523
|
+
const ranked = usable.map((core) => ({ core, count: holders(core) })).sort((a, b) => a.count - b.count);
|
|
524
|
+
const chosen = ranked.slice(0, wanted).map(({ core }) => core).sort((a, b) => a - b);
|
|
525
|
+
held.set(buildId, chosen);
|
|
526
|
+
return chosen;
|
|
527
|
+
},
|
|
528
|
+
hold(buildId, set) {
|
|
529
|
+
held.set(buildId, [...set]);
|
|
530
|
+
},
|
|
531
|
+
release(buildId) {
|
|
532
|
+
held.delete(buildId);
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
}
|
|
472
536
|
var AssetError = class extends Error {
|
|
473
537
|
constructor(file, message) {
|
|
474
538
|
super(message);
|
|
@@ -583,7 +647,7 @@ function templateScript() {
|
|
|
583
647
|
].join("\n");
|
|
584
648
|
}
|
|
585
649
|
var ids = () => ({ uid: String(process.getuid?.() ?? 0), gid: String(process.getgid?.() ?? 0) });
|
|
586
|
-
function converterArgs(dest, extra, script) {
|
|
650
|
+
function converterArgs(dest, memoryBytes, extra, script) {
|
|
587
651
|
const { uid, gid } = ids();
|
|
588
652
|
return [
|
|
589
653
|
"run",
|
|
@@ -591,6 +655,10 @@ function converterArgs(dest, extra, script) {
|
|
|
591
655
|
"-i",
|
|
592
656
|
"--network",
|
|
593
657
|
"none",
|
|
658
|
+
"--memory",
|
|
659
|
+
String(memoryBytes),
|
|
660
|
+
"--memory-swap",
|
|
661
|
+
String(memoryBytes),
|
|
594
662
|
"--mount",
|
|
595
663
|
`type=bind,src=${dirname(dest)},dst=/out`,
|
|
596
664
|
"-e",
|
|
@@ -636,18 +704,18 @@ function exportInto(container, converter) {
|
|
|
636
704
|
function createRootfsHost() {
|
|
637
705
|
const env = () => childEnvironment(process.env);
|
|
638
706
|
return {
|
|
639
|
-
async convert({ imageId, dest }) {
|
|
707
|
+
async convert({ imageId, dest, memoryBytes }) {
|
|
640
708
|
const created = await spawnRun("docker", ["create", imageId, "none"], { env: env() });
|
|
641
709
|
if (created.status !== 0) throw new Error(`docker create ${imageId} failed: ${firstLine2(created.stderr)}`);
|
|
642
710
|
const container = created.stdout.trim();
|
|
643
711
|
try {
|
|
644
|
-
await exportInto(container, converterArgs(dest, [], converterScript()));
|
|
712
|
+
await exportInto(container, converterArgs(dest, memoryBytes, [], converterScript()));
|
|
645
713
|
} finally {
|
|
646
714
|
await spawnRun("docker", ["rm", "--force", "--volumes", container], { env: env() });
|
|
647
715
|
}
|
|
648
716
|
},
|
|
649
|
-
async makeTemplate({ bytes, dest }) {
|
|
650
|
-
const made = await spawnRun("docker", converterArgs(dest, ["-e", `BYTES=${bytes}`], templateScript()), { env: env() });
|
|
717
|
+
async makeTemplate({ bytes, dest, memoryBytes }) {
|
|
718
|
+
const made = await spawnRun("docker", converterArgs(dest, memoryBytes, ["-e", `BYTES=${bytes}`], templateScript()), { env: env() });
|
|
651
719
|
if (made.status !== 0) throw new Error(`making the empty build disk failed: ${firstLine2(made.stderr)}`);
|
|
652
720
|
},
|
|
653
721
|
async imageConfig(imageId) {
|
|
@@ -696,14 +764,14 @@ async function ensureRootfs(input) {
|
|
|
696
764
|
const path = rootfsPathFor(input.runnerDir, input.imageId);
|
|
697
765
|
if (existsSync(path)) return path;
|
|
698
766
|
const { uid, gid } = ids();
|
|
699
|
-
await madeAtomically(path, (temp) => input.host.convert({ imageId: input.imageId, dest: temp, uid: Number(uid), gid: Number(gid) }));
|
|
767
|
+
await madeAtomically(path, (temp) => input.host.convert({ imageId: input.imageId, dest: temp, uid: Number(uid), gid: Number(gid), memoryBytes: input.memoryBytes }));
|
|
700
768
|
return path;
|
|
701
769
|
}
|
|
702
770
|
async function createBuildDisk(input) {
|
|
703
771
|
const template = join(diskTemplatesDir(input.runnerDir), `${input.bytes}.ext4`);
|
|
704
772
|
if (!existsSync(template)) {
|
|
705
773
|
const { uid, gid } = ids();
|
|
706
|
-
await madeAtomically(template, (temp) => input.host.makeTemplate({ bytes: input.bytes, dest: temp, uid: Number(uid), gid: Number(gid) }));
|
|
774
|
+
await madeAtomically(template, (temp) => input.host.makeTemplate({ bytes: input.bytes, dest: temp, uid: Number(uid), gid: Number(gid), memoryBytes: input.memoryBytes }));
|
|
707
775
|
}
|
|
708
776
|
mkdirSync(dirname(input.dest), { recursive: true });
|
|
709
777
|
if (input.host.copyTemplate) input.host.copyTemplate(template, input.dest);
|
|
@@ -831,6 +899,7 @@ function adoptionFailureReason(result) {
|
|
|
831
899
|
}
|
|
832
900
|
async function runBuildSteps(input) {
|
|
833
901
|
const { exec, log, tag, repository } = input;
|
|
902
|
+
let startCommit = "";
|
|
834
903
|
const rewrite = await exec(["git", "config", "--global", `url.http://127.0.0.1:${RELAY_PORT}/github.com/.insteadOf`, "https://github.com/"], "/build/work");
|
|
835
904
|
if (rewrite.status !== 0) return { ok: false, reason: `configuring the build's git remote failed (exit ${rewrite.status})` };
|
|
836
905
|
const clone = await exec(["git", "clone", "--filter=blob:none", "--single-branch", `https://github.com/${repository}.git`, CHECKOUT_DIR], "/build/work");
|
|
@@ -847,6 +916,7 @@ async function runBuildSteps(input) {
|
|
|
847
916
|
return { status: ran.status, stdout: ran.stdout.trim(), stderr: ran.stderr.trim() };
|
|
848
917
|
}
|
|
849
918
|
});
|
|
919
|
+
startCommit = prepared.startCommit;
|
|
850
920
|
log.line(`${tag} on ${prepared.branch} at ${prepared.head.slice(0, 8)}`);
|
|
851
921
|
} catch (err) {
|
|
852
922
|
if (err instanceof BranchPrepareError) return { ok: false, reason: err.message };
|
|
@@ -873,7 +943,200 @@ async function runBuildSteps(input) {
|
|
|
873
943
|
}
|
|
874
944
|
if (input.aborted()) return aborted();
|
|
875
945
|
}
|
|
876
|
-
return { ok: true };
|
|
946
|
+
return { ok: true, startCommit };
|
|
947
|
+
}
|
|
948
|
+
var EVAL_INPUT_NAME = "eval-input";
|
|
949
|
+
var TRANSCRIPT_ROOT = "/build/home/.claude/projects";
|
|
950
|
+
var MAX_TRANSCRIPT_BYTES = 7 * 1024 * 1024;
|
|
951
|
+
var MAX_TRANSCRIPTS = 500;
|
|
952
|
+
var MAX_TOTAL_TRANSCRIPT_BYTES = 64 * 1024 * 1024;
|
|
953
|
+
var TRANSCRIPT_COPY_MS = 2 * 60 * 1e3;
|
|
954
|
+
var BUILD_HOME = "/build/home";
|
|
955
|
+
function firstLine4(text) {
|
|
956
|
+
return text.trim().split("\n")[0] ?? "";
|
|
957
|
+
}
|
|
958
|
+
async function copyTranscripts(run, now = Date.now) {
|
|
959
|
+
const deadline = now() + TRANSCRIPT_COPY_MS;
|
|
960
|
+
let listed;
|
|
961
|
+
try {
|
|
962
|
+
listed = await run(["find", TRANSCRIPT_ROOT, "-type", "f", "-name", "*.jsonl", "-print0"]);
|
|
963
|
+
} catch (err) {
|
|
964
|
+
return { ok: false, reason: describeCallFailure(err) };
|
|
965
|
+
}
|
|
966
|
+
if (listed.status !== 0 && !/No such file or directory/.test(listed.stderr)) {
|
|
967
|
+
return { ok: false, reason: `listing the transcripts failed (exit ${listed.status})${firstLine4(listed.stderr) === "" ? "" : `: ${firstLine4(listed.stderr)}`}` };
|
|
968
|
+
}
|
|
969
|
+
const paths = listed.stdout.split("\0").filter((entry) => entry.startsWith(`${TRANSCRIPT_ROOT}/`) && !entry.includes("\n") && !entry.slice(TRANSCRIPT_ROOT.length + 1).split("/").includes("..")).map((entry) => entry.slice(TRANSCRIPT_ROOT.length + 1)).sort();
|
|
970
|
+
const copied = [];
|
|
971
|
+
const missed = [];
|
|
972
|
+
let total = 0;
|
|
973
|
+
for (const [index, path] of paths.entries()) {
|
|
974
|
+
if (index >= MAX_TRANSCRIPTS) {
|
|
975
|
+
missed.push({ path, reason: `the build wrote more than ${MAX_TRANSCRIPTS} transcripts` });
|
|
976
|
+
continue;
|
|
977
|
+
}
|
|
978
|
+
if (now() >= deadline) {
|
|
979
|
+
missed.push({ path, reason: `copying the transcripts took longer than ${TRANSCRIPT_COPY_MS / 1e3} seconds` });
|
|
980
|
+
continue;
|
|
981
|
+
}
|
|
982
|
+
try {
|
|
983
|
+
const read = await run(["head", "-c", String(MAX_TRANSCRIPT_BYTES + 1), `${TRANSCRIPT_ROOT}/${path}`]);
|
|
984
|
+
if (read.status !== 0) missed.push({ path, reason: `reading it failed (exit ${read.status})${firstLine4(read.stderr) === "" ? "" : `: ${firstLine4(read.stderr)}`}` });
|
|
985
|
+
else if (Buffer.byteLength(read.stdout) > MAX_TRANSCRIPT_BYTES) missed.push({ path, reason: `it is larger than ${MAX_TRANSCRIPT_BYTES / (1024 * 1024)} MiB` });
|
|
986
|
+
else if (total + Buffer.byteLength(read.stdout) > MAX_TOTAL_TRANSCRIPT_BYTES) missed.push({ path, reason: `copying it would take the transcripts past ${MAX_TOTAL_TRANSCRIPT_BYTES / (1024 * 1024)} MiB` });
|
|
987
|
+
else {
|
|
988
|
+
total += Buffer.byteLength(read.stdout);
|
|
989
|
+
copied.push({ path, content: read.stdout });
|
|
990
|
+
}
|
|
991
|
+
} catch (err) {
|
|
992
|
+
missed.push({ path, reason: describeCallFailure(err) });
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
return { ok: true, copied, missed };
|
|
996
|
+
}
|
|
997
|
+
function traceIdForSession(sessionId) {
|
|
998
|
+
const stripped = sessionId.replace(/-/g, "").toLowerCase();
|
|
999
|
+
if (/^[0-9a-f]{32}$/.test(stripped)) return stripped;
|
|
1000
|
+
return createHash("sha256").update(sessionId).digest("hex").slice(0, 32);
|
|
1001
|
+
}
|
|
1002
|
+
function sessionOptionsOf(path) {
|
|
1003
|
+
const segments = path.split("/");
|
|
1004
|
+
const stem = (segments.at(-1) ?? path).replace(/\.jsonl$/, "");
|
|
1005
|
+
const at = segments.lastIndexOf("subagents");
|
|
1006
|
+
if (at <= 0) return { fallbackId: stem };
|
|
1007
|
+
const parent = segments[at - 1];
|
|
1008
|
+
return {
|
|
1009
|
+
fallbackId: stem,
|
|
1010
|
+
isSubagent: true,
|
|
1011
|
+
...parent ? { parentSessionId: parent } : {},
|
|
1012
|
+
ownId: stem,
|
|
1013
|
+
...segments[at + 1] === "workflows" && segments[at + 2] ? { workflowRunId: segments[at + 2] } : {}
|
|
1014
|
+
};
|
|
1015
|
+
}
|
|
1016
|
+
function scrubbing(scrub, author, work) {
|
|
1017
|
+
setCustomScrubbers(scrub, () => void 0);
|
|
1018
|
+
setLocalIdentity({ home: BUILD_HOME, ...author?.name === void 0 ? {} : { name: author.name }, ...author?.email === void 0 ? {} : { email: author.email } });
|
|
1019
|
+
setRepoRoot(CHECKOUT_DIR);
|
|
1020
|
+
try {
|
|
1021
|
+
return work();
|
|
1022
|
+
} finally {
|
|
1023
|
+
setCustomScrubbers(void 0, () => void 0);
|
|
1024
|
+
setLocalIdentity({});
|
|
1025
|
+
setRepoRoot(void 0);
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
function scrubLine(line) {
|
|
1029
|
+
try {
|
|
1030
|
+
return JSON.stringify(scrubDeep(JSON.parse(line)));
|
|
1031
|
+
} catch {
|
|
1032
|
+
return scrubText(line);
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
function writeReadOnly(path, text) {
|
|
1036
|
+
writeFileSync(path, text);
|
|
1037
|
+
chmodSync(path, 292);
|
|
1038
|
+
}
|
|
1039
|
+
function diffBase(job) {
|
|
1040
|
+
const recorded = (job.container ?? job.microvm)?.startCommit;
|
|
1041
|
+
if (recorded !== void 0 && recorded !== "") return { commit: recorded, source: "build" };
|
|
1042
|
+
const recipe = job.environment?.recipe?.sourceCommit;
|
|
1043
|
+
return recipe === void 0 || recipe === "" ? void 0 : { commit: recipe, source: "recipe" };
|
|
1044
|
+
}
|
|
1045
|
+
async function writeEvalInput(request) {
|
|
1046
|
+
const { job, dir, log } = request;
|
|
1047
|
+
const tag = `#${job.item}`;
|
|
1048
|
+
rmSync(dir, { recursive: true, force: true });
|
|
1049
|
+
mkdirSync(join(dir, "sessions"), { recursive: true });
|
|
1050
|
+
chmodSync(dir, 493);
|
|
1051
|
+
chmodSync(join(dir, "sessions"), 493);
|
|
1052
|
+
let workItem;
|
|
1053
|
+
try {
|
|
1054
|
+
const data = await request.readWorkItem();
|
|
1055
|
+
writeReadOnly(join(dir, "work-item.json"), `${JSON.stringify(data, null, 2)}
|
|
1056
|
+
`);
|
|
1057
|
+
workItem = { status: "written" };
|
|
1058
|
+
} catch (err) {
|
|
1059
|
+
workItem = { status: "unavailable", reason: describeCallFailure(err) };
|
|
1060
|
+
log.error(`${tag} the work item could not be read for the checks' input: ${workItem.reason}`);
|
|
1061
|
+
}
|
|
1062
|
+
const patch = join(dir, "diff.patch");
|
|
1063
|
+
const base = diffBase(job);
|
|
1064
|
+
let diff;
|
|
1065
|
+
if (base === void 0) {
|
|
1066
|
+
diff = { status: "unavailable", reason: "the build recorded no commit it started from" };
|
|
1067
|
+
} else {
|
|
1068
|
+
const fetched = await request.fetchDiff({ remote: request.remote, dir: join(request.scratch, "diff"), base: base.commit, head: request.branchHead, token: request.readToken, output: patch });
|
|
1069
|
+
diff = fetched.ok ? { status: "written", base: base.commit, head: request.branchHead, baseSource: base.source } : { status: "unavailable", base: base.commit, head: request.branchHead, baseSource: base.source, reason: fetched.reason };
|
|
1070
|
+
if (!fetched.ok) log.error(`${tag} the diff could not be read for the checks' input: ${fetched.reason}`);
|
|
1071
|
+
}
|
|
1072
|
+
if (diff.status === "unavailable") writeFileSync(patch, "");
|
|
1073
|
+
chmodSync(patch, 292);
|
|
1074
|
+
const sessions = [];
|
|
1075
|
+
const parsed = [];
|
|
1076
|
+
const copiedByTrace = /* @__PURE__ */ new Map();
|
|
1077
|
+
let sessionsUnavailable;
|
|
1078
|
+
if (!request.transcripts.ok) {
|
|
1079
|
+
sessionsUnavailable = request.transcripts.reason;
|
|
1080
|
+
log.error(`${tag} the sessions could not be copied for the checks' input: ${sessionsUnavailable}`);
|
|
1081
|
+
} else {
|
|
1082
|
+
const { copied, missed } = request.transcripts;
|
|
1083
|
+
scrubbing(request.scrub, request.job.commitIdentity?.author, () => {
|
|
1084
|
+
for (const transcript of copied) {
|
|
1085
|
+
const options = sessionOptionsOf(transcript.path);
|
|
1086
|
+
const subagent = options.isSubagent === true;
|
|
1087
|
+
const stem = options.fallbackId ?? transcript.path;
|
|
1088
|
+
let session = null;
|
|
1089
|
+
try {
|
|
1090
|
+
session = parseTranscript(transcript.content, options).session;
|
|
1091
|
+
} catch {
|
|
1092
|
+
}
|
|
1093
|
+
const traceId = traceIdForSession(session?.id ?? stem);
|
|
1094
|
+
if (session === null) {
|
|
1095
|
+
sessions.push({ traceId, subagent, status: "missing", reason: "the transcript holds no session" });
|
|
1096
|
+
log.error(`${tag} the transcript ${transcript.path} holds no session, so the checks' input leaves it out`);
|
|
1097
|
+
continue;
|
|
1098
|
+
}
|
|
1099
|
+
const kept = copiedByTrace.get(traceId);
|
|
1100
|
+
if (kept !== void 0) {
|
|
1101
|
+
kept.duplicates = (kept.duplicates ?? 0) + 1;
|
|
1102
|
+
log.error(`${tag} the transcript ${transcript.path} repeats session ${traceId}, so the checks' input leaves it out`);
|
|
1103
|
+
continue;
|
|
1104
|
+
}
|
|
1105
|
+
const file = `sessions/${traceId}.jsonl`;
|
|
1106
|
+
const text = transcript.content.split("\n").filter((line) => line.trim() !== "").map(scrubLine).join("\n");
|
|
1107
|
+
writeReadOnly(join(dir, file), `${text}
|
|
1108
|
+
`);
|
|
1109
|
+
scrubDeep(session);
|
|
1110
|
+
parsed.push({ session: downconvertSession(session, "full"), traceId, subagent });
|
|
1111
|
+
const entry = { traceId, subagent, file, status: "copied" };
|
|
1112
|
+
copiedByTrace.set(traceId, entry);
|
|
1113
|
+
sessions.push(entry);
|
|
1114
|
+
}
|
|
1115
|
+
for (const miss of missed) {
|
|
1116
|
+
const options = sessionOptionsOf(miss.path);
|
|
1117
|
+
sessions.push({ traceId: traceIdForSession(options.fallbackId ?? miss.path), subagent: options.isSubagent === true, status: "missing", reason: miss.reason });
|
|
1118
|
+
log.error(`${tag} the transcript ${miss.path} could not be copied for the checks' input: ${miss.reason}`);
|
|
1119
|
+
}
|
|
1120
|
+
});
|
|
1121
|
+
}
|
|
1122
|
+
const ordered = orderSessions(parsed.map((entry) => entry.session));
|
|
1123
|
+
const traceOf = new Map(parsed.map((entry) => [entry.session.id, entry.traceId]));
|
|
1124
|
+
const facts = extractFacts(sessionsToTimeline(parsed.map((entry) => entry.session)));
|
|
1125
|
+
const traceAt = (index) => traceOf.get(ordered[index].id);
|
|
1126
|
+
const recorded = { commands: facts.coverage.has("commands"), edits: facts.coverage.has("edits") };
|
|
1127
|
+
const activity = {
|
|
1128
|
+
schemaVersion: 1,
|
|
1129
|
+
sessions: sessions.sort((a, b) => a.traceId.localeCompare(b.traceId)),
|
|
1130
|
+
// Left out of the file when undefined.
|
|
1131
|
+
sessionsUnavailable,
|
|
1132
|
+
workItem,
|
|
1133
|
+
diff,
|
|
1134
|
+
recorded,
|
|
1135
|
+
commands: recorded.commands ? facts.runs.map((run) => ({ seq: run.seq, traceId: traceAt(run.sessionIndex), turn: run.turnIndex, command: run.normalized, kind: run.kind, status: run.status })) : null,
|
|
1136
|
+
edits: recorded.edits ? facts.edits.map((edit) => ({ seq: edit.seq, traceId: traceAt(edit.sessionIndex), turn: edit.turnIndex, file: edit.file, status: edit.status })) : null
|
|
1137
|
+
};
|
|
1138
|
+
writeReadOnly(join(dir, "activity.json"), `${JSON.stringify(activity, null, 2)}
|
|
1139
|
+
`);
|
|
877
1140
|
}
|
|
878
1141
|
|
|
879
1142
|
// src/runner/container/agent-user.ts
|
|
@@ -1880,6 +2143,7 @@ function createContainerRuntime(opts = {}) {
|
|
|
1880
2143
|
const { cli, remoteFor } = opts;
|
|
1881
2144
|
return {
|
|
1882
2145
|
host: opts.host ?? createContainerHost(),
|
|
2146
|
+
cpus: opts.cpus ?? createCpuAllocator(usableCpus()),
|
|
1883
2147
|
tunnels: opts.tunnels ?? /* @__PURE__ */ new Map(),
|
|
1884
2148
|
buildImage: opts.buildImage ?? ((build) => buildRepositoryImage(
|
|
1885
2149
|
{
|
|
@@ -1934,7 +2198,7 @@ function gitRemoteFor(runtime, input) {
|
|
|
1934
2198
|
...input.readOnly === true ? { readOnly: true } : {}
|
|
1935
2199
|
});
|
|
1936
2200
|
}
|
|
1937
|
-
function
|
|
2201
|
+
function firstLine5(text) {
|
|
1938
2202
|
return text.trim().split("\n")[0] ?? "";
|
|
1939
2203
|
}
|
|
1940
2204
|
var NO_ENV = { literals: {}, passed: {} };
|
|
@@ -2027,7 +2291,8 @@ async function provisionContainer(input) {
|
|
|
2027
2291
|
imageId: report.imageId,
|
|
2028
2292
|
containerEnv: report.apply.containerEnv,
|
|
2029
2293
|
builtIns: true,
|
|
2030
|
-
lifecycle: report.apply.lifecycle
|
|
2294
|
+
lifecycle: report.apply.lifecycle,
|
|
2295
|
+
cpuset: formatCpuList(runtime.cpus.acquire(buildId, config.build?.cpus ?? 4))
|
|
2031
2296
|
};
|
|
2032
2297
|
const env = buildEnvironment({
|
|
2033
2298
|
config,
|
|
@@ -2058,7 +2323,7 @@ async function provisionContainer(input) {
|
|
|
2058
2323
|
}
|
|
2059
2324
|
return aborted2 ? { ok: false, reason: "ended before provision finished", aborted: true } : fail(reason);
|
|
2060
2325
|
};
|
|
2061
|
-
const dockerFailed = (what, result) => bail(`${what} failed (exit ${result.status})${
|
|
2326
|
+
const dockerFailed = (what, result) => bail(`${what} failed (exit ${result.status})${firstLine5(result.stderr) === "" ? "" : `: ${firstLine5(result.stderr)}`}`);
|
|
2062
2327
|
if (input.aborted()) return bail("", true);
|
|
2063
2328
|
mkdirSync(buildDir2, { recursive: true });
|
|
2064
2329
|
chmodSync(buildDir2, 493);
|
|
@@ -2079,7 +2344,7 @@ async function provisionContainer(input) {
|
|
|
2079
2344
|
} catch (err) {
|
|
2080
2345
|
return bail(`the tunnel could not start: ${describeCallFailure(err)}`);
|
|
2081
2346
|
}
|
|
2082
|
-
const limits2 = { memory: config.build?.memory ?? "8g", cpus: config.build?.cpus ?? 4, pids: config.build?.pids ?? 4096 };
|
|
2347
|
+
const limits2 = { memory: config.build?.memory ?? "8g", cpus: config.build?.cpus ?? 4, pids: config.build?.pids ?? 4096, cpuset: state.cpuset };
|
|
2083
2348
|
const runnerId = runnerLabelValue(config.configPath);
|
|
2084
2349
|
const volume = await host.createVolume(name, { [BUILD_LABEL]: buildId, [RUNNER_LABEL]: runnerId });
|
|
2085
2350
|
if (volume.status !== 0) return dockerFailed("creating the build's volume", volume);
|
|
@@ -2143,6 +2408,7 @@ async function provisionContainer(input) {
|
|
|
2143
2408
|
removeStagedContext: () => removeStagedContext(buildDir2)
|
|
2144
2409
|
});
|
|
2145
2410
|
if (!steps.ok) return bail(steps.reason, steps.aborted === true);
|
|
2411
|
+
state.startCommit = steps.startCommit;
|
|
2146
2412
|
return { ok: true, workdir: CHECKOUT_DIR, state, environment };
|
|
2147
2413
|
}
|
|
2148
2414
|
function agentVersionOf(toolsJson) {
|
|
@@ -2278,6 +2544,18 @@ async function syncInContainer(input) {
|
|
|
2278
2544
|
return { ok: false, reason: describeCallFailure(err) };
|
|
2279
2545
|
}
|
|
2280
2546
|
}
|
|
2547
|
+
async function copyTranscriptsFromContainer(runtime, state) {
|
|
2548
|
+
try {
|
|
2549
|
+
if (state.stopped) {
|
|
2550
|
+
const started = await runtime.host.start(state.container);
|
|
2551
|
+
if (started.status !== 0) return { ok: false, reason: `the build's container could not be started again (exit ${started.status})` };
|
|
2552
|
+
state.stopped = false;
|
|
2553
|
+
}
|
|
2554
|
+
} catch (err) {
|
|
2555
|
+
return { ok: false, reason: describeCallFailure(err) };
|
|
2556
|
+
}
|
|
2557
|
+
return copyTranscripts((argv) => runtime.host.exec({ container: state.container, user: state.agentUser ?? ADDED_USER, env: NO_ENV, argv }));
|
|
2558
|
+
}
|
|
2281
2559
|
var HOOK_ERRORS_IN_CONTAINER = "/build/home/.outerlayer/spool/hook-errors.log";
|
|
2282
2560
|
async function copyHookErrors(runtime, state, jobDir) {
|
|
2283
2561
|
try {
|
|
@@ -2310,6 +2588,7 @@ async function cleanupContainer(runtime, state, jobDir) {
|
|
|
2310
2588
|
await tunnel.close();
|
|
2311
2589
|
}
|
|
2312
2590
|
rmSync(state.buildDir, { recursive: true, force: true });
|
|
2591
|
+
runtime.cpus.release(state.buildId);
|
|
2313
2592
|
if (failures.length > 0) throw new Error(failures.join("; "));
|
|
2314
2593
|
}
|
|
2315
2594
|
async function startCheckContainer(input) {
|
|
@@ -2325,7 +2604,8 @@ async function startCheckContainer(input) {
|
|
|
2325
2604
|
const name = `outerlayer-check-${buildId}`;
|
|
2326
2605
|
const buildDir2 = buildDir(config.configPath, buildId);
|
|
2327
2606
|
const agentUser = built.agentUser ?? ADDED_USER;
|
|
2328
|
-
const
|
|
2607
|
+
const cpuset = built.cpuset ?? formatCpuList(runtime.cpus.acquire(buildId, config.build?.cpus ?? 4));
|
|
2608
|
+
const state = { buildId, container: name, volume: name, buildDir: buildDir2, repository, imageId: built.imageId, agentUser, cpuset };
|
|
2329
2609
|
const checksDir = join(jobDir, "checks");
|
|
2330
2610
|
mkdirSync(checksDir, { recursive: true });
|
|
2331
2611
|
const logPath = join(checksDir, "environment.log");
|
|
@@ -2338,7 +2618,7 @@ async function startCheckContainer(input) {
|
|
|
2338
2618
|
}
|
|
2339
2619
|
return { ok: false, reason };
|
|
2340
2620
|
};
|
|
2341
|
-
const dockerFailed = (what, result) => fail(`${what} failed (exit ${result.status})${
|
|
2621
|
+
const dockerFailed = (what, result) => fail(`${what} failed (exit ${result.status})${firstLine5(result.stderr) === "" ? "" : `: ${firstLine5(result.stderr)}`}`);
|
|
2342
2622
|
mkdirSync(buildDir2, { recursive: true });
|
|
2343
2623
|
chmodSync(buildDir2, 493);
|
|
2344
2624
|
try {
|
|
@@ -2347,7 +2627,7 @@ async function startCheckContainer(input) {
|
|
|
2347
2627
|
} catch (err) {
|
|
2348
2628
|
return fail(`the tunnel could not start: ${describeCallFailure(err)}`);
|
|
2349
2629
|
}
|
|
2350
|
-
const limits2 = { memory: config.build?.memory ?? "8g", cpus: config.build?.cpus ?? 4, pids: config.build?.pids ?? 4096 };
|
|
2630
|
+
const limits2 = { memory: config.build?.memory ?? "8g", cpus: config.build?.cpus ?? 4, pids: config.build?.pids ?? 4096, cpuset };
|
|
2351
2631
|
const runnerId = runnerLabelValue(config.configPath);
|
|
2352
2632
|
const volume = await host.createVolume(name, { [BUILD_LABEL]: buildId, [RUNNER_LABEL]: runnerId });
|
|
2353
2633
|
if (volume.status !== 0) return dockerFailed("creating the check environment's volume", volume);
|
|
@@ -2373,6 +2653,8 @@ async function startCheckContainer(input) {
|
|
|
2373
2653
|
ok: true,
|
|
2374
2654
|
container: {
|
|
2375
2655
|
state,
|
|
2656
|
+
// The directory the container sees read-only at `JOB_MOUNT` is the build's directory on the host, so a folder written there is already in place.
|
|
2657
|
+
evalInput: { dir: join(buildDir2, EVAL_INPUT_NAME), deliver: async () => void 0 },
|
|
2376
2658
|
exec: (argv, workdir, opts) => host.exec({ container: name, user: agentUser, workdir, env, argv }, opts?.logPath === void 0 ? void 0 : { logPath: opts.logPath }),
|
|
2377
2659
|
restart: async () => {
|
|
2378
2660
|
await host.stop(name);
|
|
@@ -2383,4 +2665,4 @@ async function startCheckContainer(input) {
|
|
|
2383
2665
|
};
|
|
2384
2666
|
}
|
|
2385
2667
|
|
|
2386
|
-
export { ADDED_USER, AgentUserError, AssetError, BuildTokens, GH_CONFIG_YML, MIN_ENGINE_MAJOR, classifyRefusal, cleanupContainer, containerCommandLine, containerSenderCommand, createBuildDisk, createContainerRuntime, createRunnerLog, deleteBuildDisk, describeCallFailure, ensureRootfs, ensureTunnel, formatClock, formatDuration, ghHostsYml, gitRemoteFor, isLiteralAddress, keepGhConfigCurrent, lifecycleFailureReason, lifecycleSteps, machineConfig, measureDisk, obtainImage, outOfMemoryReason, prepareBranch, provisionContainer, refusalCode, relativeToRunner, removeStagedContext, resolveAgentUser, retrySend, runBuildSteps, senderSignalScript, setUpRunnerCgroup, shellQuote, shortClaim, signalInContainer, stageGovernedContext, startCheckContainer, startServicesFor, stopContainer, syncInContainer };
|
|
2668
|
+
export { ADDED_USER, AgentUserError, AssetError, BuildTokens, EVAL_INPUT_NAME, GH_CONFIG_YML, MIN_ENGINE_MAJOR, classifyRefusal, cleanupContainer, containerCommandLine, containerSenderCommand, copyTranscripts, copyTranscriptsFromContainer, createBuildDisk, createContainerRuntime, createRunnerLog, deleteBuildDisk, describeCallFailure, ensureRootfs, ensureTunnel, formatClock, formatDuration, ghHostsYml, gitRemoteFor, isLiteralAddress, keepGhConfigCurrent, lifecycleFailureReason, lifecycleSteps, machineConfig, measureDisk, obtainImage, outOfMemoryReason, parseCpuList, prepareBranch, provisionContainer, refusalCode, relativeToRunner, removeStagedContext, resolveAgentUser, retrySend, runBuildSteps, senderSignalScript, setUpRunnerCgroup, shellQuote, shortClaim, signalInContainer, stageGovernedContext, startCheckContainer, startServicesFor, stopContainer, syncInContainer, writeEvalInput };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { compareVersions } from './chunk-I2UOAV7X.js';
|
|
4
|
+
import { launcherPath, writeLauncher, LauncherWriteError, pathNotes } from './chunk-PTW6W5NR.js';
|
|
5
|
+
import { currentVersion, currentLink, isInLayout, packageRootIn, versionDir, switchCurrent, execStartLine } from './chunk-TI7B7UEO.js';
|
|
5
6
|
import { RUNNER_DIR_MODE } from './chunk-ZM2IMMYN.js';
|
|
6
7
|
import { realpathSync, readFileSync, mkdirSync, rmSync, cpSync, existsSync } from 'fs';
|
|
7
8
|
import { dirname, sep, join } from 'path';
|
|
@@ -9,6 +10,8 @@ import { dirname, sep, join } from 'path';
|
|
|
9
10
|
createRequire(import.meta.url);
|
|
10
11
|
var RunnerInstallError = class extends Error {
|
|
11
12
|
};
|
|
13
|
+
var RunnerDowngradeError = class extends RunnerInstallError {
|
|
14
|
+
};
|
|
12
15
|
function runRunnerInstall(args) {
|
|
13
16
|
const { configPath, nodePath } = args;
|
|
14
17
|
let entry;
|
|
@@ -32,6 +35,13 @@ function runRunnerInstall(args) {
|
|
|
32
35
|
if (manifest.name !== "@outerlayer/cli") throw new RunnerInstallError(`${packageRoot} is not the @outerlayer/cli package`);
|
|
33
36
|
const version = manifest.version;
|
|
34
37
|
if (typeof version !== "string" || version === "") throw new RunnerInstallError(`${packageRoot}/package.json has no version`);
|
|
38
|
+
const installed = currentVersion(configPath);
|
|
39
|
+
if (args.allowDowngrade !== true && installed !== void 0 && (compareVersions(version, installed) ?? 0) < 0) {
|
|
40
|
+
const command = args.command ?? "runner install";
|
|
41
|
+
throw new RunnerDowngradeError(
|
|
42
|
+
`this CLI is ${version}, older than ${installed}, the version the runner runs from ${currentLink(configPath)}. Installing it would move the runner back to ${version}. Run \`${launcherPath(args.home)} ${command}\` instead, which runs ${installed}. To install ${version} anyway, run \`outerlayer ${command} --allow-downgrade\``
|
|
43
|
+
);
|
|
44
|
+
}
|
|
35
45
|
if (!isInLayout(configPath, entry) && !sameBuildInstalled(packageRoot, packageRootIn(versionDir(configPath, version)))) {
|
|
36
46
|
const target = packageRootIn(versionDir(configPath, version));
|
|
37
47
|
mkdirSync(dirname(target), { recursive: true, mode: RUNNER_DIR_MODE });
|
|
@@ -49,6 +59,7 @@ function runRunnerInstall(args) {
|
|
|
49
59
|
}
|
|
50
60
|
return {
|
|
51
61
|
version,
|
|
62
|
+
previous: installed,
|
|
52
63
|
execStart: execStartLine(configPath, nodePath),
|
|
53
64
|
launcher: {
|
|
54
65
|
path: launcherPath(args.home),
|
|
@@ -79,5 +90,9 @@ function launcherSummary(launcher) {
|
|
|
79
90
|
if (launcher.state === "foreign") return void 0;
|
|
80
91
|
return `${launcher.state === "unchanged" ? "outerlayer command already at" : "wrote the outerlayer command at"} ${launcher.path}, which runs the CLI that ${launcher.follows} names`;
|
|
81
92
|
}
|
|
93
|
+
function restartNote(result) {
|
|
94
|
+
if (result.previous === void 0 || result.previous === result.version) return void 0;
|
|
95
|
+
return `current moved from ${result.previous} to ${result.version}: a runner its service started takes no new work, waits for its running builds to finish, then restarts on ${result.version}. A runner started by hand keeps running until you restart it`;
|
|
96
|
+
}
|
|
82
97
|
|
|
83
|
-
export { RunnerInstallError, launcherSummary, runRunnerInstall };
|
|
98
|
+
export { RunnerDowngradeError, RunnerInstallError, launcherSummary, restartNote, runRunnerInstall };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { sanitizeTerminal } from './chunk-ZYHKJKSU.js';
|
|
4
|
-
import { remoteLookupFailed } from './chunk-
|
|
4
|
+
import { remoteLookupFailed } from './chunk-HN2JBGSI.js';
|
|
5
5
|
import { DEFAULT_DASHBOARD } from './chunk-USO2DKBD.js';
|
|
6
|
-
import { resolveGatewayCredentials } from './chunk-
|
|
6
|
+
import { resolveGatewayCredentials } from './chunk-PLMTLGYH.js';
|
|
7
7
|
import { readCloudConfig } from './chunk-EABW6AJQ.js';
|
|
8
8
|
import { writeRepoConnection, findGitDirs, readRepoConnection } from './chunk-BJ3KTMDH.js';
|
|
9
9
|
import { createInterface } from 'readline/promises';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { maintainedFilesForExistingSkills, loadMaintainedFiles, writeMaintainedFiles } from './chunk-
|
|
4
|
-
import { emitTree, parseOuterlayerConfig, classifyTree, generatedHeaderSource, CONTEXT_PIN_FILENAME, normalizePath } from './chunk-
|
|
3
|
+
import { maintainedFilesForExistingSkills, loadMaintainedFiles, writeMaintainedFiles } from './chunk-JXH6LEEH.js';
|
|
4
|
+
import { emitTree, parseOuterlayerConfig, classifyTree, generatedHeaderSource, CONTEXT_PIN_FILENAME, normalizePath } from './chunk-CMFCCIQN.js';
|
|
5
5
|
import { existsSync, readFileSync, mkdirSync, writeFileSync, copyFileSync, readdirSync } from 'fs';
|
|
6
6
|
import { join, dirname, relative, sep } from 'path';
|
|
7
7
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { C } from './chunk-YRYMNBGQ.js';
|
|
4
|
-
import { resolvePackRoot, loadTemplateFiles, loadMaintainedFiles, TEMPLATE_SKILLS, skillDir, writeMaintainedFiles, MAINTAINED_SKILLS } from './chunk-
|
|
4
|
+
import { resolvePackRoot, loadTemplateFiles, loadMaintainedFiles, TEMPLATE_SKILLS, skillDir, writeMaintainedFiles, MAINTAINED_SKILLS } from './chunk-JXH6LEEH.js';
|
|
5
5
|
import { resolvePackageVersion } from './chunk-RA3O54FC.js';
|
|
6
6
|
import { existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
7
7
|
import { join, dirname } from 'path';
|
|
@@ -21663,6 +21663,7 @@ function buildTokenPricingDictionary(models) {
|
|
|
21663
21663
|
}
|
|
21664
21664
|
var CACHE_CREATE_1H_INPUT_MULTIPLIER = 2;
|
|
21665
21665
|
var isCount = (n) => typeof n === "number" && Number.isFinite(n) && n > 0;
|
|
21666
|
+
var tokensOf = (n) => isCount(n) ? n : 0;
|
|
21666
21667
|
var hasTokens = (usage) => isCount(usage.in) || isCount(usage.out) || isCount(usage.cacheRead) || isCount(usage.cacheCreate5m) || isCount(usage.cacheCreate1h);
|
|
21667
21668
|
function selectRates(price, context = {}) {
|
|
21668
21669
|
var _a5, _b, _c;
|
|
@@ -21704,7 +21705,7 @@ function priceUsage(usage, price, context = {}) {
|
|
|
21704
21705
|
if (isCount(usage.cacheCreate5m) && rates.cacheCreate === void 0) unpriced.push("cacheCreate5m");
|
|
21705
21706
|
if (unpriced.length > 0) return { costUsd: null, unpricedClasses: unpriced };
|
|
21706
21707
|
return {
|
|
21707
|
-
costUsd: rates.in * usage.in + rates.out * usage.out + ((_a5 = rates.cacheRead) != null ? _a5 : 0) * usage.cacheRead + ((_b = rates.cacheCreate) != null ? _b : 0) * usage.cacheCreate5m + ((_c = rates.cacheCreate1h) != null ? _c : rates.in * CACHE_CREATE_1H_INPUT_MULTIPLIER) * usage.cacheCreate1h
|
|
21708
|
+
costUsd: rates.in * tokensOf(usage.in) + rates.out * tokensOf(usage.out) + ((_a5 = rates.cacheRead) != null ? _a5 : 0) * tokensOf(usage.cacheRead) + ((_b = rates.cacheCreate) != null ? _b : 0) * tokensOf(usage.cacheCreate5m) + ((_c = rates.cacheCreate1h) != null ? _c : rates.in * CACHE_CREATE_1H_INPUT_MULTIPLIER) * tokensOf(usage.cacheCreate1h)
|
|
21708
21709
|
};
|
|
21709
21710
|
}
|
|
21710
21711
|
function priceBuckets(buckets, dict) {
|