@outerlayer/cli 0.34.0-next.20261027023105 → 0.34.0-next.20261027162612
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/dist/{agent-setup-2A6P2SYL.js → agent-setup-THDNZ5ME.js} +6 -6
- package/dist/{bridge-F5FBQSPZ.js → bridge-MLB57JP6.js} +2 -2
- package/dist/build-25GDCEZ7.js +18 -0
- package/dist/{build-disk-RZ7AZKTY.js → build-disk-NFMQCZM3.js} +8 -8
- package/dist/build-info.json +1 -1
- package/dist/{builder-MQIL24HI.js → builder-OWDGC3VQ.js} +7 -7
- package/dist/{check-YIUZ3UX3.js → check-QGM2SECF.js} +39 -39
- package/dist/{chunk-RR3VDM7M.js → chunk-2YPOSVC7.js} +3 -3
- package/dist/{chunk-66LH5QAV.js → chunk-36M4KVBT.js} +2 -2
- package/dist/{chunk-LQHCNXPK.js → chunk-3FTIUB7I.js} +1 -1
- package/dist/{chunk-QWXBWOVV.js → chunk-3RRYEZAC.js} +4 -4
- package/dist/{chunk-GJ4KBHBD.js → chunk-3VJYDWFV.js} +1 -1
- package/dist/{chunk-CCHSD7RS.js → chunk-4QQJTJUN.js} +1 -1
- package/dist/{chunk-P3NPTFLF.js → chunk-5ARXP3BP.js} +3 -3
- package/dist/{chunk-IYQPUGST.js → chunk-5FHBVV25.js} +104 -59
- package/dist/{chunk-7QAJQDHS.js → chunk-62URQYCB.js} +1 -1
- package/dist/{chunk-QABXXQ67.js → chunk-6IMQXBTZ.js} +6 -6
- package/dist/{chunk-77VBS2RT.js → chunk-7Q7GQELE.js} +5 -5
- package/dist/{chunk-QRJIBTNQ.js → chunk-7SJNVGVC.js} +6 -6
- package/dist/{chunk-FQGC22IP.js → chunk-7TLGRE5F.js} +2 -2
- package/dist/{chunk-OOD5NDQA.js → chunk-A6PJSNP6.js} +349 -94
- package/dist/{chunk-7PCA37ZS.js → chunk-ANFNZCXZ.js} +5 -5
- package/dist/{chunk-MN3PP45X.js → chunk-AV5T7HV3.js} +1 -1
- package/dist/{chunk-DX4FF5P5.js → chunk-BCIBSJZH.js} +43 -24
- package/dist/{chunk-6KFJIU73.js → chunk-BS3OYFAD.js} +1 -1
- package/dist/{chunk-TS3EFB7S.js → chunk-BS4CZMT6.js} +1 -1
- package/dist/{chunk-SDELQEG4.js → chunk-CFJOONWM.js} +1 -1
- package/dist/{chunk-UWDFA6WW.js → chunk-CKVJSOY3.js} +20 -20
- package/dist/{chunk-GTBY7BTI.js → chunk-CMMEJJTL.js} +10 -35
- package/dist/{chunk-OKGHWCSK.js → chunk-EYJRVHBN.js} +3 -3
- package/dist/{chunk-GR7ZVGNI.js → chunk-FLHBUQ2W.js} +7 -6
- package/dist/{chunk-72CJOYN6.js → chunk-FVVHQIZR.js} +1 -1
- package/dist/{chunk-SDAEXUIX.js → chunk-GMKDAF37.js} +26 -6
- package/dist/{chunk-CFFVCI2I.js → chunk-GPO7F757.js} +1 -1
- package/dist/{chunk-EBVK3QBO.js → chunk-HJCNWEQK.js} +3 -3
- package/dist/{chunk-LKTH7PUH.js → chunk-J3Q3QCOF.js} +393 -91
- package/dist/{chunk-MYLOOVRJ.js → chunk-JO4SAEHH.js} +3 -3
- package/dist/{chunk-3VZTNXK5.js → chunk-JVNQNKHV.js} +1 -1
- package/dist/{chunk-DEJCZ43H.js → chunk-JWMJMQRF.js} +83 -7
- package/dist/{chunk-JL4GSPGD.js → chunk-KVGK2JL3.js} +6 -6
- package/dist/{chunk-BLSEHKZ4.js → chunk-LYX2RRSF.js} +2 -2
- package/dist/{chunk-WPDL7MBC.js → chunk-MGF346ND.js} +3 -3
- package/dist/{chunk-SSRB5HEL.js → chunk-N33OOF3K.js} +11 -11
- package/dist/{chunk-36U7LY7C.js → chunk-NEBMTP7T.js} +6 -6
- package/dist/{chunk-O7QPHJWN.js → chunk-NO6E72RM.js} +2 -2
- package/dist/{chunk-7QF2EXAN.js → chunk-OHTMTMFX.js} +4 -4
- package/dist/{chunk-Q2KGDDUX.js → chunk-OP2L7OXA.js} +3 -3
- package/dist/{chunk-WBTPI5MP.js → chunk-QRIE4JZE.js} +3 -3
- package/dist/{chunk-ZK3A4W3I.js → chunk-QWSAZGH6.js} +14 -6
- package/dist/{chunk-7DK2FOZ4.js → chunk-RCAMBC3H.js} +3 -3
- package/dist/{chunk-L5VHGRQE.js → chunk-RJZZFAXS.js} +1 -1
- package/dist/{chunk-JA2ARVY6.js → chunk-T6ALNN3H.js} +1 -1
- package/dist/{chunk-HOUFCUMH.js → chunk-UZIAZXXO.js} +1 -1
- package/dist/{chunk-25XBOX3K.js → chunk-W246VXU4.js} +3 -3
- package/dist/{chunk-YL3RWW7X.js → chunk-WR2GRWK3.js} +1 -1
- package/dist/{chunk-QUOITPN7.js → chunk-WX2HW2G2.js} +8 -1
- package/dist/{chunk-HDLON3RJ.js → chunk-X7M73LKT.js} +9 -2
- package/dist/{chunk-WYR4INK3.js → chunk-Z4LFCJT6.js} +3 -3
- package/dist/{claude-launcher-EO3ALKBS.js → claude-launcher-LYGS66AC.js} +1 -1
- package/dist/{cli-MP5AUR36.js → cli-HVBFWC3J.js} +114 -113
- package/dist/{command-RGBJLW72.js → command-J3CDQLWC.js} +27 -27
- package/dist/{config-NGCQD6SN.js → config-5NWSCHIO.js} +9 -9
- package/dist/{connect-cmd-65YBQRSY.js → connect-cmd-HB3K3AHE.js} +6 -6
- package/dist/{container-start-KT2KKAQX.js → container-start-YLKDT2JG.js} +33 -33
- package/dist/{context-show-cmd-S5SEBOI2.js → context-show-cmd-RJIQS2KF.js} +7 -7
- package/dist/{control-plane-launch-BDSUP4DK.js → control-plane-launch-TS4DFJF4.js} +5 -5
- package/dist/{demo-record-cmd-BUNOOCNM.js → demo-record-cmd-VVZGUCWB.js} +4 -4
- package/dist/{demo-voice-cmd-RWTRJUAX.js → demo-voice-cmd-3ADGIWK6.js} +13 -13
- package/dist/{dist-ADKRGE7I.js → dist-BUSLJNSZ.js} +1 -1
- package/dist/{docker-TRGA5QRL.js → docker-5VGCFZV2.js} +7 -7
- package/dist/{doctor-NEO7NXJJ.js → doctor-AG73VZNG.js} +32 -30
- package/dist/{emit-artifact-cmd-56C6DBUP.js → emit-artifact-cmd-WJT7AXTZ.js} +11 -11
- package/dist/{emit-criteria-cmd-HRCWXD3W.js → emit-criteria-cmd-45IYB535.js} +8 -8
- package/dist/{emit-demo-cmd-QMRDQGB6.js → emit-demo-cmd-AIIQNPXS.js} +13 -13
- package/dist/{emit-finding-cmd-6MVFN4BO.js → emit-finding-cmd-6YTJK2NA.js} +8 -8
- package/dist/{emit-result-cmd-E3YYBXRY.js → emit-result-cmd-TZGFY743.js} +10 -10
- package/dist/{emit-step-cmd-DM4CRYYI.js → emit-step-cmd-LGBTIAXC.js} +8 -8
- package/dist/{exec-client-LXHTMVIB.js → exec-client-LR67CA24.js} +3 -3
- package/dist/find-unit-YGDFVHVU.js +19 -0
- package/dist/{findings-cmd-K2OYBTUH.js → findings-cmd-ETJXUDQI.js} +8 -8
- package/dist/{fleet-readiness-VIAVQYRP.js → fleet-readiness-MYIMDBF7.js} +5 -5
- package/dist/{governing-source-MQA2SDJT.js → governing-source-GBJTVMK2.js} +10 -10
- package/dist/{guest-init-WWL2WL7R.js → guest-init-GXPOW53F.js} +4 -4
- package/dist/{hook-fast-KXAQ22LZ.js → hook-fast-5WOGLR7V.js} +1 -1
- package/dist/{host-checks-JH2ILNZT.js → host-checks-6G2F2HTK.js} +31 -31
- package/dist/{pending-UWFDVFOA.js → host-key-GAZM4EOH.js} +3 -3
- package/dist/{image-tag-BTXKIH73.js → image-tag-OYHGRHVV.js} +3 -3
- package/dist/index.js +4 -4
- package/dist/{init-WGVNY4NP.js → init-7VWIU5TG.js} +24 -24
- package/dist/{init-HGJQW2NL.js → init-Y2OJSOAA.js} +24 -24
- package/dist/{init-cmd-L2SG2WSN.js → init-cmd-77XKBRUF.js} +11 -11
- package/dist/{init-update-JMVLGBDE.js → init-update-TXQHBY3H.js} +9 -9
- package/dist/{install-cmd-RGO7NWKP.js → install-cmd-VZGXSS73.js} +5 -5
- package/dist/{logs-LEVH6VAI.js → logs-42QPBCMC.js} +2 -2
- package/dist/{loop-F6E6PGWG.js → loop-FRT5NSFG.js} +38 -38
- package/dist/{machine-GYTMJSIY.js → machine-TEG554M5.js} +24 -24
- package/dist/{mcp-serve-cmd-4O5INM77.js → mcp-serve-cmd-LYJQO6U4.js} +4 -4
- package/dist/{paths-AQ47ZRHK.js → paths-QLFRPIKS.js} +2 -2
- package/dist/{host-key-TSOKVSZX.js → pending-6DDSCXUD.js} +3 -3
- package/dist/{pidfile-PCG2H5T4.js → pidfile-WLZ427QQ.js} +3 -3
- package/dist/{record-SVCNFCGQ.js → record-WGCMQLQS.js} +3 -3
- package/dist/{runner-env-DH7YA4BU.js → runner-env-6FSJOSWS.js} +11 -11
- package/dist/{runner-identity-GLL56XY7.js → runner-identity-XODZ7YBP.js} +7 -7
- package/dist/{runner-key-HMXSBRBE.js → runner-key-T3V7N7CL.js} +24 -24
- package/dist/{session-sender-KLOMLL7X.js → session-sender-U54EQJNR.js} +11 -11
- package/dist/{spec-cmd-MX5QFW32.js → spec-cmd-EM24GTAM.js} +9 -9
- package/dist/{status-QNKTP6OU.js → status-4YO4TUEH.js} +31 -31
- package/dist/{sync-cmd-CO4DFMHU.js → sync-cmd-Y5RKWVF7.js} +10 -10
- package/dist/{update-steps-M2UKG4QZ.js → update-steps-KNN4Y2ZU.js} +32 -32
- package/dist/{watch-GU62YVQY.js → watch-X5VYY4LH.js} +10 -10
- package/dist/{work-claim-cmd-JF5GGDFZ.js → work-claim-cmd-IU3YJQKR.js} +15 -15
- package/dist/{work-cmd-VR7PPSP6.js → work-cmd-LUKJHAMH.js} +8 -8
- package/dist/{work-comment-cmd-HVZF72B4.js → work-comment-cmd-BDNFAVKL.js} +9 -9
- package/dist/{work-demo-cmd-EDGNM5VJ.js → work-demo-cmd-GPDJHU6F.js} +8 -8
- package/dist/{work-logs-cmd-ZZVAHX36.js → work-logs-cmd-B6EX4RPE.js} +8 -8
- package/dist/{work-open-pr-cmd-AQWZRJHZ.js → work-open-pr-cmd-TRXDCMSG.js} +9 -9
- package/dist/{work-pr-cmd-UJ7VWCJN.js → work-pr-cmd-5GUR5SIU.js} +8 -8
- package/dist/{work-proofs-cmd-A7SZSM2A.js → work-proofs-cmd-PBY7WNYI.js} +9 -9
- package/dist/{work-proofs-record-YG6HD6SJ.js → work-proofs-record-AVKJFZOD.js} +16 -16
- package/dist/{work-stop-cmd-SAT4XVM2.js → work-stop-cmd-J47GZB2N.js} +8 -8
- package/package.json +1 -1
- package/skill-pack/maintained/outerlayer-build/SKILL.md +15 -0
- package/dist/build-FS7TQEJ6.js +0 -18
- package/dist/find-unit-IOCVYPNW.js +0 -19
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { sha256OfFile, downloadPinned, VoiceDownloadError } from './chunk-2PGI6RDE.js';
|
|
4
|
-
import { readDefaultBranchHead, cloneRepository, buildRepositoryImage, prepareImageBuild, KEY_PREFIX, TAG_HOST, metadataFromLabels, writeRecord } from './chunk-
|
|
5
|
-
import { FETCHED_DIR, toolsDockerfile, FETCHED_FFMPEG, FETCHED_GH, FETCHED_TINI, FETCHED_HEADLESS_SHELL, FETCHED_PLAYWRIGHT_FFMPEG, FETCHED_VOICE_DIR } from './chunk-
|
|
4
|
+
import { readDefaultBranchHead, cloneRepository, buildRepositoryImage, prepareImageBuild, KEY_PREFIX, TAG_HOST, SHARED_OWNER, SHARED_NAME, metadataFromLabels, writeRecord } from './chunk-5FHBVV25.js';
|
|
5
|
+
import { FETCHED_DIR, toolsDockerfile, FETCHED_FFMPEG, FETCHED_GH, FETCHED_TINI, FETCHED_HEADLESS_SHELL, FETCHED_PLAYWRIGHT_FFMPEG, FETCHED_VOICE_DIR } from './chunk-CMMEJJTL.js';
|
|
6
6
|
import { currentCliBuild } from './chunk-OGFGZQA3.js';
|
|
7
|
-
import { runExec, execCapture, waitForAgent } from './chunk-
|
|
8
|
-
import { GUEST_CID, linkVsockSockets } from './chunk-
|
|
9
|
-
import { retrySend, describeCallFailure, keepStagedContext, controlPlaneTokenFailure, refusalCode, resolveGoverningSource, prefetchGovernedContext, removeStagedContext, stageGovernedContext, pinnedSourceOf, commandWithShim, shimScript, WORKFLOW_PERMISSION_REASON } from './chunk-
|
|
10
|
-
import { runnerImageVersion } from './chunk-
|
|
11
|
-
import { hasStoredCredential, AGENT_COMMANDS, storeClaudeCredential, credentialFromStdin, isAgentName } from './chunk-
|
|
12
|
-
import { runnerCredentialProblem, builtinKind, allowHostProblem, hostAllowed } from './chunk-
|
|
13
|
-
import { formatBytes, allocatedBytes } from './chunk-
|
|
14
|
-
import { createDockerHost, builderSpec, runnerLabelValue, RUNNER_LABEL, BUILD_LABEL, prepareRunArgs, containerRunArgs, HASH_ARGV, parseProgramHash, JUDGE_PROGRAM, containerExecArgs, childEnvironment, readDu, JUDGE_DIR, MAX_ITEMS_BYTES, JUDGE_ITEMS, MAX_REPORT_BYTES, JUDGE_REPORT, spawnRun } from './chunk-
|
|
15
|
-
import { RecipeError, DOCKER_FEATURE, writeSanitizedRecipe, classifyProperties } from './chunk-
|
|
16
|
-
import { firecrackerArch, MICROVM_ARCHES, FIRECRACKER_VERSION, hostHelperPinned, CLAUDE_CODE_VERSION, builderDiskPinned, guestAssetsPinned, GUEST_HELPER_SHA256, GUEST_ASSETS_BASE_URL, GUEST_KERNEL_SHA256, JAILER_BINARY_SHA256, FIRECRACKER_BINARY_SHA256, FIRECRACKER_SHA256, GUEST_ASSETS_VERSION, BUILDER_DISK_VERSION, FFMPEG_STATIC, FFMPEG_BUILD_TAG, GH_SHA256, GH_VERSION, TINI_SHA256, TINI_VERSION, HEADLESS_SHELL, HEADLESS_SHELL_BASE_URL, PLAYWRIGHT_FFMPEG, PLAYWRIGHT_FFMPEG_BASE_URL, VOICE_PACK_FILES, BUILDER_DISK_SHA256, BUILDER_DISK_BASE_URL, DEFAULT_BASE_IMAGE } from './chunk-
|
|
7
|
+
import { runExec, execCapture, waitForAgent } from './chunk-JVNQNKHV.js';
|
|
8
|
+
import { GUEST_CID, linkVsockSockets } from './chunk-BS3OYFAD.js';
|
|
9
|
+
import { retrySend, describeCallFailure, keepStagedContext, controlPlaneTokenFailure, refusalCode, resolveGoverningSource, prefetchGovernedContext, removeStagedContext, stageGovernedContext, pinnedSourceOf, commandWithShim, shimScript, WORKFLOW_PERMISSION_REASON } from './chunk-7Q7GQELE.js';
|
|
10
|
+
import { runnerImageVersion } from './chunk-CFJOONWM.js';
|
|
11
|
+
import { hasStoredCredential, AGENT_COMMANDS, storeClaudeCredential, credentialFromStdin, isAgentName } from './chunk-OP2L7OXA.js';
|
|
12
|
+
import { optionalEgress, runnerCredentialProblem, builtinKind, allowHostProblem, systemClock, emptyEgressCounts, hostAllowed } from './chunk-JWMJMQRF.js';
|
|
13
|
+
import { formatBytes, allocatedBytes } from './chunk-LYX2RRSF.js';
|
|
14
|
+
import { createDockerHost, builderSpec, runnerLabelValue, RUNNER_LABEL, BUILD_LABEL, prepareRunArgs, containerRunArgs, HASH_ARGV, parseProgramHash, JUDGE_PROGRAM, containerExecArgs, childEnvironment, readDu, JUDGE_DIR, MAX_ITEMS_BYTES, JUDGE_ITEMS, MAX_REPORT_BYTES, JUDGE_REPORT, spawnRun } from './chunk-FLHBUQ2W.js';
|
|
15
|
+
import { RecipeError, DOCKER_FEATURE, universalImagePending, writeSanitizedRecipe, classifyProperties } from './chunk-X7M73LKT.js';
|
|
16
|
+
import { firecrackerArch, MICROVM_ARCHES, FIRECRACKER_VERSION, hostHelperPinned, CLAUDE_CODE_VERSION, builderDiskPinned, guestAssetsPinned, GUEST_HELPER_SHA256, GUEST_ASSETS_BASE_URL, GUEST_KERNEL_SHA256, JAILER_BINARY_SHA256, FIRECRACKER_BINARY_SHA256, FIRECRACKER_SHA256, GUEST_ASSETS_VERSION, BUILDER_DISK_VERSION, universalImagePinned, UNIVERSAL_IMAGE, UNIVERSAL_IMAGE_DIGEST, UNIVERSAL_IMAGE_REPOSITORY, UNIVERSAL_IMAGE_SOURCE, FFMPEG_STATIC, FFMPEG_BUILD_TAG, GH_SHA256, GH_VERSION, TINI_SHA256, TINI_VERSION, HEADLESS_SHELL, HEADLESS_SHELL_BASE_URL, PLAYWRIGHT_FFMPEG, PLAYWRIGHT_FFMPEG_BASE_URL, VOICE_PACK_FILES, BUILDER_DISK_SHA256, BUILDER_DISK_BASE_URL, DEFAULT_BASE_IMAGE } from './chunk-WX2HW2G2.js';
|
|
17
17
|
import { startTimeOf, isSameProcess } from './chunk-JBJTC3UU.js';
|
|
18
|
-
import { postJson, WorkCommandError, getJson } from './chunk-
|
|
18
|
+
import { postJson, WorkCommandError, getJson } from './chunk-6IMQXBTZ.js';
|
|
19
19
|
import { sanitizeTerminal } from './chunk-IXPH4EXK.js';
|
|
20
|
-
import { signerFor } from './chunk-
|
|
20
|
+
import { signerFor } from './chunk-RJZZFAXS.js';
|
|
21
21
|
import { sharedSkillNames, skillConflictMessage } from './chunk-FGF52V4V.js';
|
|
22
22
|
import { versionAtLeast, MINIMUM_CLAUDE_VERSION } from './chunk-HCVLP7XA.js';
|
|
23
|
-
import { MIN_SCRUBBED_LITERAL, setCustomScrubbers, setLocalIdentity, setRepoRoot, parseTranscript, scrubDeep, scrubText } from './chunk-
|
|
23
|
+
import { MIN_SCRUBBED_LITERAL, setCustomScrubbers, setLocalIdentity, setRepoRoot, parseTranscript, scrubDeep, scrubText } from './chunk-A6PJSNP6.js';
|
|
24
24
|
import { orderSessions, extractFacts, sessionsToTimeline } from './chunk-XFJ7YOPD.js';
|
|
25
25
|
import { downconvertSession } from './chunk-DINRXUQA.js';
|
|
26
|
-
import { vmAssetsDir, RUNNER_DIR_MODE, rootfsPathFor, diskTemplatesDir, RUNNER_FILE_MODE, buildsDir, buildDir, runnerDir, deliveryDir, ghConfigDir, runnerDirOfBuild, spoolDir, mirrorDir, SHIM_DIR, vsockPath, builderCacheDiskPath, builderConsolePath } from './chunk-
|
|
27
|
-
import { claudeCredential, parseIsolation, proxyEnvironment, withProxyWarningHidden, containerLocalAddress, destinationEnvironment, CLAUDE_CREDENTIAL_VARIABLES, builtInEnvironment, withHooksPath, startBuildServices, BUILT_IN_NAMES, repositoriesOf, primaryOf, RELAY_PORT, repositoryPath, CHECKOUT_DIR, lifecycleWorkdir, buildEnvironment, writeBuildMavenSettings, checkEnvironment, AGENT_CREDENTIAL_MISSING, mavenSettingsXml, namesGlobalSettings, MAVEN_NO_PROXY_NOTE, mavenArgs, MAVEN_SPACE_NOTE, writeMavenSettings, checkoutPath, JOB_MOUNT, realFdStorePort } from './chunk-
|
|
26
|
+
import { vmAssetsDir, RUNNER_DIR_MODE, rootfsPathFor, diskTemplatesDir, RUNNER_FILE_MODE, buildsDir, buildDir, runnerDir, deliveryDir, ghConfigDir, runnerDirOfBuild, spoolDir, mirrorDir, SHIM_DIR, vsockPath, builderCacheDiskPath, builderConsolePath } from './chunk-3VJYDWFV.js';
|
|
27
|
+
import { claudeCredential, parseIsolation, proxyEnvironment, withProxyWarningHidden, containerLocalAddress, destinationEnvironment, CLAUDE_CREDENTIAL_VARIABLES, builtInEnvironment, withHooksPath, startBuildServices, BUILT_IN_NAMES, repositoriesOf, primaryOf, RELAY_PORT, repositoryPath, CHECKOUT_DIR, lifecycleWorkdir, buildEnvironment, writeBuildMavenSettings, checkEnvironment, AGENT_CREDENTIAL_MISSING, mavenSettingsXml, namesGlobalSettings, MAVEN_NO_PROXY_NOTE, mavenArgs, MAVEN_SPACE_NOTE, writeMavenSettings, checkoutPath, nodeAcceptsProxyWarningFlag, PROXY_WARNING_FLAG, JOB_MOUNT, realFdStorePort } from './chunk-GMKDAF37.js';
|
|
28
28
|
import { RELAY_USER, RELAY_ID, UNKNOWN_TRANSPORT_REASON, DOCKER_DESKTOP_REASON, MAX_MALFORMED_SESSIONS, MALFORMED_REASON, JOIN_WAIT_MS, MAX_OPEN_STREAMS, STREAM_RESET_RATE, STREAM_RESET_BURST, STREAM_WINDOW, SESSION_WINDOW, targetOfPath } from './chunk-MESOOLF4.js';
|
|
29
29
|
import { spawn, spawnSync } from 'child_process';
|
|
30
30
|
import { mkdirSync, existsSync, readFileSync, mkdtempSync, rmSync, chmodSync, truncateSync, statSync, accessSync, constants, readdirSync, writeFileSync, lstatSync, copyFileSync, renameSync, rmdirSync, unlinkSync, linkSync, openSync, closeSync, cpSync, writeSync, appendFileSync, createWriteStream, createReadStream } from 'fs';
|
|
@@ -32,7 +32,7 @@ import { randomBytes, createHash } from 'crypto';
|
|
|
32
32
|
import { join, dirname, isAbsolute, relative, resolve, basename } from 'path';
|
|
33
33
|
import { createConnection, connect, createServer as createServer$1, isIP } from 'net';
|
|
34
34
|
import { availableParallelism, networkInterfaces, tmpdir } from 'os';
|
|
35
|
-
import { Duplex, PassThrough
|
|
35
|
+
import { Transform, Duplex, PassThrough } from 'stream';
|
|
36
36
|
import { createServer, request } from 'http';
|
|
37
37
|
import { lookup } from 'dns/promises';
|
|
38
38
|
import http2 from 'http2';
|
|
@@ -726,9 +726,9 @@ function createFirecrackerHost(options = {}) {
|
|
|
726
726
|
var BUILD_PREFIX = "build-";
|
|
727
727
|
var LEAF = "runner";
|
|
728
728
|
function serviceDirectory(selfCgroup, mount) {
|
|
729
|
-
const
|
|
730
|
-
if (
|
|
731
|
-
const path =
|
|
729
|
+
const line2 = selfCgroup?.split("\n").find((l) => l.startsWith("0::"));
|
|
730
|
+
if (line2 === void 0) return void 0;
|
|
731
|
+
const path = line2.slice(3).trim();
|
|
732
732
|
if (!path.endsWith(".service")) return void 0;
|
|
733
733
|
return join(mount, path);
|
|
734
734
|
}
|
|
@@ -1111,6 +1111,9 @@ var IDLE_TIMEOUT_MS = 10 * 6e4;
|
|
|
1111
1111
|
var STALLED_RESPONSE_MS = 6e4;
|
|
1112
1112
|
var MAX_BAD_GATEWAY_LINES = 10;
|
|
1113
1113
|
var BAD_GATEWAY_WINDOW_MS = 1e4;
|
|
1114
|
+
var CONNECTION_RATE_RANGE = "connection-rate";
|
|
1115
|
+
var OPEN_CONNECTIONS_RANGE = "open-connections";
|
|
1116
|
+
var COUNTS_SAVE_MS = 500;
|
|
1114
1117
|
async function systemResolve(host) {
|
|
1115
1118
|
const found = await lookup(host, { all: true, verbatim: true });
|
|
1116
1119
|
return found.map((a) => ({ address: a.address }));
|
|
@@ -1145,6 +1148,8 @@ async function startTunnel(socketPath, opts = {}) {
|
|
|
1145
1148
|
const connectTimeoutMs = opts.connectTimeoutMs ?? CONNECT_TIMEOUT_MS;
|
|
1146
1149
|
const idleTimeoutMs = opts.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
|
|
1147
1150
|
const stalledResponseMs = opts.stalledResponseMs ?? STALLED_RESPONSE_MS;
|
|
1151
|
+
const limits2 = opts.egress ?? { connectionsPerSecond: 0, connectionBurst: 1, openConnections: 0, sendBytesPerSecond: 0, flagHosts: 0 };
|
|
1152
|
+
const clock = opts.clock ?? systemClock;
|
|
1148
1153
|
let windowStartedMs = 0;
|
|
1149
1154
|
let linesInWindow = 0;
|
|
1150
1155
|
let suppressed = 0;
|
|
@@ -1173,6 +1178,15 @@ async function startTunnel(socketPath, opts = {}) {
|
|
|
1173
1178
|
const extraRefusalKeys = /* @__PURE__ */ new Set();
|
|
1174
1179
|
let refusalsMore = 0;
|
|
1175
1180
|
const destinations = [];
|
|
1181
|
+
const counts = emptyEgressCounts();
|
|
1182
|
+
let openNow = 0;
|
|
1183
|
+
let secondOf = 0;
|
|
1184
|
+
let openedInSecond = 0;
|
|
1185
|
+
let tokens = limits2.connectionBurst;
|
|
1186
|
+
let refilledAt = clock.now();
|
|
1187
|
+
let nextSendFree = 0;
|
|
1188
|
+
let lastSendClock = 0;
|
|
1189
|
+
const limitLogged = /* @__PURE__ */ new Set();
|
|
1176
1190
|
const routes = /* @__PURE__ */ Object.create(null);
|
|
1177
1191
|
if (opts.recordPath !== void 0 && existsSync(opts.recordPath)) {
|
|
1178
1192
|
try {
|
|
@@ -1183,8 +1197,12 @@ async function startTunnel(socketPath, opts = {}) {
|
|
|
1183
1197
|
}
|
|
1184
1198
|
hostsMore = saved.hostsMore ?? 0;
|
|
1185
1199
|
for (const name of saved.destinations ?? []) destinations.push(name);
|
|
1186
|
-
for (const [name,
|
|
1200
|
+
for (const [name, counts2] of Object.entries(saved.routes ?? {})) routes[name] = { requests: counts2.requests, failures: counts2.failures };
|
|
1187
1201
|
refusalsMore = saved.refusalsMore ?? 0;
|
|
1202
|
+
if (saved.egress !== void 0) {
|
|
1203
|
+
const kept = saved.egress;
|
|
1204
|
+
Object.assign(counts, kept, { refused: { ...counts.refused, ...kept.refused } });
|
|
1205
|
+
}
|
|
1188
1206
|
for (const refusal of saved.refusals ?? []) {
|
|
1189
1207
|
refusals.push(refusal);
|
|
1190
1208
|
refusalKeys.add(`${refusal.host}|${refusal.address}|${refusal.range}`);
|
|
@@ -1198,8 +1216,9 @@ async function startTunnel(socketPath, opts = {}) {
|
|
|
1198
1216
|
refusalsMore,
|
|
1199
1217
|
refusals: refusals.map((r) => ({ ...r })),
|
|
1200
1218
|
destinations: [...destinations],
|
|
1219
|
+
egress: { ...counts, refused: { ...counts.refused } },
|
|
1201
1220
|
// Absent until a route is served, so a record of a tunnel that served none is the shape an older runner wrote.
|
|
1202
|
-
...Object.keys(routes).length === 0 ? {} : { routes: Object.fromEntries(Object.entries(routes).map(([name,
|
|
1221
|
+
...Object.keys(routes).length === 0 ? {} : { routes: Object.fromEntries(Object.entries(routes).map(([name, counts2]) => [name, { ...counts2 }])) }
|
|
1203
1222
|
});
|
|
1204
1223
|
const persist = () => {
|
|
1205
1224
|
if (opts.recordPath === void 0) return;
|
|
@@ -1208,6 +1227,15 @@ async function startTunnel(socketPath, opts = {}) {
|
|
|
1208
1227
|
} catch {
|
|
1209
1228
|
}
|
|
1210
1229
|
};
|
|
1230
|
+
let saveTimer;
|
|
1231
|
+
const persistSoon = () => {
|
|
1232
|
+
if (opts.recordPath === void 0 || saveTimer !== void 0) return;
|
|
1233
|
+
saveTimer = setTimeout(() => {
|
|
1234
|
+
saveTimer = void 0;
|
|
1235
|
+
persist();
|
|
1236
|
+
}, COUNTS_SAVE_MS);
|
|
1237
|
+
saveTimer.unref();
|
|
1238
|
+
};
|
|
1211
1239
|
const destinationUsed = (name) => {
|
|
1212
1240
|
if (destinations.includes(name)) return;
|
|
1213
1241
|
destinations.push(name);
|
|
@@ -1219,9 +1247,9 @@ async function startTunnel(socketPath, opts = {}) {
|
|
|
1219
1247
|
persist();
|
|
1220
1248
|
};
|
|
1221
1249
|
const routeFinished = (name, ok) => {
|
|
1222
|
-
const
|
|
1223
|
-
|
|
1224
|
-
if (!ok)
|
|
1250
|
+
const counts2 = routes[name] ??= { requests: 0, failures: 0 };
|
|
1251
|
+
counts2.requests++;
|
|
1252
|
+
if (!ok) counts2.failures++;
|
|
1225
1253
|
persist();
|
|
1226
1254
|
};
|
|
1227
1255
|
const reached = (host) => {
|
|
@@ -1235,6 +1263,10 @@ async function startTunnel(socketPath, opts = {}) {
|
|
|
1235
1263
|
hosts.push(name);
|
|
1236
1264
|
seen.add(name);
|
|
1237
1265
|
}
|
|
1266
|
+
if (limits2.flagHosts > 0 && !counts.hostsFlagged && hosts.length + hostsMore > limits2.flagHosts) {
|
|
1267
|
+
counts.hostsFlagged = true;
|
|
1268
|
+
opts.log?.(`tunnel: this build reached more than ${limits2.flagHosts} distinct remote hosts`);
|
|
1269
|
+
}
|
|
1238
1270
|
persist();
|
|
1239
1271
|
};
|
|
1240
1272
|
const refused2 = (host, address, range) => {
|
|
@@ -1250,6 +1282,64 @@ async function startTunnel(socketPath, opts = {}) {
|
|
|
1250
1282
|
}
|
|
1251
1283
|
persist();
|
|
1252
1284
|
};
|
|
1285
|
+
const limitText = (range) => range === CONNECTION_RATE_RANGE ? `${limits2.connectionsPerSecond} new connections per second, burst ${limits2.connectionBurst}` : `${limits2.openConnections} open connections`;
|
|
1286
|
+
const admit = () => {
|
|
1287
|
+
const now = clock.now();
|
|
1288
|
+
if (limits2.openConnections > 0 && openNow >= limits2.openConnections) return OPEN_CONNECTIONS_RANGE;
|
|
1289
|
+
if (limits2.connectionsPerSecond > 0) {
|
|
1290
|
+
tokens = Math.min(limits2.connectionBurst, tokens + Math.max(0, now - refilledAt) / 1e3 * limits2.connectionsPerSecond);
|
|
1291
|
+
refilledAt = now;
|
|
1292
|
+
if (tokens < 1) return CONNECTION_RATE_RANGE;
|
|
1293
|
+
tokens -= 1;
|
|
1294
|
+
}
|
|
1295
|
+
counts.connectionsOpened++;
|
|
1296
|
+
openNow++;
|
|
1297
|
+
counts.peakOpenConnections = Math.max(counts.peakOpenConnections, openNow);
|
|
1298
|
+
const second = Math.floor(now / 1e3);
|
|
1299
|
+
if (second !== secondOf) {
|
|
1300
|
+
secondOf = second;
|
|
1301
|
+
openedInSecond = 0;
|
|
1302
|
+
}
|
|
1303
|
+
openedInSecond++;
|
|
1304
|
+
counts.peakConnectionsPerSecond = Math.max(counts.peakConnectionsPerSecond, openedInSecond);
|
|
1305
|
+
persistSoon();
|
|
1306
|
+
return void 0;
|
|
1307
|
+
};
|
|
1308
|
+
const release = () => {
|
|
1309
|
+
openNow--;
|
|
1310
|
+
};
|
|
1311
|
+
const refuseOverLimit = (host, range) => {
|
|
1312
|
+
if (range === CONNECTION_RATE_RANGE) counts.refused.connectionRate++;
|
|
1313
|
+
else counts.refused.openConnections++;
|
|
1314
|
+
refused2(host, NOT_RESOLVED, range);
|
|
1315
|
+
if (!limitLogged.has(range)) {
|
|
1316
|
+
limitLogged.add(range);
|
|
1317
|
+
opts.log?.(`tunnel refused ${host}: over the ${range} limit of ${limitText(range)}. Later refusals of this kind are counted when the build ends`);
|
|
1318
|
+
}
|
|
1319
|
+
persistSoon();
|
|
1320
|
+
return { status: 429, body: `refused: this build is over the ${range} limit of ${limitText(range)}
|
|
1321
|
+
` };
|
|
1322
|
+
};
|
|
1323
|
+
const waitToSend = async (n) => {
|
|
1324
|
+
const now = clock.now();
|
|
1325
|
+
if (now < lastSendClock) nextSendFree = Math.max(0, nextSendFree - (lastSendClock - now));
|
|
1326
|
+
lastSendClock = now;
|
|
1327
|
+
nextSendFree = Math.max(nextSendFree, now) + n * 1e3 / limits2.sendBytesPerSecond;
|
|
1328
|
+
await clock.sleep(nextSendFree - now);
|
|
1329
|
+
};
|
|
1330
|
+
const meter = () => new Transform({
|
|
1331
|
+
highWaterMark: 64 * 1024,
|
|
1332
|
+
transform(chunk, _encoding, done) {
|
|
1333
|
+
waitToSend(chunk.length).then(
|
|
1334
|
+
() => {
|
|
1335
|
+
counts.bytesSent += chunk.length;
|
|
1336
|
+
persistSoon();
|
|
1337
|
+
done(null, chunk);
|
|
1338
|
+
},
|
|
1339
|
+
(err) => done(err)
|
|
1340
|
+
);
|
|
1341
|
+
}
|
|
1342
|
+
});
|
|
1253
1343
|
async function decide(host, port) {
|
|
1254
1344
|
if (opts.allowHosts !== void 0 && !hostAllowed(host, opts.allowHosts)) {
|
|
1255
1345
|
refused2(host, NOT_RESOLVED, NOT_ALLOWED_RANGE);
|
|
@@ -1294,7 +1384,7 @@ async function startTunnel(socketPath, opts = {}) {
|
|
|
1294
1384
|
server.on("connect", (req, client, head) => {
|
|
1295
1385
|
void tunnelConnect(req, client, head);
|
|
1296
1386
|
});
|
|
1297
|
-
const statusLine = (status) => `HTTP/1.1 ${status} ${status === 403 ? "Forbidden" : "Bad Gateway"}`;
|
|
1387
|
+
const statusLine = (status) => `HTTP/1.1 ${status} ${status === 403 ? "Forbidden" : status === 429 ? "Too Many Requests" : "Bad Gateway"}`;
|
|
1298
1388
|
const reply = (client, status, body) => {
|
|
1299
1389
|
client.end(`${statusLine(status)}\r
|
|
1300
1390
|
Content-Type: text/plain\r
|
|
@@ -1310,6 +1400,13 @@ ${body}`);
|
|
|
1310
1400
|
client.end("HTTP/1.1 400 Bad Request\r\nConnection: close\r\nContent-Length: 0\r\n\r\n");
|
|
1311
1401
|
return;
|
|
1312
1402
|
}
|
|
1403
|
+
const over = admit();
|
|
1404
|
+
if (over !== void 0) {
|
|
1405
|
+
const refusal = refuseOverLimit(target.host, over);
|
|
1406
|
+
reply(client, refusal.status, refusal.body);
|
|
1407
|
+
return;
|
|
1408
|
+
}
|
|
1409
|
+
client.once("close", release);
|
|
1313
1410
|
const decision = await decide(target.host, target.port);
|
|
1314
1411
|
if (!decision.ok) {
|
|
1315
1412
|
reply(client, decision.status, decision.body);
|
|
@@ -1336,16 +1433,33 @@ ${body}`);
|
|
|
1336
1433
|
if (!upstream.readableEnded && !client.writableEnded) client.destroy(abortedError("the tunnel closed the connection to the server before it ended"));
|
|
1337
1434
|
else client.resume();
|
|
1338
1435
|
});
|
|
1339
|
-
|
|
1436
|
+
const buildEnded = () => {
|
|
1340
1437
|
upstream.destroy();
|
|
1341
1438
|
client.end();
|
|
1342
|
-
}
|
|
1439
|
+
};
|
|
1440
|
+
const metered = limits2.sendBytesPerSecond > 0 ? meter() : void 0;
|
|
1441
|
+
if (metered === void 0) client.once("end", buildEnded);
|
|
1442
|
+
else metered.once("end", buildEnded);
|
|
1343
1443
|
reached(target.host);
|
|
1344
1444
|
client.write("HTTP/1.1 200 Connection Established\r\n\r\n");
|
|
1345
|
-
|
|
1445
|
+
if (metered !== void 0) {
|
|
1446
|
+
if (head.length > 0) metered.write(head);
|
|
1447
|
+
} else {
|
|
1448
|
+
counts.bytesSent += head.length;
|
|
1449
|
+
upstream.write(head);
|
|
1450
|
+
}
|
|
1346
1451
|
releaseWhenStalled(client, upstream);
|
|
1347
1452
|
upstream.pipe(client);
|
|
1348
|
-
|
|
1453
|
+
if (metered === void 0) {
|
|
1454
|
+
client.on("data", (chunk) => {
|
|
1455
|
+
counts.bytesSent += chunk.length;
|
|
1456
|
+
persistSoon();
|
|
1457
|
+
});
|
|
1458
|
+
client.pipe(upstream);
|
|
1459
|
+
} else {
|
|
1460
|
+
client.once("close", () => metered.destroy());
|
|
1461
|
+
client.pipe(metered).pipe(upstream);
|
|
1462
|
+
}
|
|
1349
1463
|
};
|
|
1350
1464
|
if (upstream.readyState === "open") established();
|
|
1351
1465
|
else upstream.once("connect", established);
|
|
@@ -1395,6 +1509,14 @@ ${body}`);
|
|
|
1395
1509
|
}
|
|
1396
1510
|
const host = url.hostname.replace(/^\[|\]$/g, "");
|
|
1397
1511
|
const port = url.port === "" ? 80 : Number(url.port);
|
|
1512
|
+
const over = admit();
|
|
1513
|
+
if (over !== void 0) {
|
|
1514
|
+
const refusal = refuseOverLimit(host, over);
|
|
1515
|
+
res.writeHead(refusal.status, { "Content-Type": "text/plain", Connection: "close" });
|
|
1516
|
+
res.end(refusal.body);
|
|
1517
|
+
return;
|
|
1518
|
+
}
|
|
1519
|
+
res.once("close", release);
|
|
1398
1520
|
const decision = await decide(host, port);
|
|
1399
1521
|
if (!decision.ok) {
|
|
1400
1522
|
res.writeHead(decision.status, { "Content-Type": "text/plain", Connection: "close" });
|
|
@@ -1430,7 +1552,17 @@ ${body}`);
|
|
|
1430
1552
|
res.destroy();
|
|
1431
1553
|
}
|
|
1432
1554
|
});
|
|
1433
|
-
|
|
1555
|
+
if (limits2.sendBytesPerSecond > 0) {
|
|
1556
|
+
const metered = meter();
|
|
1557
|
+
res.once("close", () => metered.destroy());
|
|
1558
|
+
req.pipe(metered).pipe(upstream);
|
|
1559
|
+
} else {
|
|
1560
|
+
req.on("data", (chunk) => {
|
|
1561
|
+
counts.bytesSent += chunk.length;
|
|
1562
|
+
persistSoon();
|
|
1563
|
+
});
|
|
1564
|
+
req.pipe(upstream);
|
|
1565
|
+
}
|
|
1434
1566
|
}
|
|
1435
1567
|
if (opts.socket !== false) {
|
|
1436
1568
|
if (opts.listenOn !== void 0) {
|
|
@@ -1463,6 +1595,9 @@ ${body}`);
|
|
|
1463
1595
|
return { port: tcp.address().port };
|
|
1464
1596
|
},
|
|
1465
1597
|
close: () => new Promise((resolveClose) => {
|
|
1598
|
+
clearTimeout(saveTimer);
|
|
1599
|
+
saveTimer = void 0;
|
|
1600
|
+
persist();
|
|
1466
1601
|
for (const socket of sockets) socket.destroy();
|
|
1467
1602
|
for (const tcp of tcpServers) tcp.close();
|
|
1468
1603
|
server.close(() => resolveClose());
|
|
@@ -1646,14 +1781,14 @@ async function deliverExecMaven(build, workdir, base, run, note) {
|
|
|
1646
1781
|
}
|
|
1647
1782
|
function onceNote(write) {
|
|
1648
1783
|
const seen = /* @__PURE__ */ new Set();
|
|
1649
|
-
return (
|
|
1650
|
-
if (seen.has(
|
|
1651
|
-
seen.add(
|
|
1652
|
-
write(
|
|
1784
|
+
return (line2) => {
|
|
1785
|
+
if (seen.has(line2)) return;
|
|
1786
|
+
seen.add(line2);
|
|
1787
|
+
write(line2);
|
|
1653
1788
|
};
|
|
1654
1789
|
}
|
|
1655
1790
|
function attemptNote(log, tag) {
|
|
1656
|
-
return onceNote((
|
|
1791
|
+
return onceNote((line2) => log.line(`${tag} ${line2}`));
|
|
1657
1792
|
}
|
|
1658
1793
|
function hostCommandEnvironment(base, build, config, hooksPath, note) {
|
|
1659
1794
|
let env = { ...base };
|
|
@@ -1690,6 +1825,7 @@ async function startHostServices(input) {
|
|
|
1690
1825
|
jobDir: input.jobDir,
|
|
1691
1826
|
destinations,
|
|
1692
1827
|
allowHosts: config.build?.allowHosts,
|
|
1828
|
+
...optionalEgress(config),
|
|
1693
1829
|
serve: input.process ? "tcp" : "both",
|
|
1694
1830
|
proxy: input.process,
|
|
1695
1831
|
...input.process ? { builtIns: { gatewayUrl: config.url, itemKey: input.itemKey, claudeUpstream: runtime.claudeUpstream } } : {},
|
|
@@ -1739,7 +1875,7 @@ function e2fsckRunner(run = runWithSpawn(), env = process.env) {
|
|
|
1739
1875
|
};
|
|
1740
1876
|
}
|
|
1741
1877
|
function firstLine2(text) {
|
|
1742
|
-
return text.split("\n").find((
|
|
1878
|
+
return text.split("\n").find((line2) => line2.trim() !== "")?.trim() ?? "";
|
|
1743
1879
|
}
|
|
1744
1880
|
async function giveBackCacheSpace(input) {
|
|
1745
1881
|
try {
|
|
@@ -1985,7 +2121,8 @@ function readStored(prepared) {
|
|
|
1985
2121
|
toolsBuilt: false,
|
|
1986
2122
|
checkedCommit: prepared.checkout.commit,
|
|
1987
2123
|
recordDir: prepared.recordDir,
|
|
1988
|
-
|
|
2124
|
+
// On the universal image the stored report is shared by every repository, so the reused result names this build's repository and commit.
|
|
2125
|
+
report: prepared.location.kind === "default" ? { ...stored.report, repository: prepared.repository, sourceCommit: prepared.checkout.commit, defaultBranch: prepared.checkout.defaultBranch } : stored.report,
|
|
1989
2126
|
removed: [],
|
|
1990
2127
|
rootfs: { path, env: stored.env, user: stored.user }
|
|
1991
2128
|
};
|
|
@@ -2012,6 +2149,7 @@ async function buildRootDiskInMicroVm(opts, deps) {
|
|
|
2012
2149
|
try {
|
|
2013
2150
|
const stored = readStored(prepared);
|
|
2014
2151
|
if (stored !== void 0) return stored;
|
|
2152
|
+
if (prepared.location.kind === "default" && !(deps.universalPublished ?? universalImagePinned)()) throw universalImagePending();
|
|
2015
2153
|
return await buildInBuilder(opts, deps, prepared);
|
|
2016
2154
|
} finally {
|
|
2017
2155
|
prepared.release();
|
|
@@ -2025,8 +2163,8 @@ async function buildInBuilder(opts, deps, prepared) {
|
|
|
2025
2163
|
const { repository, owner, name, checkout, location, recipe, repoRecords, recordDir, logPath } = prepared;
|
|
2026
2164
|
const rKey = prepared.recipeKey.slice(0, KEY_PREFIX);
|
|
2027
2165
|
const tKey = prepared.toolsKey.slice(0, KEY_PREFIX);
|
|
2028
|
-
const recipeTag = `${TAG_HOST}/recipe/${
|
|
2029
|
-
const buildTag = `${TAG_HOST}/build/${
|
|
2166
|
+
const recipeTag = `${TAG_HOST}/recipe/${prepared.tagName}:${rKey}`;
|
|
2167
|
+
const buildTag = `${TAG_HOST}/build/${prepared.tagName}:${rKey}-${tKey}`;
|
|
2030
2168
|
const runner = runnerDir(opts.configPath);
|
|
2031
2169
|
const builderDisk = await ports.builderDisk(runner);
|
|
2032
2170
|
const toolFilesDir = await ports.toolFiles(runner);
|
|
@@ -2037,7 +2175,7 @@ async function buildInBuilder(opts, deps, prepared) {
|
|
|
2037
2175
|
const dir = buildDir(opts.configPath, id);
|
|
2038
2176
|
const state = { buildId: id, buildDir: dir, vsockPath: vsockPath(dir) };
|
|
2039
2177
|
const record = { owner, name, id };
|
|
2040
|
-
const cachePath = builderCacheDiskPath(opts.configPath, owner, name);
|
|
2178
|
+
const cachePath = location.kind === "default" ? builderCacheDiskPath(opts.configPath, SHARED_OWNER, SHARED_NAME) : builderCacheDiskPath(opts.configPath, owner, name);
|
|
2041
2179
|
const diskPath = join(dir, "build.ext4");
|
|
2042
2180
|
const partial = join(recordDir, "rootfs.ext4.partial");
|
|
2043
2181
|
const scratchRoot = opts.tmpDir ?? tmpdir();
|
|
@@ -2080,12 +2218,12 @@ async function buildInBuilder(opts, deps, prepared) {
|
|
|
2080
2218
|
lines.push(pending);
|
|
2081
2219
|
pending = "";
|
|
2082
2220
|
}
|
|
2083
|
-
for (const
|
|
2084
|
-
if (
|
|
2085
|
-
else if (
|
|
2086
|
-
else if (
|
|
2221
|
+
for (const line2 of lines) {
|
|
2222
|
+
if (line2.startsWith(RESULT_PREFIX)) result = line2.slice(RESULT_PREFIX.length);
|
|
2223
|
+
else if (line2.startsWith(ENGINE_PANIC_PREFIX)) enginePanic ??= line2.slice(ENGINE_PANIC_PREFIX.length);
|
|
2224
|
+
else if (line2 === ENGINE_STOPPED_LINE) continue;
|
|
2087
2225
|
else {
|
|
2088
|
-
tail.push(
|
|
2226
|
+
tail.push(line2);
|
|
2089
2227
|
if (tail.length > LOG_TAIL_LINES) tail.shift();
|
|
2090
2228
|
}
|
|
2091
2229
|
}
|
|
@@ -2126,6 +2264,7 @@ async function buildInBuilder(opts, deps, prepared) {
|
|
|
2126
2264
|
tunnel = await deps.startTunnel(join(dir, TUNNEL_SOCKET), {
|
|
2127
2265
|
...deps.tunnelOptions,
|
|
2128
2266
|
...opts.allowHosts === void 0 ? {} : { allowHosts: opts.allowHosts },
|
|
2267
|
+
...opts.egress === void 0 ? {} : { egress: opts.egress },
|
|
2129
2268
|
recordPath: join(dir, "tunnel.json")
|
|
2130
2269
|
});
|
|
2131
2270
|
const configPath = join(dir, "vm.json");
|
|
@@ -2158,7 +2297,8 @@ async function buildInBuilder(opts, deps, prepared) {
|
|
|
2158
2297
|
let recipeParts = { kind: "default" };
|
|
2159
2298
|
const recipeDir = join(scratch, "recipe");
|
|
2160
2299
|
mkdirSync(recipeDir);
|
|
2161
|
-
if (location.kind === "default") writeFileSync(join(recipeDir, "Dockerfile"),
|
|
2300
|
+
if (location.kind === "default") writeFileSync(join(recipeDir, "Dockerfile"), `FROM ${UNIVERSAL_IMAGE}
|
|
2301
|
+
`);
|
|
2162
2302
|
else {
|
|
2163
2303
|
sanitized = writeSanitizedRecipe(checkout.dir, location, recipe);
|
|
2164
2304
|
recipeParts = { kind: "file", config: relative(checkout.dir, sanitized) };
|
|
@@ -2173,7 +2313,15 @@ async function buildInBuilder(opts, deps, prepared) {
|
|
|
2173
2313
|
mkdirSync(join(toolsDir, FETCHED_DIR));
|
|
2174
2314
|
writeFileSync(
|
|
2175
2315
|
join(toolsDir, "Dockerfile"),
|
|
2176
|
-
toolsDockerfile({
|
|
2316
|
+
toolsDockerfile({
|
|
2317
|
+
recipeImage: recipeTag,
|
|
2318
|
+
nodeImage: prepared.nodeImage,
|
|
2319
|
+
claudeCodeVersion: prepared.claudeCodeVersion,
|
|
2320
|
+
buildId: opts.cli.buildId,
|
|
2321
|
+
guestHelper: true,
|
|
2322
|
+
fetched: true,
|
|
2323
|
+
...location.kind === "default" ? { universal: true } : {}
|
|
2324
|
+
})
|
|
2177
2325
|
);
|
|
2178
2326
|
inputs = builderInput({ checkoutDir: checkout.dir, toolsDir, toolFilesDir, recipeDir }, archive);
|
|
2179
2327
|
for (const { target, stream } of inputs) {
|
|
@@ -2223,6 +2371,7 @@ async function buildInBuilder(opts, deps, prepared) {
|
|
|
2223
2371
|
sourceCommit: checkout.commit,
|
|
2224
2372
|
defaultBranch: checkout.defaultBranch,
|
|
2225
2373
|
recipe: location.kind === "default" ? "default" : location.path,
|
|
2374
|
+
...location.kind === "default" ? { base: { reference: `${UNIVERSAL_IMAGE_REPOSITORY}:${UNIVERSAL_IMAGE_SOURCE}`, digest: UNIVERSAL_IMAGE_DIGEST } } : {},
|
|
2226
2375
|
recipeKey: prepared.recipeKey,
|
|
2227
2376
|
toolsKey: prepared.toolsKey,
|
|
2228
2377
|
imageId: `${ROOT_DISK_ID_PREFIX}${rKey}-${tKey}`,
|
|
@@ -2291,7 +2440,7 @@ async function buildInBuilder(opts, deps, prepared) {
|
|
|
2291
2440
|
}
|
|
2292
2441
|
const refusals = tunnel?.record().refusals ?? [];
|
|
2293
2442
|
if (err instanceof StepFailed && refusals.length > 0) return new RecipeError("image_builder_failed", refusalReason(refusals, logPath), logPath);
|
|
2294
|
-
const last = tail.filter((
|
|
2443
|
+
const last = tail.filter((line2) => line2.trim() !== "").at(-1);
|
|
2295
2444
|
const why = err instanceof StepFailed ? err.message : `the builder microVM failed: ${describeCallFailure(err)}`;
|
|
2296
2445
|
const panicNote = enginePanic === void 0 ? "" : `; the first panic in the Docker engine's log was: ${enginePanic}`;
|
|
2297
2446
|
return new RecipeError("image_builder_failed", `${why}${panicNote}${last === void 0 ? "" : `; the last line was: ${last}`}. The build log is at ${logPath}`, logPath);
|
|
@@ -2745,14 +2894,145 @@ function lifecycleFailureReason(step, exitCode) {
|
|
|
2745
2894
|
return `lifecycle command ${step.name} (${step.source}) exited ${exitCode}`;
|
|
2746
2895
|
}
|
|
2747
2896
|
|
|
2897
|
+
// src/runner/runtimes.ts
|
|
2898
|
+
var RUNTIMES = ["node", "python", "go", "rust", "ruby", "java"];
|
|
2899
|
+
var MANIFESTS = {
|
|
2900
|
+
"package.json": "node",
|
|
2901
|
+
"pyproject.toml": "python",
|
|
2902
|
+
"requirements.txt": "python",
|
|
2903
|
+
"go.mod": "go",
|
|
2904
|
+
"Cargo.toml": "rust",
|
|
2905
|
+
Gemfile: "ruby",
|
|
2906
|
+
"pom.xml": "java",
|
|
2907
|
+
"build.gradle": "java",
|
|
2908
|
+
"build.gradle.kts": "java"
|
|
2909
|
+
};
|
|
2910
|
+
var IMAGE_CONFIG = "/etc/mise/config.toml";
|
|
2911
|
+
var RUST_PIN_FILES = ["rust-toolchain.toml", "rust-toolchain"];
|
|
2912
|
+
var REFUSALS_NAMED2 = 3;
|
|
2913
|
+
var PLAIN = { withoutProxyWarning: true };
|
|
2914
|
+
function firstLine4(text) {
|
|
2915
|
+
return text.trim().split("\n")[0] ?? "";
|
|
2916
|
+
}
|
|
2917
|
+
function toolFailure(stderr) {
|
|
2918
|
+
for (const l of stderr.split("\n")) {
|
|
2919
|
+
if (/^\S+@\S+: /.test(l)) return l;
|
|
2920
|
+
const summary = /^\s*mise ✗ (\S+@\S+)\s+.*?· failed: (.+)$/.exec(l);
|
|
2921
|
+
if (summary !== null) return `${summary[1]}: ${summary[2]}`;
|
|
2922
|
+
}
|
|
2923
|
+
return "";
|
|
2924
|
+
}
|
|
2925
|
+
function describeSource(source, path) {
|
|
2926
|
+
if (source === void 0 || source === IMAGE_CONFIG) return "the image default";
|
|
2927
|
+
return source.startsWith(`${path}/`) ? source.slice(path.length + 1) : source;
|
|
2928
|
+
}
|
|
2929
|
+
function parseListing(stdout) {
|
|
2930
|
+
try {
|
|
2931
|
+
const parsed = JSON.parse(stdout);
|
|
2932
|
+
return Object.entries(parsed).flatMap(
|
|
2933
|
+
([tool, versions]) => (Array.isArray(versions) ? versions : []).flatMap(
|
|
2934
|
+
(entry) => typeof entry.version === "string" ? [{ tool, version: entry.version, source: typeof entry.source?.path === "string" ? entry.source.path : void 0, installed: entry.installed !== false }] : []
|
|
2935
|
+
)
|
|
2936
|
+
);
|
|
2937
|
+
} catch {
|
|
2938
|
+
return void 0;
|
|
2939
|
+
}
|
|
2940
|
+
}
|
|
2941
|
+
async function listing(context) {
|
|
2942
|
+
const ran = await context.input.exec(["mise", "ls", "--current", "--json"], context.path, { quiet: true, ...PLAIN });
|
|
2943
|
+
return ran.status === 0 ? parseListing(ran.stdout) : void 0;
|
|
2944
|
+
}
|
|
2945
|
+
function refusalNote(context) {
|
|
2946
|
+
const named = context.input.refusals().slice(context.refusalsBefore).slice(0, REFUSALS_NAMED2).map((r) => r.range === "not-allowed" ? `${r.host} (not in runner.build.allowHosts)` : `${r.host} (${r.range})`);
|
|
2947
|
+
return named.length === 0 ? "" : `; the build's tunnel refused ${named.join(", ")}`;
|
|
2948
|
+
}
|
|
2949
|
+
function line(context, text) {
|
|
2950
|
+
context.input.log.line(`${context.input.tag} runtimes ${context.entry.repository}: ${text}`);
|
|
2951
|
+
}
|
|
2952
|
+
var installWithMise = async (context) => {
|
|
2953
|
+
const { input, entry, path } = context;
|
|
2954
|
+
context.before = await listing(context) ?? [];
|
|
2955
|
+
const installed = await input.exec(["mise", "install"], path, PLAIN);
|
|
2956
|
+
if (installed.status !== 0) {
|
|
2957
|
+
const missing = context.before.filter((r) => !r.installed).map((r) => `${r.tool} ${r.version} (from ${describeSource(r.source, path)})`);
|
|
2958
|
+
const what = missing.length === 0 ? `mise install failed in ${entry.repository} (exit ${installed.status})${firstLine4(installed.stderr) === "" ? "" : `: ${firstLine4(installed.stderr)}`}` : `mise could not install ${missing.join(", ")} in ${entry.repository} (exit ${installed.status})${toolFailure(installed.stderr) === "" ? "" : `: ${toolFailure(installed.stderr)}`}`;
|
|
2959
|
+
return `runtime_install_failed: ${what}${refusalNote(context)}`;
|
|
2960
|
+
}
|
|
2961
|
+
const after = await listing(context);
|
|
2962
|
+
if (after === void 0) return `runtime_install_failed: mise installed the tools but its listing failed in ${entry.repository}${refusalNote(context)}`;
|
|
2963
|
+
context.resolved = after;
|
|
2964
|
+
for (const r of context.resolved) line(context, `${r.tool} ${r.version} from ${describeSource(r.source, path)}`);
|
|
2965
|
+
return void 0;
|
|
2966
|
+
};
|
|
2967
|
+
var goToolchain = async (context) => {
|
|
2968
|
+
if (!context.files.has("go.mod")) return void 0;
|
|
2969
|
+
const ran = await context.input.exec(["go", "version"], context.path);
|
|
2970
|
+
if (ran.status !== 0) return `runtime_install_failed: go version failed in ${context.entry.repository} (exit ${ran.status})${firstLine4(ran.stderr) === "" ? "" : `: ${firstLine4(ran.stderr)}`}${refusalNote(context)}`;
|
|
2971
|
+
const version = /\bgo(\d+\.\d+(?:\.\d+)?\S*)/.exec(ran.stdout)?.[1];
|
|
2972
|
+
line(context, `go ${version ?? firstLine4(ran.stdout)} from go.mod`);
|
|
2973
|
+
return void 0;
|
|
2974
|
+
};
|
|
2975
|
+
var rustToolchain = async (context) => {
|
|
2976
|
+
const pin = RUST_PIN_FILES.find((file) => context.files.has(file));
|
|
2977
|
+
if (pin === void 0) return void 0;
|
|
2978
|
+
const ran = await context.input.exec(["rustc", "--version"], context.path);
|
|
2979
|
+
if (ran.status !== 0) return `runtime_install_failed: rustc --version failed in ${context.entry.repository} (exit ${ran.status})${firstLine4(ran.stderr) === "" ? "" : `: ${firstLine4(ran.stderr)}`}${refusalNote(context)}`;
|
|
2980
|
+
const version = /\brustc (\S+)/.exec(ran.stdout)?.[1];
|
|
2981
|
+
line(context, `rust ${version ?? firstLine4(ran.stdout)} from ${pin}`);
|
|
2982
|
+
return void 0;
|
|
2983
|
+
};
|
|
2984
|
+
var CHECKOUT_STEPS = [installWithMise, goToolchain, rustToolchain];
|
|
2985
|
+
function unpinnedIn(context) {
|
|
2986
|
+
const used = new Set([...context.files].map((file) => MANIFESTS[file]));
|
|
2987
|
+
const pinned = new Set(context.resolved.filter((r) => r.source?.startsWith(`${context.path}/`)).map((r) => r.tool));
|
|
2988
|
+
pinned.add("go");
|
|
2989
|
+
if (RUST_PIN_FILES.some((file) => context.files.has(file))) pinned.add("rust");
|
|
2990
|
+
return RUNTIMES.filter((runtime) => used.has(runtime) && !pinned.has(runtime));
|
|
2991
|
+
}
|
|
2992
|
+
async function provisionRuntimes(input) {
|
|
2993
|
+
const unpinned = {};
|
|
2994
|
+
let dropProxyWarning = false;
|
|
2995
|
+
for (const entry of input.repositories) {
|
|
2996
|
+
if (input.aborted?.() === true) return { ok: false, reason: "", aborted: true };
|
|
2997
|
+
const path = checkoutPath(entry);
|
|
2998
|
+
const listed = await input.exec(["ls", "-1", "-A"], path, { quiet: true });
|
|
2999
|
+
const context = {
|
|
3000
|
+
input,
|
|
3001
|
+
entry,
|
|
3002
|
+
path,
|
|
3003
|
+
files: new Set(listed.status === 0 ? listed.stdout.split("\n").map((name) => name.trim()) : []),
|
|
3004
|
+
refusalsBefore: input.refusals().length,
|
|
3005
|
+
before: [],
|
|
3006
|
+
resolved: []
|
|
3007
|
+
};
|
|
3008
|
+
for (const step of CHECKOUT_STEPS) {
|
|
3009
|
+
const reason = await step(context);
|
|
3010
|
+
if (reason !== void 0) return { ok: false, reason };
|
|
3011
|
+
}
|
|
3012
|
+
unpinned[entry.repository] = unpinnedIn(context);
|
|
3013
|
+
const old = context.resolved.find((r) => r.tool === "node" && !nodeAcceptsProxyWarningFlag(r.version));
|
|
3014
|
+
if (old !== void 0) {
|
|
3015
|
+
dropProxyWarning = true;
|
|
3016
|
+
line(context, `leaving ${PROXY_WARNING_FLAG} out of NODE_OPTIONS because node ${old.version} does not accept it`);
|
|
3017
|
+
}
|
|
3018
|
+
}
|
|
3019
|
+
return { ok: true, unpinned, dropProxyWarning };
|
|
3020
|
+
}
|
|
3021
|
+
function runtimeStepInput(report, services, dropProxyWarning) {
|
|
3022
|
+
return report.base === void 0 ? {} : { runtimes: { refusals: () => services.record().refusals, dropProxyWarning } };
|
|
3023
|
+
}
|
|
3024
|
+
function keepUnpinnedRuntimes(state, steps) {
|
|
3025
|
+
if (steps.unpinnedRuntimes !== void 0) state.unpinnedRuntimes = steps.unpinnedRuntimes;
|
|
3026
|
+
}
|
|
3027
|
+
|
|
2748
3028
|
// src/runner/build-steps.ts
|
|
2749
3029
|
var aborted = () => ({ ok: false, reason: "", aborted: true });
|
|
2750
|
-
function
|
|
3030
|
+
function firstLine5(text) {
|
|
2751
3031
|
return text.trim().split("\n")[0] ?? "";
|
|
2752
3032
|
}
|
|
2753
3033
|
function gitErrorLine(text) {
|
|
2754
|
-
const lines = text.split("\n").map((
|
|
2755
|
-
return lines.find((
|
|
3034
|
+
const lines = text.split("\n").map((line2) => line2.trim()).filter((line2) => line2 !== "");
|
|
3035
|
+
return lines.find((line2) => /^(fatal|error):/.test(line2)) ?? lines.at(-1) ?? "";
|
|
2756
3036
|
}
|
|
2757
3037
|
var STAGED_TREE = `${JOB_MOUNT}/context/tree`;
|
|
2758
3038
|
var DELIVER_SCRIPT = [
|
|
@@ -2768,7 +3048,7 @@ var DELIVER_SCRIPT = [
|
|
|
2768
3048
|
var RECORD_SCRIPT = 'd="$(git rev-parse --git-common-dir)" && mkdir -p "$d/outerlayer" && printf "%s" "$1" > "$d/outerlayer/delivery.json"';
|
|
2769
3049
|
var WRITE_SHIM_SCRIPT = 'mkdir -p "$1" && printf "%s" "$2" > "$1/claude" && chmod 755 "$1/claude"';
|
|
2770
3050
|
function failure(what, result) {
|
|
2771
|
-
return `context_delivery_failed: ${what} (exit ${result.status})${
|
|
3051
|
+
return `context_delivery_failed: ${what} (exit ${result.status})${firstLine5(result.stderr) === "" ? "" : `: ${firstLine5(result.stderr)}`}`;
|
|
2772
3052
|
}
|
|
2773
3053
|
async function repositorySkills(input, folder) {
|
|
2774
3054
|
const listed = await input.exec(["ls", "-1", folder], CHECKOUT_DIR, { quiet: true });
|
|
@@ -2870,6 +3150,14 @@ async function runBuildSteps(input) {
|
|
|
2870
3150
|
if (!checked.ok) return checked;
|
|
2871
3151
|
}
|
|
2872
3152
|
if (input.governing !== void 0) await noteIgnoredDevcontainers(input, repositories, input.governing.repository);
|
|
3153
|
+
let unpinnedRuntimes;
|
|
3154
|
+
if (input.runtimes !== void 0) {
|
|
3155
|
+
const ordered = [{ ...primary, primary: true }, ...repositories.filter((candidate) => candidate.repository !== primary.repository).map((entry) => ({ ...entry, primary: false }))];
|
|
3156
|
+
const chosen = await provisionRuntimes({ repositories: ordered, exec, log, tag, refusals: input.runtimes.refusals, aborted: input.aborted });
|
|
3157
|
+
if (!chosen.ok) return chosen.aborted === true ? aborted() : { ok: false, reason: chosen.reason };
|
|
3158
|
+
unpinnedRuntimes = chosen.unpinned;
|
|
3159
|
+
if (chosen.dropProxyWarning) input.runtimes.dropProxyWarning();
|
|
3160
|
+
}
|
|
2873
3161
|
const lifecycleDir = lifecycleWorkdir(repositories, input.governing?.repository);
|
|
2874
3162
|
for (const step of lifecycleSteps(input.lifecycle)) {
|
|
2875
3163
|
if (input.aborted()) return aborted();
|
|
@@ -2914,7 +3202,7 @@ async function runBuildSteps(input) {
|
|
|
2914
3202
|
}
|
|
2915
3203
|
if (input.aborted()) return aborted();
|
|
2916
3204
|
}
|
|
2917
|
-
return { ok: true, startCommit, ...controlPlane === void 0 ? {} : { controlPlane } };
|
|
3205
|
+
return { ok: true, startCommit, ...controlPlane === void 0 ? {} : { controlPlane }, ...unpinnedRuntimes === void 0 ? {} : { unpinnedRuntimes } };
|
|
2918
3206
|
}
|
|
2919
3207
|
var EVAL_INPUT_NAME = "eval-input";
|
|
2920
3208
|
var TRANSCRIPT_ROOT = "/build/home/.claude/projects";
|
|
@@ -2923,7 +3211,7 @@ var MAX_TRANSCRIPTS = 500;
|
|
|
2923
3211
|
var MAX_TOTAL_TRANSCRIPT_BYTES = 64 * 1024 * 1024;
|
|
2924
3212
|
var TRANSCRIPT_COPY_MS = 2 * 60 * 1e3;
|
|
2925
3213
|
var BUILD_HOME = "/build/home";
|
|
2926
|
-
function
|
|
3214
|
+
function firstLine6(text) {
|
|
2927
3215
|
return text.trim().split("\n")[0] ?? "";
|
|
2928
3216
|
}
|
|
2929
3217
|
async function copyTranscripts(run, now = Date.now) {
|
|
@@ -2935,7 +3223,7 @@ async function copyTranscripts(run, now = Date.now) {
|
|
|
2935
3223
|
return { ok: false, reason: describeCallFailure(err) };
|
|
2936
3224
|
}
|
|
2937
3225
|
if (listed.status !== 0 && !/No such file or directory/.test(listed.stderr)) {
|
|
2938
|
-
return { ok: false, reason: `listing the transcripts failed (exit ${listed.status})${
|
|
3226
|
+
return { ok: false, reason: `listing the transcripts failed (exit ${listed.status})${firstLine6(listed.stderr) === "" ? "" : `: ${firstLine6(listed.stderr)}`}` };
|
|
2939
3227
|
}
|
|
2940
3228
|
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();
|
|
2941
3229
|
const copied = [];
|
|
@@ -2952,7 +3240,7 @@ async function copyTranscripts(run, now = Date.now) {
|
|
|
2952
3240
|
}
|
|
2953
3241
|
try {
|
|
2954
3242
|
const read = await run(["head", "-c", String(MAX_TRANSCRIPT_BYTES + 1), `${TRANSCRIPT_ROOT}/${path}`]);
|
|
2955
|
-
if (read.status !== 0) missed.push({ path, reason: `reading it failed (exit ${read.status})${
|
|
3243
|
+
if (read.status !== 0) missed.push({ path, reason: `reading it failed (exit ${read.status})${firstLine6(read.stderr) === "" ? "" : `: ${firstLine6(read.stderr)}`}` });
|
|
2956
3244
|
else if (Buffer.byteLength(read.stdout) > MAX_TRANSCRIPT_BYTES) missed.push({ path, reason: `it is larger than ${MAX_TRANSCRIPT_BYTES / (1024 * 1024)} MiB` });
|
|
2957
3245
|
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` });
|
|
2958
3246
|
else {
|
|
@@ -2996,11 +3284,11 @@ function scrubbing(scrub, author, work) {
|
|
|
2996
3284
|
setRepoRoot(void 0);
|
|
2997
3285
|
}
|
|
2998
3286
|
}
|
|
2999
|
-
function scrubLine(
|
|
3287
|
+
function scrubLine(line2) {
|
|
3000
3288
|
try {
|
|
3001
|
-
return JSON.stringify(scrubDeep(JSON.parse(
|
|
3289
|
+
return JSON.stringify(scrubDeep(JSON.parse(line2)));
|
|
3002
3290
|
} catch {
|
|
3003
|
-
return scrubText(
|
|
3291
|
+
return scrubText(line2);
|
|
3004
3292
|
}
|
|
3005
3293
|
}
|
|
3006
3294
|
function writeReadOnly(path, text) {
|
|
@@ -3074,7 +3362,7 @@ async function writeEvalInput(request) {
|
|
|
3074
3362
|
continue;
|
|
3075
3363
|
}
|
|
3076
3364
|
const file = `sessions/${traceId}.jsonl`;
|
|
3077
|
-
const text = transcript.content.split("\n").filter((
|
|
3365
|
+
const text = transcript.content.split("\n").filter((line2) => line2.trim() !== "").map(scrubLine).join("\n");
|
|
3078
3366
|
writeReadOnly(join(dir, file), `${text}
|
|
3079
3367
|
`);
|
|
3080
3368
|
scrubDeep(session);
|
|
@@ -3501,8 +3789,8 @@ async function deliverTar(runtime, state, input) {
|
|
|
3501
3789
|
{ timeoutMs: DELIVERY_TIMEOUT_MS }
|
|
3502
3790
|
);
|
|
3503
3791
|
if (result.status === 0) return { ok: true };
|
|
3504
|
-
const
|
|
3505
|
-
return { ok: false, reason: `${input.step} could not be delivered (exit ${result.status})${
|
|
3792
|
+
const line2 = scrubDelivery(result.stderr.trim().split("\n")[0] ?? "", input.secrets);
|
|
3793
|
+
return { ok: false, reason: `${input.step} could not be delivered (exit ${result.status})${line2 === "" ? "" : `: ${line2}`}` };
|
|
3506
3794
|
} catch (err) {
|
|
3507
3795
|
return { ok: false, reason: `${input.step} could not be delivered: ${scrubDelivery(describeCallFailure(err), input.secrets)}` };
|
|
3508
3796
|
}
|
|
@@ -3625,18 +3913,18 @@ function parse(data) {
|
|
|
3625
3913
|
const length = Number.parseInt(header, 16);
|
|
3626
3914
|
if (length === 0) return { kind: "commands", commands, capabilities };
|
|
3627
3915
|
if (data.length - offset < length) return { kind: "need-more" };
|
|
3628
|
-
const
|
|
3916
|
+
const line2 = data.subarray(offset + 4, offset + length);
|
|
3629
3917
|
offset += length;
|
|
3630
3918
|
if (offset > limits().sectionBytes) return refused(TOO_LONG);
|
|
3631
3919
|
const first = commands.length === 0;
|
|
3632
|
-
const nul =
|
|
3633
|
-
const decoded = decodeText(first && nul !== -1 ?
|
|
3920
|
+
const nul = line2.indexOf(0);
|
|
3921
|
+
const decoded = decodeText(first && nul !== -1 ? line2.subarray(0, nul) : line2);
|
|
3634
3922
|
if (decoded === void 0) return refused(UNREADABLE);
|
|
3635
3923
|
const text = decoded.replace(/\n$/, "");
|
|
3636
3924
|
if (first && text.startsWith("shallow ")) continue;
|
|
3637
3925
|
const match = COMMAND.exec(text);
|
|
3638
3926
|
if (match === null) return refused(UNREADABLE);
|
|
3639
|
-
if (first && nul !== -1) capabilities =
|
|
3927
|
+
if (first && nul !== -1) capabilities = line2.subarray(nul + 1).toString("latin1").split(/\s+/).filter((word) => word !== "");
|
|
3640
3928
|
commands.push({ oldId: match[1], newId: match[2], ref: match[3] });
|
|
3641
3929
|
}
|
|
3642
3930
|
}
|
|
@@ -3790,7 +4078,7 @@ function createGitRemote(options) {
|
|
|
3790
4078
|
const claimed = options.repositories ?? (options.repository === void 0 || options.branch === void 0 || options.mirrorDir === void 0 ? [] : [{ repository: options.repository, branch: options.branch, mirrorDir: options.mirrorDir }]);
|
|
3791
4079
|
const maxLfsBodyBytes = 1024 * 1024;
|
|
3792
4080
|
const hopByHop = /* @__PURE__ */ new Set(["connection", "keep-alive", "transfer-encoding", "upgrade", "proxy-authenticate", "proxy-authorization", "te", "trailer", "set-cookie"]);
|
|
3793
|
-
const log = (
|
|
4081
|
+
const log = (line2) => options.log?.(line2);
|
|
3794
4082
|
function forward(input) {
|
|
3795
4083
|
const { route, res } = input;
|
|
3796
4084
|
const url = new URL(`${gitUrl}/${route.owner}/${route.name}.git/${route.kind === "info-refs" ? "info/refs" : route.kind === "lfs-batch" ? "info/lfs/objects/batch" : `git-${route.kind}`}${route.search === "" ? "" : `?${route.search}`}`);
|
|
@@ -4208,7 +4496,7 @@ function gitRemoteFor(runtime, input) {
|
|
|
4208
4496
|
...input.readOnly === true ? { readOnly: true } : {}
|
|
4209
4497
|
});
|
|
4210
4498
|
}
|
|
4211
|
-
function
|
|
4499
|
+
function firstLine7(text) {
|
|
4212
4500
|
return text.trim().split("\n")[0] ?? "";
|
|
4213
4501
|
}
|
|
4214
4502
|
var NO_ENV = { literals: {}, passed: {} };
|
|
@@ -4272,7 +4560,7 @@ async function obtainImage(input) {
|
|
|
4272
4560
|
};
|
|
4273
4561
|
}
|
|
4274
4562
|
try {
|
|
4275
|
-
const common = { repository, configPath: config.configPath, readToken, pinned: input.pinned, log: (
|
|
4563
|
+
const common = { repository, configPath: config.configPath, readToken, pinned: input.pinned, log: (line2) => log.line(`${tag} ${line2}`) };
|
|
4276
4564
|
if (input.inBuilder !== void 0) {
|
|
4277
4565
|
return { ok: true, built: await runtime.buildRootDisk({ ...input.inBuilder, ...common, guestHelper: input.guestHelper, deadlineMs: input.deadlineMs }) };
|
|
4278
4566
|
}
|
|
@@ -4410,7 +4698,7 @@ async function provisionContainer(input) {
|
|
|
4410
4698
|
}
|
|
4411
4699
|
return aborted2 ? { ok: false, reason: "ended before provision finished", aborted: true } : fail(reason);
|
|
4412
4700
|
};
|
|
4413
|
-
const dockerFailed = (what, result) => bail(`${what} failed (exit ${result.status})${
|
|
4701
|
+
const dockerFailed = (what, result) => bail(`${what} failed (exit ${result.status})${firstLine7(result.stderr) === "" ? "" : `: ${firstLine7(result.stderr)}`}`);
|
|
4414
4702
|
if (input.aborted()) return bail("", true);
|
|
4415
4703
|
mkdirSync(buildDir2, { recursive: true });
|
|
4416
4704
|
const ghDir = ghConfigDir(buildDir2);
|
|
@@ -4441,8 +4729,8 @@ async function provisionContainer(input) {
|
|
|
4441
4729
|
environment.credentials = tokens.used();
|
|
4442
4730
|
let services;
|
|
4443
4731
|
try {
|
|
4444
|
-
const gitRemote = gitRemoteFor(runtime, { repositories, tokens, buildDir: buildDir2, log: (
|
|
4445
|
-
services = await startServicesFor(runtime, config, buildDir2, jobDir, itemKey, true, gitRemote, "stream", input.leaseExpiryMs === void 0 ? void 0 : leaseFor(runtime, buildId, input.leaseExpiryMs), void 0, (
|
|
4732
|
+
const gitRemote = gitRemoteFor(runtime, { repositories, tokens, buildDir: buildDir2, log: (line2) => log.line(`${tag} ${line2}`) });
|
|
4733
|
+
services = await startServicesFor(runtime, config, buildDir2, jobDir, itemKey, true, gitRemote, "stream", input.leaseExpiryMs === void 0 ? void 0 : leaseFor(runtime, buildId, input.leaseExpiryMs), void 0, (line2) => log.line(`${tag} ${line2}`));
|
|
4446
4734
|
runtime.tunnels.set(buildId, services);
|
|
4447
4735
|
} catch (err) {
|
|
4448
4736
|
return bail(`the tunnel could not start: ${describeCallFailure(err)}`);
|
|
@@ -4469,7 +4757,7 @@ async function provisionContainer(input) {
|
|
|
4469
4757
|
if (prepared.status !== 0) return dockerFailed("preparing the build's volume", prepared);
|
|
4470
4758
|
const started = await host.run(containerRunArgs(runInput), { logPath });
|
|
4471
4759
|
if (started.status !== 0) return dockerFailed("starting the build's container", started);
|
|
4472
|
-
joinBuild(runtime, state, services, (
|
|
4760
|
+
joinBuild(runtime, state, services, (line2) => log.line(`${tag} ${line2}`));
|
|
4473
4761
|
if (input.aborted()) return bail("", true);
|
|
4474
4762
|
if (!await waitForRelay(runtime, state)) return bail("the relay in the build's container did not start");
|
|
4475
4763
|
const ghDelivered = await deliverJobFiles(runtime, state, ["gh", "maven"], secrets);
|
|
@@ -4506,9 +4794,10 @@ async function provisionContainer(input) {
|
|
|
4506
4794
|
const hashed = program.status === 0 ? parseProgramHash(program.stdout) : void 0;
|
|
4507
4795
|
if (hashed !== void 0) state.judgeProgram = { path: JUDGE_PROGRAM, sha256: hashed };
|
|
4508
4796
|
input.save(state, environment);
|
|
4509
|
-
|
|
4797
|
+
let execEnv = buildEnvironment({ ...envInput, imageEnv: state.imageEnv });
|
|
4510
4798
|
for (const notice of execEnv.notices) log.line(`${tag} ${notice}`);
|
|
4511
|
-
const
|
|
4799
|
+
const plainEnv = buildEnvironment({ ...envInput, imageEnv: state.imageEnv, proxyWarning: false });
|
|
4800
|
+
const exec = (argv, workdir, opts) => host.exec({ container: name, user: agentUser, workdir, env: opts?.withoutProxyWarning === true ? plainEnv : execEnv, argv }, opts?.quiet === true ? void 0 : { logPath });
|
|
4512
4801
|
const steps = await runBuildSteps({
|
|
4513
4802
|
repository,
|
|
4514
4803
|
branch: primary.branch,
|
|
@@ -4539,10 +4828,16 @@ async function provisionContainer(input) {
|
|
|
4539
4828
|
},
|
|
4540
4829
|
removeStagedContext: () => removeStagedContext(buildDir2),
|
|
4541
4830
|
keepIn: jobDir,
|
|
4542
|
-
...input.requireBuildSkill === true ? { requireBuildSkill: true } : {}
|
|
4831
|
+
...input.requireBuildSkill === true ? { requireBuildSkill: true } : {},
|
|
4832
|
+
// A repository with no devcontainer file builds on the universal image, whose runtimes the build chooses and installs.
|
|
4833
|
+
...runtimeStepInput(report, services, () => {
|
|
4834
|
+
state.proxyWarningDropped = true;
|
|
4835
|
+
execEnv = plainEnv;
|
|
4836
|
+
})
|
|
4543
4837
|
});
|
|
4544
4838
|
if (!steps.ok) return bail(steps.reason, steps.aborted === true);
|
|
4545
4839
|
state.startCommit = steps.startCommit;
|
|
4840
|
+
keepUnpinnedRuntimes(state, steps);
|
|
4546
4841
|
if (steps.controlPlane !== void 0) environment.controlPlane = steps.controlPlane;
|
|
4547
4842
|
return { ok: true, workdir: CHECKOUT_DIR, state, environment };
|
|
4548
4843
|
}
|
|
@@ -4568,9 +4863,11 @@ function containerCommandExec(input) {
|
|
|
4568
4863
|
repositories: input.job.repositories,
|
|
4569
4864
|
hostEnv: input.runtime.hostEnv,
|
|
4570
4865
|
containerEnv: state.containerEnv ?? {},
|
|
4866
|
+
unpinnedRuntimes: state.unpinnedRuntimes,
|
|
4571
4867
|
builtIns: state.builtIns === true,
|
|
4572
4868
|
identity: input.job.commitIdentity,
|
|
4573
|
-
imageEnv: state.imageEnv
|
|
4869
|
+
imageEnv: state.imageEnv,
|
|
4870
|
+
proxyWarning: state.proxyWarningDropped !== true
|
|
4574
4871
|
});
|
|
4575
4872
|
return {
|
|
4576
4873
|
container: state.container,
|
|
@@ -4592,9 +4889,11 @@ function containerSenderCommand(input) {
|
|
|
4592
4889
|
repositories: input.job.repositories,
|
|
4593
4890
|
hostEnv: input.runtime.hostEnv,
|
|
4594
4891
|
containerEnv: state.containerEnv ?? {},
|
|
4892
|
+
unpinnedRuntimes: state.unpinnedRuntimes,
|
|
4595
4893
|
builtIns: state.builtIns === true,
|
|
4596
4894
|
identity: input.job.commitIdentity,
|
|
4597
|
-
imageEnv: state.imageEnv
|
|
4895
|
+
imageEnv: state.imageEnv,
|
|
4896
|
+
proxyWarning: state.proxyWarningDropped !== true
|
|
4598
4897
|
});
|
|
4599
4898
|
const args = containerExecArgs({
|
|
4600
4899
|
container: state.container,
|
|
@@ -4658,6 +4957,7 @@ async function startServicesFor(runtime, config, buildDir2, jobDir, itemKey, bui
|
|
|
4658
4957
|
destinations: config.build?.destinations ?? [],
|
|
4659
4958
|
// A managed build's tunnel allows the factory's hosts beside the runner's own.
|
|
4660
4959
|
allowHosts: withFactoryHosts(config.build?.allowHosts, managedBuildSettingsFor(settingsDir ?? jobDir)),
|
|
4960
|
+
...optionalEgress(config),
|
|
4661
4961
|
serve,
|
|
4662
4962
|
...lease === void 0 ? {} : { lease },
|
|
4663
4963
|
...inherit === void 0 ? {} : { inherit },
|
|
@@ -4722,9 +5022,11 @@ async function syncInContainer(input) {
|
|
|
4722
5022
|
repositories: job.repositories,
|
|
4723
5023
|
hostEnv: runtime.hostEnv,
|
|
4724
5024
|
containerEnv: state.containerEnv ?? {},
|
|
5025
|
+
unpinnedRuntimes: state.unpinnedRuntimes,
|
|
4725
5026
|
builtIns: state.builtIns === true,
|
|
4726
5027
|
identity: job.commitIdentity,
|
|
4727
|
-
imageEnv: state.imageEnv
|
|
5028
|
+
imageEnv: state.imageEnv,
|
|
5029
|
+
proxyWarning: state.proxyWarningDropped !== true
|
|
4728
5030
|
});
|
|
4729
5031
|
const result = await runtime.host.exec(
|
|
4730
5032
|
{ container: state.container, user: state.agentUser ?? ADDED_USER, workdir: job.workdir ?? CHECKOUT_DIR, env, argv: ["outerlayer", "sync"] },
|
|
@@ -4799,7 +5101,7 @@ function containerJudgeEnvironment(input) {
|
|
|
4799
5101
|
env: NO_ENV,
|
|
4800
5102
|
argv: ["/bin/sh", "-c", `[ -f ${file} ] && [ ! -L ${file} ] && head -c ${maxBytes + 1} ${file}`]
|
|
4801
5103
|
}, { timeoutMs: REPORT_READ_TIMEOUT_MS });
|
|
4802
|
-
if (read.status > 1) throw new Error(`reading the judge's ${name} exited ${read.status}: ${
|
|
5104
|
+
if (read.status > 1) throw new Error(`reading the judge's ${name} exited ${read.status}: ${firstLine7(read.stderr)}`);
|
|
4803
5105
|
return read.status === 0 && Buffer.byteLength(read.stdout) <= maxBytes ? read.stdout : void 0;
|
|
4804
5106
|
};
|
|
4805
5107
|
return {
|
|
@@ -4817,7 +5119,7 @@ function containerJudgeEnvironment(input) {
|
|
|
4817
5119
|
hashProgram: async () => {
|
|
4818
5120
|
const ran = await runtime.host.exec({ container: state.container, user: ADDED_USER, env: NO_ENV, argv: [...HASH_ARGV] });
|
|
4819
5121
|
const sha256 = ran.status === 0 ? parseProgramHash(ran.stdout) : void 0;
|
|
4820
|
-
return sha256 === void 0 ? { ok: false, reason:
|
|
5122
|
+
return sha256 === void 0 ? { ok: false, reason: firstLine7(ran.stderr) || `the hash could not be taken (exit ${ran.status})` } : { ok: true, sha256 };
|
|
4821
5123
|
},
|
|
4822
5124
|
prepare: async (files, tree) => {
|
|
4823
5125
|
if (filesAreCopied(state)) {
|
|
@@ -4850,7 +5152,7 @@ function containerJudgeEnvironment(input) {
|
|
|
4850
5152
|
// host. Every capability is dropped in the container, so root there could not either; the build's user removes its own, and the runner removes the rest.
|
|
4851
5153
|
clear: async () => {
|
|
4852
5154
|
const removed = await runtime.host.exec({ container: state.container, user, env: NO_ENV, argv: ["find", JUDGE_DIR, "-mindepth", "1", "-user", user, "-delete"] });
|
|
4853
|
-
if (removed.status !== 0) throw new Error(`find exited ${removed.status}: ${
|
|
5155
|
+
if (removed.status !== 0) throw new Error(`find exited ${removed.status}: ${firstLine7(removed.stderr)}`);
|
|
4854
5156
|
if (!filesAreCopied(state)) return;
|
|
4855
5157
|
const emptied = await clearJudgeFolder(runtime, state, secretsOf(runtime, input.jobDir));
|
|
4856
5158
|
if (!emptied.ok) throw new Error(emptied.reason);
|
|
@@ -4906,7 +5208,7 @@ async function startCheckContainer(input) {
|
|
|
4906
5208
|
}
|
|
4907
5209
|
return { ok: false, reason };
|
|
4908
5210
|
};
|
|
4909
|
-
const dockerFailed = (what, result) => fail(`${what} failed (exit ${result.status})${
|
|
5211
|
+
const dockerFailed = (what, result) => fail(`${what} failed (exit ${result.status})${firstLine7(result.stderr) === "" ? "" : `: ${firstLine7(result.stderr)}`}`);
|
|
4910
5212
|
mkdirSync(buildDir2, { recursive: true });
|
|
4911
5213
|
if (!filesAreCopied(state)) chmodSync(buildDir2, 493);
|
|
4912
5214
|
let services;
|
|
@@ -4915,7 +5217,7 @@ async function startCheckContainer(input) {
|
|
|
4915
5217
|
repositories: repositoriesOf({ repositories: job.repositories, repository, branch: job.branch }),
|
|
4916
5218
|
tokens,
|
|
4917
5219
|
buildDir: buildDir2,
|
|
4918
|
-
log: (
|
|
5220
|
+
log: (line2) => log.line(`${tag} ${line2}`),
|
|
4919
5221
|
readOnly: true
|
|
4920
5222
|
});
|
|
4921
5223
|
services = await startServicesFor(runtime, config, buildDir2, checksDir, void 0, false, gitRemote, transport === "exec" ? "stream" : "socket");
|
|
@@ -4944,7 +5246,7 @@ async function startCheckContainer(input) {
|
|
|
4944
5246
|
if (prepared.status !== 0) return dockerFailed("preparing the check environment's volume", prepared);
|
|
4945
5247
|
const started = await host.run(containerRunArgs(runInput), { logPath });
|
|
4946
5248
|
if (started.status !== 0) return dockerFailed("starting the check environment's container", started);
|
|
4947
|
-
if (transport === "exec") joinBuild(runtime, state, services, (
|
|
5249
|
+
if (transport === "exec") joinBuild(runtime, state, services, (line2) => log.line(`${tag} ${line2}`));
|
|
4948
5250
|
if (!await waitForRelay(runtime, state)) return fail("the relay in the check environment's container did not start");
|
|
4949
5251
|
const env = checkEnvironment({ config, item: job.item, repository, hostEnv: runtime.hostEnv, containerEnv: built.containerEnv ?? {}, imageEnv: built.imageEnv });
|
|
4950
5252
|
const secrets = () => tokens.issuedTokens();
|
|
@@ -4973,7 +5275,7 @@ async function startCheckContainer(input) {
|
|
|
4973
5275
|
await host.stop(name);
|
|
4974
5276
|
const again = await host.start(name);
|
|
4975
5277
|
if (again.status !== 0 || !await waitForRelay(runtime, state)) return false;
|
|
4976
|
-
rejoinBuild(runtime, state, (
|
|
5278
|
+
rejoinBuild(runtime, state, (line2) => log.line(`${tag} ${line2}`));
|
|
4977
5279
|
if (delivered) {
|
|
4978
5280
|
const again2 = await deliverInput();
|
|
4979
5281
|
if (!again2.ok) {
|
|
@@ -4990,8 +5292,8 @@ async function startCheckContainer(input) {
|
|
|
4990
5292
|
// src/runner/machine.ts
|
|
4991
5293
|
function groupName(gid) {
|
|
4992
5294
|
try {
|
|
4993
|
-
for (const
|
|
4994
|
-
const [name, , id] =
|
|
5295
|
+
for (const line2 of readFileSync("/etc/group", "utf8").split("\n")) {
|
|
5296
|
+
const [name, , id] = line2.split(":");
|
|
4995
5297
|
if (name !== void 0 && Number(id) === gid) return name;
|
|
4996
5298
|
}
|
|
4997
5299
|
} catch {
|
|
@@ -5086,4 +5388,4 @@ function describeMachineDocker(machine) {
|
|
|
5086
5388
|
return `Docker Engine ${version ?? "of no known version"}, older than the ${MIN_ENGINE_MAJOR} that container builds need`;
|
|
5087
5389
|
}
|
|
5088
5390
|
|
|
5089
|
-
export { ADDED_USER, ADOPTED_FETCH_RETRY_WINDOW_MS, AgentUserError, AssetError, DeliveryFailure, EVAL_INPUT_NAME, GH_CONFIG_YML, HELPER_ENV, LEASE_SECONDS, MANAGED_UNJAILED_REASON, MIN_ENGINE_MAJOR, PLACEHOLDER_MARKER, ROOT_DISK_ID_PREFIX, RunnerInitError, attemptNote, claimPermissionProblem, claudeCredentialCheck, cleanupContainer, closeHostBuild, containerCommandExec, containerJudgeEnvironment, containerSenderCommand, copyJudgeTree, copyTranscripts, copyTranscriptsFromContainer, createBuildDisk, createContainerRuntime, createLeaseChannel, currentSkillCommand, decideHostBuildSkill, deleteBuildDisk, deliverContainerHooks, deliverExecMaven, describeMachineDocker, detectMachine, dropManagedBuildSettings, dropManagedClaudeKey, ensureFirecrackerAndJailer, ensureRootfs, ensureTunnel, execArgv, execCommandLine, fetchManagedBuildSettings, fetchManagedClaudeKey, filesAreCopied, formerSkillProblem, formerSkillQueues, ghHostsYml, gitRemoteFor, hasClaudeCredential, helperFirecrackerNote, helperSocketPath, holdManagedBuildSettings, holdManagedClaudeKey, hostCommandEnvironment, hostEnvironment, isPlaceholderCommand, keepGhConfigCurrent, leaseExpiresAtMs, leaseTimeLeftMs, lifecycleFailureReason, lifecycleSteps, listenOnBroker, machineConfig, makeBuildsDirPrivate, managedBuildSettingValues, managedBuildSettingsFor, managedClaudeKeyFor, managedClaudeKeyValues, managedMachineLimits, measureDisk, microVmArchSupported, microVmAssetsPinned, missingPermissionFix, missingPermissionOf, needsBuildSkill, needsClaudeCredential, obtainImage, outOfMemoryReason, parseCpuList, permissionModeProblem, permissionModeProblems, placeholderProblem, placeholderQueues, prepareBranch, prepareRunnerInit, probeHelper, provisionContainer, provisionEnvironment, reachDockerStep, readConfigObject, resolveAgentUser, resolveHostBuild, runBuildSteps, runRunnerInit, runWithSpawn, senderAliveScript, senderSignalScript, setUpRunnerCgroup, shellQuote, signalInContainer, startCheckContainer, startHostServices, startJailedInto, startServicesFor, stopContainer, stopJailed, supportsContainerBuilds, supportsMicroVmBuilds, sweepImageBuilders, syncInContainer, withFactoryHosts, withTunnelLog, writeEvalInput, writeRunnerInit };
|
|
5391
|
+
export { ADDED_USER, ADOPTED_FETCH_RETRY_WINDOW_MS, AgentUserError, AssetError, DeliveryFailure, EVAL_INPUT_NAME, GH_CONFIG_YML, HELPER_ENV, LEASE_SECONDS, MANAGED_UNJAILED_REASON, MIN_ENGINE_MAJOR, PLACEHOLDER_MARKER, ROOT_DISK_ID_PREFIX, RunnerInitError, attemptNote, claimPermissionProblem, claudeCredentialCheck, cleanupContainer, closeHostBuild, containerCommandExec, containerJudgeEnvironment, containerSenderCommand, copyJudgeTree, copyTranscripts, copyTranscriptsFromContainer, createBuildDisk, createContainerRuntime, createLeaseChannel, currentSkillCommand, decideHostBuildSkill, deleteBuildDisk, deliverContainerHooks, deliverExecMaven, describeMachineDocker, detectMachine, dropManagedBuildSettings, dropManagedClaudeKey, ensureFirecrackerAndJailer, ensureRootfs, ensureTunnel, execArgv, execCommandLine, fetchManagedBuildSettings, fetchManagedClaudeKey, filesAreCopied, formerSkillProblem, formerSkillQueues, ghHostsYml, gitRemoteFor, hasClaudeCredential, helperFirecrackerNote, helperSocketPath, holdManagedBuildSettings, holdManagedClaudeKey, hostCommandEnvironment, hostEnvironment, isPlaceholderCommand, keepGhConfigCurrent, keepUnpinnedRuntimes, leaseExpiresAtMs, leaseTimeLeftMs, lifecycleFailureReason, lifecycleSteps, listenOnBroker, machineConfig, makeBuildsDirPrivate, managedBuildSettingValues, managedBuildSettingsFor, managedClaudeKeyFor, managedClaudeKeyValues, managedMachineLimits, measureDisk, microVmArchSupported, microVmAssetsPinned, missingPermissionFix, missingPermissionOf, needsBuildSkill, needsClaudeCredential, obtainImage, outOfMemoryReason, parseCpuList, permissionModeProblem, permissionModeProblems, placeholderProblem, placeholderQueues, prepareBranch, prepareRunnerInit, probeHelper, provisionContainer, provisionEnvironment, reachDockerStep, readConfigObject, resolveAgentUser, resolveHostBuild, runBuildSteps, runRunnerInit, runWithSpawn, runtimeStepInput, senderAliveScript, senderSignalScript, setUpRunnerCgroup, shellQuote, signalInContainer, startCheckContainer, startHostServices, startJailedInto, startServicesFor, stopContainer, stopJailed, supportsContainerBuilds, supportsMicroVmBuilds, sweepImageBuilders, syncInContainer, withFactoryHosts, withTunnelLog, writeEvalInput, writeRunnerInit };
|