@outerlayer/cli 0.10.1 → 0.11.0
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 +15 -0
- package/dist/{agent-setup-ODTDC3US.js → agent-setup-YEFN74Y4.js} +6 -3
- package/dist/build-info.json +1 -1
- package/dist/{builder-EVO6F2NO.js → builder-PP436VGZ.js} +2 -2
- package/dist/{check-RBRRI77E.js → check-YDXOLVJ5.js} +17 -16
- package/dist/{chunk-VVIRHTH4.js → chunk-2GBCTEN4.js} +1 -1
- package/dist/{chunk-4AVAETSU.js → chunk-3YFCWYBU.js} +140 -40
- package/dist/{chunk-M6G7TJVF.js → chunk-4Q7OMKAT.js} +44 -4
- package/dist/{chunk-MC6J453K.js → chunk-7C4T5BGN.js} +2 -2
- package/dist/{chunk-47RS42OZ.js → chunk-A56PYPDF.js} +11 -4
- package/dist/{chunk-472KC6JV.js → chunk-BEZSECPA.js} +1 -1
- package/dist/{chunk-KZ5M4QOB.js → chunk-BHOBM3IZ.js} +32 -14
- package/dist/{chunk-JSUUXA5W.js → chunk-CJGQQZWB.js} +1 -1
- package/dist/{chunk-BREEX2Z7.js → chunk-E5DC4VZL.js} +115 -58
- package/dist/{chunk-R2UYH4QV.js → chunk-EOWWTFUU.js} +3 -3
- package/dist/{chunk-PDTSUOVT.js → chunk-FI5UYJMQ.js} +1 -1
- package/dist/{chunk-V42JY4F6.js → chunk-HYZRY4KZ.js} +2 -2
- package/dist/chunk-O765JR4W.js +35 -0
- package/dist/{chunk-6CXYORUS.js → chunk-QKFB4K7X.js} +1 -1
- package/dist/{chunk-ESZJ5QIC.js → chunk-R7BJYFD2.js} +4 -4
- package/dist/{chunk-S6IUUNCD.js → chunk-RSNSZ2LJ.js} +1 -1
- package/dist/{chunk-NTLGWCWK.js → chunk-TFIOXPZT.js} +1 -1
- package/dist/{chunk-M2PBLRB7.js → chunk-XR3BJN33.js} +23 -3
- package/dist/{chunk-ABIWDUMS.js → chunk-YETTWTAY.js} +4 -4
- package/dist/{cli-G6TH4YMK.js → cli-RQZXTOEI.js} +44 -40
- package/dist/{command-LNEFKIVC.js → command-U6UGIBVT.js} +9 -9
- package/dist/config-MKBX2ZQD.js +11 -0
- package/dist/{docker-GM526LGX.js → docker-WVRRMK6R.js} +3 -3
- package/dist/{doctor-QSV4DYT2.js → doctor-ZF4PYWVN.js} +10 -10
- package/dist/{exec-client-QTUO6TZT.js → exec-client-CQV746UF.js} +3 -3
- package/dist/{guest-init-4UW4HM6N.js → guest-init-LJP5GPZF.js} +3 -3
- package/dist/index.js +1 -1
- package/dist/{init-ORDCPTFD.js → init-M5IBAGVE.js} +10 -10
- package/dist/{init-OKCDXEOG.js → init-PUY2BUHH.js} +8 -8
- package/dist/{init-cmd-5TEM2QNH.js → init-cmd-NPNR23UL.js} +1 -1
- package/dist/{install-PYNCWSTV.js → install-HKOVISUP.js} +3 -3
- package/dist/{loop-ZNUQT736.js → loop-3FNROLW7.js} +17 -16
- package/dist/{machine-TBJKZ6TN.js → machine-RWDDJRWB.js} +7 -7
- package/dist/mcp-install-cmd-XZARXNYT.js +9 -0
- package/dist/pending-MXLSRYMO.js +7 -0
- package/dist/{real-deps-LS64D3M6.js → real-deps-KNNBQC75.js} +1 -1
- package/dist/{status-KPDVZMJ6.js → status-2OW5AKWL.js} +17 -9
- package/dist/{work-claim-cmd-DYD6II56.js → work-claim-cmd-LXXSNEGF.js} +3 -3
- package/dist/{work-open-pr-cmd-N2RBDKZ4.js → work-open-pr-cmd-YZAENDP6.js} +5 -4
- package/package.json +1 -1
- package/skill-pack/maintained/amend/SKILL.md +10 -1
- package/skill-pack/maintained/outerlayer/SKILL.md +19 -3
- package/skill-pack/maintained/outerlayer/references/open-pull-request.md +11 -0
- package/dist/config-X45X7AS4.js +0 -11
- package/dist/mcp-install-cmd-4AQMSIGY.js +0 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @outerlayer/cli
|
|
2
2
|
|
|
3
|
+
## 0.11.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- b248d4f: A container or microVM build now checks out every repository connected to the factory. The primary stays at `/build/work/checkout`, and each other repository is cloned to `/build/work/repos/<owner>/<repo>` on its claim branch. `OUTERLAYER_REPOSITORIES` lists each repository with its path, branch and whether it is primary. `outerlayer work open-pr --repository <owner/name>` opens a pull request in any repository the claim names. The runner protocol is now 16: a gateway refuses an older runner a claim over more than one repository.
|
|
8
|
+
- 4b30f06: A runner with an update pending now keeps taking work while a build runs, and updates the first time no build is running. It holds new work only when the gateway refuses its version or the update has waited longer than `runner.update.maxWaitHours` (default 6, `0` holds at once). The runner logs when an update is pending and when it starts holding work, and `outerlayer runner status` shows the pending version and the builds the runner waits for.
|
|
9
|
+
|
|
10
|
+
## 0.10.2
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- 4e309ad: `outerlayer init` now also adds the OuterLayer docs MCP server, `outerlayer-docs` at `https://docs.outerlayer.ai/mcp`, beside the `outerlayer` one, so your coding agent can look up how OuterLayer works. It goes into the same file, `.mcp.json` or `.outerlayer/mcp.json`, and an entry of that name already there is left as it is. `outerlayer mcp install` is unchanged.
|
|
15
|
+
- a1b7ec0: `outerlayer work list --startable` help now says what makes an item startable: a build request, no open pull request, and no live lease. An item with an open pull request is no longer offered to the implement queue. `outerlayer work build --item <n>` on such an item reruns the amend when a review waits on an agent, and is otherwise refused with `nothing_to_rerun`.
|
|
16
|
+
- 854a747: A runner now updates itself to a release that has no npm provenance attestation. The tarball must still match the registry's digest and pass `npm audit signatures`. An attestation that is present must still name this repository's release workflow and cover the same tarball, and one that cannot be read refuses the release.
|
|
17
|
+
|
|
3
18
|
## 0.10.1
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { addStdioMcpEntryIfAbsent } from './chunk-
|
|
3
|
+
import { addStdioMcpEntryIfAbsent, addDocsMcpEntryIfAbsent, DOCS_MCP_SERVER_NAME } from './chunk-A56PYPDF.js';
|
|
4
4
|
import { installStarterPack } from './chunk-SUMWRA7K.js';
|
|
5
5
|
import { runEmit } from './chunk-YU5GL7QS.js';
|
|
6
6
|
import { C } from './chunk-YRYMNBGQ.js';
|
|
@@ -119,6 +119,9 @@ function runAgentSetup(opts) {
|
|
|
119
119
|
const mcp = addStdioMcpEntryIfAbsent(repoRoot);
|
|
120
120
|
if (mcp.added) written.add(mcp.path);
|
|
121
121
|
else kept.push(`${mcp.path} (already has an outerlayer server)`);
|
|
122
|
+
const docs = addDocsMcpEntryIfAbsent(repoRoot);
|
|
123
|
+
if (docs.added) written.add(docs.path);
|
|
124
|
+
else kept.push(`${docs.path} (already has an ${DOCS_MCP_SERVER_NAME} server)`);
|
|
122
125
|
} catch (err) {
|
|
123
126
|
problems.push(errorMessage(err));
|
|
124
127
|
}
|
|
@@ -186,9 +189,9 @@ function renderPaths(paths, kept) {
|
|
|
186
189
|
`;
|
|
187
190
|
}
|
|
188
191
|
function renderDone(paths, kept, mcpKept) {
|
|
189
|
-
const mcpNote = mcpKept ? ` ${C.yellow}!${C.reset} The outerlayer
|
|
192
|
+
const mcpNote = mcpKept ? ` ${C.yellow}!${C.reset} The outerlayer and ${DOCS_MCP_SERVER_NAME} entries were not added to .mcp.json, so their MCP servers are not set up. Add them to .mcp.json by hand, or move the servers you wrote into .outerlayer/mcp.json and run \`outerlayer context emit\`.
|
|
190
193
|
` : "";
|
|
191
|
-
const what = mcpKept ? "the OuterLayer skills" : "the OuterLayer skills and MCP
|
|
194
|
+
const what = mcpKept ? "the OuterLayer skills" : "the OuterLayer skills and MCP servers";
|
|
192
195
|
if (paths.length === 0) {
|
|
193
196
|
return `${C.green}\u2713${C.reset} Agent setup: already in place, nothing changed
|
|
194
197
|
${renderPaths(paths, kept)}${mcpNote}`;
|
package/dist/build-info.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"id":"2026-10-
|
|
1
|
+
{"id":"2026-10-07T20:56:19.457Z+b4e50a8","root":"/home/runner/_work/outerlayer/outerlayer","pkg":"outerlayer"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
export { MIN_BUILDX_VERSION, builderName, builderSpec, buildxState, ensureBuilder, ensureFailureCount, isOutOfMemory, proxyEnvironment, trackImageBuild } from './chunk-
|
|
3
|
+
export { MIN_BUILDX_VERSION, builderName, builderSpec, buildxState, ensureBuilder, ensureFailureCount, isOutOfMemory, proxyEnvironment, trackImageBuild } from './chunk-CJGQQZWB.js';
|
|
4
4
|
import './chunk-CX22S5BA.js';
|
|
5
5
|
import './chunk-IU4NZROR.js';
|
|
6
6
|
import './chunk-7RQ73DLO.js';
|
|
7
|
-
import './chunk-
|
|
7
|
+
import './chunk-4Q7OMKAT.js';
|
|
8
8
|
import './chunk-YT35WGIP.js';
|
|
9
9
|
import './chunk-BYT5O5RV.js';
|
|
10
10
|
import './chunk-ZM2IMMYN.js';
|
|
@@ -1,35 +1,36 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { probeCredentials } from './chunk-
|
|
3
|
+
import { probeCredentials } from './chunk-3YFCWYBU.js';
|
|
4
|
+
import './chunk-UGP76IZ5.js';
|
|
4
5
|
import './chunk-3JVYMD4G.js';
|
|
5
6
|
import './chunk-I2UOAV7X.js';
|
|
6
|
-
import './chunk-
|
|
7
|
-
import './chunk-
|
|
7
|
+
import './chunk-YETTWTAY.js';
|
|
8
|
+
import './chunk-BHOBM3IZ.js';
|
|
8
9
|
import './chunk-T6OIJQRT.js';
|
|
9
|
-
import './chunk-
|
|
10
|
-
import './chunk-
|
|
10
|
+
import './chunk-FI5UYJMQ.js';
|
|
11
|
+
import './chunk-O765JR4W.js';
|
|
11
12
|
import './chunk-HKUH5AR2.js';
|
|
12
|
-
import './chunk-
|
|
13
|
+
import './chunk-HYZRY4KZ.js';
|
|
13
14
|
import './chunk-Y6P5XX2B.js';
|
|
14
15
|
import './chunk-HHJDN6AU.js';
|
|
15
|
-
import { placeholderQueues, placeholderProblem, permissionModeProblems, permissionModeProblem, needsClaudeCredential, claudeCredentialCheck, claimPermissionProblem } from './chunk-
|
|
16
|
+
import { placeholderQueues, placeholderProblem, permissionModeProblems, permissionModeProblem, needsClaudeCredential, claudeCredentialCheck, claimPermissionProblem } from './chunk-R7BJYFD2.js';
|
|
16
17
|
import './chunk-TI7B7UEO.js';
|
|
17
18
|
import './chunk-YYYRBYWG.js';
|
|
18
19
|
import './chunk-TBT347UY.js';
|
|
19
|
-
import './chunk-
|
|
20
|
-
import './chunk-
|
|
21
|
-
import './chunk-
|
|
20
|
+
import './chunk-7C4T5BGN.js';
|
|
21
|
+
import './chunk-BEZSECPA.js';
|
|
22
|
+
import './chunk-E5DC4VZL.js';
|
|
22
23
|
import { parseRunnerEnv } from './chunk-6MZSX4M7.js';
|
|
23
24
|
import './chunk-JKIWMRFH.js';
|
|
24
25
|
import './chunk-3FMPZPJQ.js';
|
|
25
26
|
import './chunk-N5FOE5PS.js';
|
|
26
27
|
import './chunk-OGFGZQA3.js';
|
|
27
|
-
import './chunk-
|
|
28
|
+
import './chunk-2GBCTEN4.js';
|
|
28
29
|
import './chunk-QOZKPLVJ.js';
|
|
29
|
-
import './chunk-
|
|
30
|
+
import './chunk-CJGQQZWB.js';
|
|
30
31
|
import './chunk-CX22S5BA.js';
|
|
31
|
-
import './chunk-
|
|
32
|
-
import './chunk-
|
|
32
|
+
import './chunk-QKFB4K7X.js';
|
|
33
|
+
import './chunk-RSNSZ2LJ.js';
|
|
33
34
|
import './chunk-F7CU5ABH.js';
|
|
34
35
|
import './chunk-BKO6JEZI.js';
|
|
35
36
|
import './chunk-DTDZXDQ3.js';
|
|
@@ -41,10 +42,10 @@ import './chunk-IU4NZROR.js';
|
|
|
41
42
|
import './chunk-USO2DKBD.js';
|
|
42
43
|
import './chunk-N6LURUEF.js';
|
|
43
44
|
import './chunk-YRYMNBGQ.js';
|
|
44
|
-
import { loadRunnerConfig, RunnerConfigError, checkHooks } from './chunk-
|
|
45
|
+
import { loadRunnerConfig, RunnerConfigError, checkHooks } from './chunk-XR3BJN33.js';
|
|
45
46
|
import './chunk-UXYLWVTQ.js';
|
|
46
47
|
import './chunk-7RQ73DLO.js';
|
|
47
|
-
import './chunk-
|
|
48
|
+
import './chunk-4Q7OMKAT.js';
|
|
48
49
|
import './chunk-GQD22KKN.js';
|
|
49
50
|
import './chunk-WZBHBH3J.js';
|
|
50
51
|
import './chunk-5QRP3MVS.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { RecipeError } from './chunk-QOZKPLVJ.js';
|
|
4
|
-
import { trackImageBuild, isOutOfMemory, ensureBuilder } from './chunk-
|
|
4
|
+
import { trackImageBuild, isOutOfMemory, ensureBuilder } from './chunk-CJGQQZWB.js';
|
|
5
5
|
import { spawn } from 'child_process';
|
|
6
6
|
import { existsSync, mkdirSync, createWriteStream, rmSync, readFileSync } from 'fs';
|
|
7
7
|
import { join, dirname } from 'path';
|
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
+
import { readHousekeepingRecord, writeHousekeepingRecord } from './chunk-UGP76IZ5.js';
|
|
3
4
|
import { decideInstalledSwitch } from './chunk-3JVYMD4G.js';
|
|
4
5
|
import { compareVersions, satisfiesRange } from './chunk-I2UOAV7X.js';
|
|
5
|
-
import { fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest, fetchProvenance, installVersion, auditSignatures } from './chunk-
|
|
6
|
-
import { LEASE_SECONDS, releaseLease, isUnfinished, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, provisionEnvironment, readProvisionOut, resolveHostBuild, workdirProblem, listenOnBroker, hostEnvironment, hostCommandEnvironment, execArgv, microVmCommandLine, runCommand, execCommandLine, startSender, startHostServices, finishJob, isGroupAlive, outcomeFromExitCode, isTimedOut, readCpuUsec, isIdle, stopOrphanedMicroVms, unfinishedJobs, listAdoptableJobs, retryFailedReleases, recoverLostJobs, hookLimitsFor, needsRenew, renewLease, RENEW_INTERVAL_SECONDS, ALREADY_RELEASED } from './chunk-
|
|
6
|
+
import { fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest, fetchProvenance, installVersion, auditSignatures } from './chunk-YETTWTAY.js';
|
|
7
|
+
import { LEASE_SECONDS, releaseLease, isUnfinished, setStage, jobEnv, runHook, describeHookEnd, provisionMicroVm, deliverCommitHooks, provisionProcess, provisionEnvironment, readProvisionOut, resolveHostBuild, workdirProblem, listenOnBroker, hostEnvironment, hostCommandEnvironment, execArgv, microVmCommandLine, runCommand, execCommandLine, startSender, startHostServices, finishJob, isGroupAlive, outcomeFromExitCode, isTimedOut, readCpuUsec, isIdle, stopOrphanedMicroVms, unfinishedJobs, listAdoptableJobs, retryFailedReleases, recoverLostJobs, hookLimitsFor, needsRenew, renewLease, RENEW_INTERVAL_SECONDS, ALREADY_RELEASED } from './chunk-BHOBM3IZ.js';
|
|
7
8
|
import { writeJobFile, readJobFile, readJobFileChecked } from './chunk-T6OIJQRT.js';
|
|
8
|
-
import { RUNNER_PROTOCOL } from './chunk-
|
|
9
|
-
import {
|
|
10
|
-
import { placeholderQueues, placeholderProblem } from './chunk-
|
|
9
|
+
import { RUNNER_PROTOCOL } from './chunk-FI5UYJMQ.js';
|
|
10
|
+
import { writePendingUpdate } from './chunk-O765JR4W.js';
|
|
11
|
+
import { placeholderQueues, placeholderProblem } from './chunk-R7BJYFD2.js';
|
|
11
12
|
import { writeMarker, readMarker, currentVersion, removeMarker, entryIn, versionDir, startedThroughCurrent, switchCurrent, cleanVersions, isInLayout, stagingDir } from './chunk-TI7B7UEO.js';
|
|
12
13
|
import { freeBytes, formatBytes } from './chunk-YYYRBYWG.js';
|
|
13
14
|
import { RepoFilter } from './chunk-TBT347UY.js';
|
|
14
|
-
import { describeCallFailure, retrySend, shortClaim, relativeToRunner, formatDuration, provisionContainer, lifecycleSteps, lifecycleFailureReason, prepareBranch, containerCommandLine, BuildTokens, classifyRefusal, refusalCode, measureDisk, createRunnerLog, setUpRunnerCgroup, parseCpuList, ensureTunnel, keepGhConfigCurrent, createContainerRuntime, formatClock } from './chunk-
|
|
15
|
+
import { describeCallFailure, retrySend, shortClaim, relativeToRunner, formatDuration, provisionContainer, lifecycleSteps, lifecycleFailureReason, prepareBranch, containerCommandLine, BuildTokens, classifyRefusal, refusalCode, measureDisk, createRunnerLog, setUpRunnerCgroup, parseCpuList, ensureTunnel, keepGhConfigCurrent, createContainerRuntime, formatClock } from './chunk-E5DC4VZL.js';
|
|
15
16
|
import { checkFit } from './chunk-JKIWMRFH.js';
|
|
16
17
|
import { startTimeOf, claimPidFile, readPidFile, isSameProcess, releasePidFile } from './chunk-N5FOE5PS.js';
|
|
17
|
-
import { spawnRun } from './chunk-
|
|
18
|
-
import { builderName, runnerLabelValue, ensureFailureCount, builderSpec, ensureBuilder, BUILD_LABEL, RUNNER_LABEL } from './chunk-
|
|
18
|
+
import { spawnRun } from './chunk-2GBCTEN4.js';
|
|
19
|
+
import { builderName, runnerLabelValue, ensureFailureCount, builderSpec, ensureBuilder, BUILD_LABEL, RUNNER_LABEL } from './chunk-CJGQQZWB.js';
|
|
19
20
|
import { isSignatureRefusal, WorkCommandError, getJson, postJson } from './chunk-DTDZXDQ3.js';
|
|
20
|
-
import { isBuiltinContainer, isBuiltinVm, isBuiltinProcess, loadRunnerConfig, checkHooks, builtinKind } from './chunk-
|
|
21
|
+
import { isBuiltinContainer, isBuiltinVm, isBuiltinProcess, loadRunnerConfig, checkHooks, builtinKind, DEFAULT_UPDATE_MAX_WAIT_HOURS } from './chunk-XR3BJN33.js';
|
|
21
22
|
import { exceedsDisk } from './chunk-7RQ73DLO.js';
|
|
22
|
-
import { sharedUserEnvironment, JOB_MOUNT, claudeCredential } from './chunk-
|
|
23
|
+
import { parseClaimedRepositories, repositoriesOf, primaryOf, sharedUserEnvironment, JOB_MOUNT, claudeCredential } from './chunk-4Q7OMKAT.js';
|
|
23
24
|
import { parseClaimIdentity } from './chunk-BYT5O5RV.js';
|
|
24
25
|
import { resolveVersion } from './chunk-RA3O54FC.js';
|
|
25
26
|
import { loadHostKey, ensureHostKey, signerFor } from './chunk-V7NIVOFD.js';
|
|
@@ -225,15 +226,17 @@ async function verifyInto(staging, version, deps) {
|
|
|
225
226
|
const digest = await fetchTarballDigest(meta.tarball, deps.fetchImpl);
|
|
226
227
|
if (digest !== expected) return failed(`the tarball for ${version} does not match the registry's integrity digest`);
|
|
227
228
|
const provenance = await fetchProvenance(version, deps.fetchImpl);
|
|
228
|
-
if (provenance ===
|
|
229
|
-
if (provenance.
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
229
|
+
if (provenance.kind === "unreadable") return failed(`the provenance of ${version} could not be read`);
|
|
230
|
+
if (provenance.kind === "found") {
|
|
231
|
+
if (provenance.repository !== RELEASE_REPOSITORY) {
|
|
232
|
+
return failed(`the provenance of ${version} names the repository ${provenance.repository}, not ${RELEASE_REPOSITORY}`);
|
|
233
|
+
}
|
|
234
|
+
if (provenance.workflowPath !== RELEASE_WORKFLOW_PATH) {
|
|
235
|
+
return failed(`the provenance of ${version} names the workflow ${provenance.workflowPath}, not ${RELEASE_WORKFLOW_PATH}`);
|
|
236
|
+
}
|
|
237
|
+
if (Buffer.from(provenance.subjectSha512, "hex").toString("base64") !== digest) {
|
|
238
|
+
return failed(`the provenance of ${version} covers a different package than the tarball`);
|
|
239
|
+
}
|
|
237
240
|
}
|
|
238
241
|
mkdirSync(staging, { recursive: true, mode: RUNNER_DIR_MODE });
|
|
239
242
|
const npm = await npmVersion(deps.runNpm, staging);
|
|
@@ -948,12 +951,19 @@ function considerNamedVersion(state, named) {
|
|
|
948
951
|
});
|
|
949
952
|
const updating = decision === "update" && !retryHeld(state, named);
|
|
950
953
|
state.pendingUpdate = updating ? named : void 0;
|
|
954
|
+
if (!updating) clearUpdateWait(state);
|
|
951
955
|
if (!updating || state.preflightedUpdate !== named) state.preflightedUpdate = void 0;
|
|
952
956
|
if (decision === "cannot_self_update" && !state.cannotSelfUpdateLogged && installedSwitchOf(state, update).kind !== "restart") {
|
|
953
957
|
state.cannotSelfUpdateLogged = true;
|
|
954
958
|
logOf(state).line(`this runner cannot update itself to ${named}: ${blocker}`);
|
|
955
959
|
}
|
|
956
960
|
}
|
|
961
|
+
function adoptUpdateWait(state, version) {
|
|
962
|
+
const previous = state.updateWait;
|
|
963
|
+
const wait = { version, sinceMs: previous?.sinceMs ?? nowOf(state).getTime(), holdSinceMs: previous?.holdSinceMs };
|
|
964
|
+
state.updateWait = wait;
|
|
965
|
+
return wait;
|
|
966
|
+
}
|
|
957
967
|
function retryHeld(state, version) {
|
|
958
968
|
return state.updateRetry?.version === version && nowOf(state).getTime() < state.updateRetry.retryAtMs;
|
|
959
969
|
}
|
|
@@ -970,6 +980,68 @@ function updateArgsOf(state, update, version) {
|
|
|
970
980
|
function dropPendingUpdate(state) {
|
|
971
981
|
state.pendingUpdate = void 0;
|
|
972
982
|
state.preflightedUpdate = void 0;
|
|
983
|
+
clearUpdateWait(state);
|
|
984
|
+
}
|
|
985
|
+
function clearUpdateWait(state) {
|
|
986
|
+
state.updateWait = void 0;
|
|
987
|
+
state.updateLogged = void 0;
|
|
988
|
+
state.upgradeRefused = false;
|
|
989
|
+
recordPendingUpdate(state, void 0);
|
|
990
|
+
}
|
|
991
|
+
function recordPendingUpdate(state, record) {
|
|
992
|
+
const text = record === void 0 ? "none" : JSON.stringify(record);
|
|
993
|
+
if (state.updateRecord === text) return;
|
|
994
|
+
try {
|
|
995
|
+
writePendingUpdate(runnerDir(state.config.configPath), record);
|
|
996
|
+
state.updateRecord = text;
|
|
997
|
+
reportRepeating(state, "the update-pending.json record", void 0);
|
|
998
|
+
} catch (err) {
|
|
999
|
+
const code = err.code;
|
|
1000
|
+
const cause = code?.replace(/^ERR_FS_/, "") ?? (err instanceof Error ? err.name : "unknown error");
|
|
1001
|
+
reportRepeating(
|
|
1002
|
+
state,
|
|
1003
|
+
"the update-pending.json record",
|
|
1004
|
+
`could not write update-pending.json (${cause}): \`runner status\` will not show the pending update`
|
|
1005
|
+
);
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
function runningItems(state) {
|
|
1009
|
+
const numbers = [...state.jobs.values()].map((entry) => Number(entry.job.item)).filter((n) => Number.isFinite(n));
|
|
1010
|
+
return numbers.sort((a, b) => a - b);
|
|
1011
|
+
}
|
|
1012
|
+
function holdForUpdate(state, version, mayHold = true) {
|
|
1013
|
+
const log = logOf(state);
|
|
1014
|
+
const nowMs = nowOf(state).getTime();
|
|
1015
|
+
const wait = adoptUpdateWait(state, version);
|
|
1016
|
+
const failed2 = readLastUpdate(state.config.configPath);
|
|
1017
|
+
const failedAtMs = failed2?.to === version && failed2.outcome === "retrying" ? new Date(failed2.at ?? Number.NaN).getTime() : Number.NaN;
|
|
1018
|
+
if (failedAtMs < wait.sinceMs) wait.sinceMs = failedAtMs;
|
|
1019
|
+
const logged = state.updateLogged ??= {};
|
|
1020
|
+
if (logged.pending !== version) {
|
|
1021
|
+
logged.pending = version;
|
|
1022
|
+
log.line(`update to ${version} pending \xB7 updating when no build is running`);
|
|
1023
|
+
}
|
|
1024
|
+
const maxWaitMs = (state.config.update?.maxWaitHours ?? DEFAULT_UPDATE_MAX_WAIT_HOURS) * 60 * 6e4;
|
|
1025
|
+
const holding = mayHold && (state.upgradeRefused === true || nowMs - wait.sinceMs >= maxWaitMs);
|
|
1026
|
+
const record = { version, since: new Date(wait.sinceMs).toISOString() };
|
|
1027
|
+
if (holding) {
|
|
1028
|
+
wait.holdSinceMs ??= nowMs;
|
|
1029
|
+
const builds = runningItems(state);
|
|
1030
|
+
const key = `${version}:${builds.join(",")}`;
|
|
1031
|
+
if (logged.hold !== key) {
|
|
1032
|
+
logged.hold = key;
|
|
1033
|
+
log.line(`claiming nothing: update to ${version} waits for ${buildsPhrase(builds)} to finish`);
|
|
1034
|
+
}
|
|
1035
|
+
record.holding = { builds, since: new Date(wait.holdSinceMs).toISOString() };
|
|
1036
|
+
} else {
|
|
1037
|
+
wait.holdSinceMs = void 0;
|
|
1038
|
+
logged.hold = void 0;
|
|
1039
|
+
}
|
|
1040
|
+
recordPendingUpdate(state, record);
|
|
1041
|
+
return holding;
|
|
1042
|
+
}
|
|
1043
|
+
function buildsPhrase(builds) {
|
|
1044
|
+
return builds.length === 0 ? "the running builds" : builds.map((n) => `#${n}`).join(", ");
|
|
973
1045
|
}
|
|
974
1046
|
function reportUpdateResult(state, version, result) {
|
|
975
1047
|
if (result.kind === "retrying") state.updateRetry = { version, retryAtMs: result.retryAtMs };
|
|
@@ -1029,7 +1101,10 @@ function restartOntoInstalled(state) {
|
|
|
1029
1101
|
async function updateWhenIdle(state) {
|
|
1030
1102
|
const update = state.deps.update;
|
|
1031
1103
|
const version = state.pendingUpdate;
|
|
1032
|
-
if (update === void 0 || version === void 0)
|
|
1104
|
+
if (update === void 0 || version === void 0) {
|
|
1105
|
+
recordPendingUpdate(state, void 0);
|
|
1106
|
+
return false;
|
|
1107
|
+
}
|
|
1033
1108
|
if (!state.config.autoUpdate || retryHeld(state, version)) {
|
|
1034
1109
|
dropPendingUpdate(state);
|
|
1035
1110
|
return false;
|
|
@@ -1037,18 +1112,22 @@ async function updateWhenIdle(state) {
|
|
|
1037
1112
|
if (state.jobs.size > 0) {
|
|
1038
1113
|
const record = readLastUpdate(state.config.configPath);
|
|
1039
1114
|
if (record?.to === version && record.outcome === "retrying") {
|
|
1040
|
-
const failedAtMs = record.at
|
|
1041
|
-
if (!(nowOf(state).getTime() >= failedAtMs + RETRY_MAX_WAIT_MS))
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
if (early !== void 0) {
|
|
1046
|
-
dropPendingUpdate(state);
|
|
1047
|
-
reportUpdateResult(state, version, early);
|
|
1048
|
-
return false;
|
|
1115
|
+
const failedAtMs = new Date(record.at ?? Number.NaN).getTime();
|
|
1116
|
+
if (!(nowOf(state).getTime() >= failedAtMs + RETRY_MAX_WAIT_MS)) {
|
|
1117
|
+
holdForUpdate(state, version, false);
|
|
1118
|
+
return false;
|
|
1119
|
+
}
|
|
1049
1120
|
}
|
|
1050
|
-
state.preflightedUpdate
|
|
1051
|
-
|
|
1121
|
+
if (state.preflightedUpdate !== version) {
|
|
1122
|
+
const early = await preflightUpdate(updateArgsOf(state, update, version));
|
|
1123
|
+
if (early !== void 0) {
|
|
1124
|
+
dropPendingUpdate(state);
|
|
1125
|
+
reportUpdateResult(state, version, early);
|
|
1126
|
+
return false;
|
|
1127
|
+
}
|
|
1128
|
+
state.preflightedUpdate = version;
|
|
1129
|
+
}
|
|
1130
|
+
return holdForUpdate(state, version);
|
|
1052
1131
|
}
|
|
1053
1132
|
dropPendingUpdate(state);
|
|
1054
1133
|
const result = await performUpdate(updateArgsOf(state, update, version));
|
|
@@ -1213,7 +1292,7 @@ async function runTick(state) {
|
|
|
1213
1292
|
claimed = true;
|
|
1214
1293
|
break;
|
|
1215
1294
|
}
|
|
1216
|
-
if (attempt.kind === "outdated" || attempt.kind === "signature" || attempt.kind === "no_item_key" || attempt.kind === "no_branch") {
|
|
1295
|
+
if (attempt.kind === "outdated" || attempt.kind === "signature" || attempt.kind === "no_item_key" || attempt.kind === "no_branch" || attempt.kind === "unreadable_repositories") {
|
|
1217
1296
|
return;
|
|
1218
1297
|
}
|
|
1219
1298
|
if (attempt.kind === "error") {
|
|
@@ -1233,7 +1312,7 @@ async function runTick(state) {
|
|
|
1233
1312
|
);
|
|
1234
1313
|
}
|
|
1235
1314
|
var CLAIM_REFUSAL_CODES = new Set(
|
|
1236
|
-
"pull_request_from_fork pull_request_on_default_branch pull_request_ambiguous branch_claimed_elsewhere".split(" ")
|
|
1315
|
+
"pull_request_from_fork pull_request_on_default_branch pull_request_ambiguous pull_request_repository_not_connected branch_claimed_elsewhere".split(" ")
|
|
1237
1316
|
);
|
|
1238
1317
|
async function tryClaimAndStart(state, item, queue) {
|
|
1239
1318
|
const { postJson: postJson2 } = await import('./work-cmd-ZJY3NA2G.js');
|
|
@@ -1274,11 +1353,13 @@ async function tryClaimAndStart(state, item, queue) {
|
|
|
1274
1353
|
}
|
|
1275
1354
|
if (claim.code === "runner_upgrade_required") {
|
|
1276
1355
|
reportRepeating(state, "the runner protocol", claim.message ?? claim.reason);
|
|
1356
|
+
state.upgradeRefused = true;
|
|
1277
1357
|
return { kind: "outdated" };
|
|
1278
1358
|
}
|
|
1279
1359
|
return { kind: "error", reason: `${claim.reason} (${claim.attempts} attempt(s))` };
|
|
1280
1360
|
}
|
|
1281
1361
|
reportRepeating(state, "the runner protocol", void 0);
|
|
1362
|
+
state.upgradeRefused = false;
|
|
1282
1363
|
reportRepeating(state, "the request signature", void 0);
|
|
1283
1364
|
const { data } = claim.value;
|
|
1284
1365
|
const claimId = data.id === void 0 || data.id === null ? "" : String(data.id);
|
|
@@ -1324,8 +1405,22 @@ async function tryClaimAndStart(state, item, queue) {
|
|
|
1324
1405
|
}
|
|
1325
1406
|
reportRepeating(state, "the branch", void 0);
|
|
1326
1407
|
const identity = parseClaimIdentity(data);
|
|
1408
|
+
const repositories = parseClaimedRepositories(data.repositories);
|
|
1409
|
+
if (repositories === null) {
|
|
1410
|
+
const released = await retrySend(
|
|
1411
|
+
() => releaseLease(state.config, item.number, void 0, {}, state.deps.fetchImpl),
|
|
1412
|
+
{ now: state.deps.now, sleep: state.deps.sleep }
|
|
1413
|
+
);
|
|
1414
|
+
reportRepeating(
|
|
1415
|
+
state,
|
|
1416
|
+
"the repositories",
|
|
1417
|
+
`the gateway named repositories for #${item.number} that this runner cannot read; upgrade the runner or the gateway. ` + (released.ok ? "The claim was released and no build started" : `No build started, but releasing the claim failed (${released.reason}), so it stays held until its lease lapses`)
|
|
1418
|
+
);
|
|
1419
|
+
return { kind: "unreadable_repositories" };
|
|
1420
|
+
}
|
|
1421
|
+
reportRepeating(state, "the repositories", void 0);
|
|
1327
1422
|
try {
|
|
1328
|
-
await startJob(state, item, queue, claimId, itemKey, branch, identity);
|
|
1423
|
+
await startJob(state, item, queue, claimId, itemKey, branch, identity, repositories);
|
|
1329
1424
|
} catch (err) {
|
|
1330
1425
|
const stranded = [...state.jobs.values()].find((active) => active.job.claimId === claimId);
|
|
1331
1426
|
if (stranded === void 0) throw err;
|
|
@@ -1350,9 +1445,11 @@ function wasExtended(claim) {
|
|
|
1350
1445
|
if (!Number.isFinite(createdAtMs) || !Number.isFinite(expiresAtMs)) return false;
|
|
1351
1446
|
return expiresAtMs - createdAtMs > LEASE_SECONDS * 1e3 + 2e3;
|
|
1352
1447
|
}
|
|
1353
|
-
async function startJob(state, item, queue, claimId, itemKey, branch, identity) {
|
|
1448
|
+
async function startJob(state, item, queue, claimId, itemKey, branch, identity, claimed) {
|
|
1354
1449
|
const log = logOf(state);
|
|
1355
1450
|
const startedAt = nowOf(state);
|
|
1451
|
+
const repositories = repositoriesOf({ repositories: claimed, repository: item.specRepository, branch });
|
|
1452
|
+
const primary = primaryOf(repositories);
|
|
1356
1453
|
const dirPath = freeJobDir(state.config.configPath, queue, item.number, claimId, startedAt);
|
|
1357
1454
|
mkdirSync(dirPath, { recursive: true, mode: RUNNER_DIR_MODE });
|
|
1358
1455
|
const runnerRoot = runnerDir(state.config.configPath);
|
|
@@ -1364,7 +1461,7 @@ async function startJob(state, item, queue, claimId, itemKey, branch, identity)
|
|
|
1364
1461
|
itemKey,
|
|
1365
1462
|
branch,
|
|
1366
1463
|
commitIdentity: identity,
|
|
1367
|
-
...
|
|
1464
|
+
...primary === void 0 ? {} : { repository: primary.repository, repositories },
|
|
1368
1465
|
startedAt: startedAt.toISOString()
|
|
1369
1466
|
};
|
|
1370
1467
|
writeJobFile(jobFilePath, job);
|
|
@@ -1438,7 +1535,8 @@ async function startJob(state, item, queue, claimId, itemKey, branch, identity)
|
|
|
1438
1535
|
item,
|
|
1439
1536
|
itemKey,
|
|
1440
1537
|
tokens,
|
|
1441
|
-
branch,
|
|
1538
|
+
branch: primary?.branch ?? branch,
|
|
1539
|
+
repositories,
|
|
1442
1540
|
jobDir: dirPath,
|
|
1443
1541
|
cliVersion,
|
|
1444
1542
|
log,
|
|
@@ -1470,7 +1568,8 @@ async function startJob(state, item, queue, claimId, itemKey, branch, identity)
|
|
|
1470
1568
|
item,
|
|
1471
1569
|
itemKey,
|
|
1472
1570
|
tokens,
|
|
1473
|
-
branch,
|
|
1571
|
+
branch: primary?.branch ?? branch,
|
|
1572
|
+
repositories,
|
|
1474
1573
|
jobDir: dirPath,
|
|
1475
1574
|
cliVersion,
|
|
1476
1575
|
log,
|
|
@@ -1747,6 +1846,7 @@ function buildTokensFor(state, active, item) {
|
|
|
1747
1846
|
return new BuildTokens({
|
|
1748
1847
|
config: state.config,
|
|
1749
1848
|
item,
|
|
1849
|
+
primary: primaryOf(repositoriesOf({ repositories: active.job.repositories, repository: active.job.repository, branch: active.job.branch }))?.repository,
|
|
1750
1850
|
fetchImpl: state.deps.fetchImpl,
|
|
1751
1851
|
now: state.deps.now,
|
|
1752
1852
|
sleep: state.deps.sleep,
|
|
@@ -1972,7 +2072,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
1972
2072
|
const outcome = await onStartUnderMarker({
|
|
1973
2073
|
configPath,
|
|
1974
2074
|
own: ownVersionOf(deps),
|
|
1975
|
-
check: update.check ? () => update.check(configPath) : async () => (await import('./check-
|
|
2075
|
+
check: update.check ? () => update.check(configPath) : async () => (await import('./check-YDXOLVJ5.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl }),
|
|
1976
2076
|
now: () => (deps.now ?? (() => /* @__PURE__ */ new Date()))().getTime(),
|
|
1977
2077
|
log
|
|
1978
2078
|
});
|
|
@@ -2018,7 +2118,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
2018
2118
|
if (cores !== void 0) runtimeOf(state).cpus.hold(job.container.buildId, cores);
|
|
2019
2119
|
const tokens = buildTokensFor(state, adopted, job.item);
|
|
2020
2120
|
runtimeOf(state).credentials.set(dirPath, tokens);
|
|
2021
|
-
await ensureTunnel(runtimeOf(state), job.container, dirPath, config, job.itemKey, job.branch);
|
|
2121
|
+
await ensureTunnel(runtimeOf(state), job.container, dirPath, config, job.itemKey, job.branch, job.repositories);
|
|
2022
2122
|
try {
|
|
2023
2123
|
await tokens.token("read");
|
|
2024
2124
|
keepGhConfigCurrent(
|
|
@@ -345,11 +345,38 @@ async function startBuildServices(input) {
|
|
|
345
345
|
}
|
|
346
346
|
}
|
|
347
347
|
|
|
348
|
+
// src/runner/repositories.ts
|
|
349
|
+
function parseClaimedRepositories(value) {
|
|
350
|
+
if (!Array.isArray(value) || value.length === 0) return void 0;
|
|
351
|
+
const parsed = [];
|
|
352
|
+
for (const entry of value) {
|
|
353
|
+
if (typeof entry !== "object" || entry === null) return null;
|
|
354
|
+
const { repository, branch, primary } = entry;
|
|
355
|
+
if (typeof repository !== "string" || repository === "" || typeof branch !== "string" || branch === "") return null;
|
|
356
|
+
parsed.push({ repository, branch, primary: primary === true });
|
|
357
|
+
}
|
|
358
|
+
const primaryAt = parsed.findIndex((entry) => entry.primary);
|
|
359
|
+
const at = primaryAt === -1 ? 0 : primaryAt;
|
|
360
|
+
return [{ ...parsed[at], primary: true }, ...parsed.filter((_, index) => index !== at).map((entry) => ({ ...entry, primary: false }))];
|
|
361
|
+
}
|
|
362
|
+
function repositoriesOf(input) {
|
|
363
|
+
if (input.repositories !== void 0 && input.repositories.length > 0) return input.repositories;
|
|
364
|
+
if (input.repository === void 0 || input.repository === null || input.repository === "" || input.branch === void 0) return [];
|
|
365
|
+
return [{ repository: input.repository, branch: input.branch, primary: true }];
|
|
366
|
+
}
|
|
367
|
+
function primaryOf(repositories) {
|
|
368
|
+
return repositories.find((entry) => entry.primary) ?? repositories[0];
|
|
369
|
+
}
|
|
370
|
+
|
|
348
371
|
// src/runner/container/environment.ts
|
|
349
372
|
var RELAY_PORT = 3128;
|
|
350
373
|
var JOB_MOUNT = "/outerlayer/job";
|
|
351
374
|
var EVAL_INPUT_DIR = `${JOB_MOUNT}/eval-input`;
|
|
352
375
|
var CHECKOUT_DIR = "/build/work/checkout";
|
|
376
|
+
var REPOS_DIR = "/build/work/repos";
|
|
377
|
+
function checkoutPath(entry) {
|
|
378
|
+
return entry.primary ? CHECKOUT_DIR : `${REPOS_DIR}/${entry.repository}`;
|
|
379
|
+
}
|
|
353
380
|
var MAX_HOSTS = 200;
|
|
354
381
|
function tokenVariables() {
|
|
355
382
|
return ["GH_TOKEN", "GITHUB_TOKEN", "GH_ENTERPRISE_TOKEN", "GITHUB_ENTERPRISE_TOKEN"];
|
|
@@ -377,7 +404,7 @@ function proxyEnvironment(proxyUrl, alsoNoProxy) {
|
|
|
377
404
|
YARN_HTTP_PROXY: proxyUrl
|
|
378
405
|
};
|
|
379
406
|
}
|
|
380
|
-
function runnerLiterals(repository) {
|
|
407
|
+
function runnerLiterals(repository, repositories = []) {
|
|
381
408
|
return {
|
|
382
409
|
OUTERLAYER_JOB_DIR: JOB_MOUNT,
|
|
383
410
|
HOME: "/build/home",
|
|
@@ -386,7 +413,13 @@ function runnerLiterals(repository) {
|
|
|
386
413
|
GIT_TERMINAL_PROMPT: "0",
|
|
387
414
|
GH_CONFIG_DIR: `${JOB_MOUNT}/gh`,
|
|
388
415
|
GH_NO_UPDATE_NOTIFIER: "1",
|
|
389
|
-
...repository === void 0 ? {} : { GH_REPO: repository }
|
|
416
|
+
...repository === void 0 ? {} : { GH_REPO: repository },
|
|
417
|
+
// What the build's command reads to find every repository it holds: its path, its branch, and whether it is the primary.
|
|
418
|
+
...repositories.length === 0 ? {} : {
|
|
419
|
+
OUTERLAYER_REPOSITORIES: JSON.stringify(
|
|
420
|
+
repositories.map((entry) => ({ repository: entry.repository, path: checkoutPath(entry), branch: entry.branch, primary: entry.primary }))
|
|
421
|
+
)
|
|
422
|
+
}
|
|
390
423
|
};
|
|
391
424
|
}
|
|
392
425
|
function containerBuiltInAddress(name) {
|
|
@@ -448,7 +481,14 @@ function buildEnvironment(input) {
|
|
|
448
481
|
delete passed.GIT_CONFIG_COUNT;
|
|
449
482
|
}
|
|
450
483
|
return {
|
|
451
|
-
literals: {
|
|
484
|
+
literals: {
|
|
485
|
+
...recipe,
|
|
486
|
+
...destinations,
|
|
487
|
+
...runnerLiterals(input.repository, repositoriesOf({ repositories: input.repositories, repository: input.repository, branch: input.branch })),
|
|
488
|
+
...builtInLiterals,
|
|
489
|
+
...authored,
|
|
490
|
+
...hooks
|
|
491
|
+
},
|
|
452
492
|
passed,
|
|
453
493
|
variables,
|
|
454
494
|
skippedTokenVariables
|
|
@@ -504,4 +544,4 @@ function withTunnelRecord(environment, record, onlyWhenUsed = false) {
|
|
|
504
544
|
};
|
|
505
545
|
}
|
|
506
546
|
|
|
507
|
-
export { AGENT_CREDENTIAL_MISSING, BUILT_IN_NAMES, CHECKOUT_DIR, CLAUDE_CREDENTIAL_VARIABLES, CLAUDE_PORT, CLAUDE_SOCKET, DESTINATION_BASE_PORT, EVAL_INPUT_DIR, GATEWAY_PORT, GATEWAY_SOCKET, JOB_MOUNT, RELAY_PORT, buildEnvironment, builtInEnvironment, checkEnvironment, claudeCredential, containerLocalAddress, destinationEnvironment, headerVariables, isRefusedInConfig, isReservedVariable, parseIsolation, proxyEnvironment, resolveDestinations, sharedUserEnvironment, startBuildServices, withTunnelRecord };
|
|
547
|
+
export { AGENT_CREDENTIAL_MISSING, BUILT_IN_NAMES, CHECKOUT_DIR, CLAUDE_CREDENTIAL_VARIABLES, CLAUDE_PORT, CLAUDE_SOCKET, DESTINATION_BASE_PORT, EVAL_INPUT_DIR, GATEWAY_PORT, GATEWAY_SOCKET, JOB_MOUNT, RELAY_PORT, buildEnvironment, builtInEnvironment, checkEnvironment, checkoutPath, claudeCredential, containerLocalAddress, destinationEnvironment, headerVariables, isRefusedInConfig, isReservedVariable, parseClaimedRepositories, parseIsolation, primaryOf, proxyEnvironment, repositoriesOf, resolveDestinations, sharedUserEnvironment, startBuildServices, withTunnelRecord };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { detectMachine, supportsContainerBuilds, reachDockerStep, describeMachineDocker, supportsMicroVmBuilds } from './chunk-
|
|
4
|
-
import { MIN_ENGINE_MAJOR } from './chunk-
|
|
3
|
+
import { detectMachine, supportsContainerBuilds, reachDockerStep, describeMachineDocker, supportsMicroVmBuilds } from './chunk-BEZSECPA.js';
|
|
4
|
+
import { MIN_ENGINE_MAJOR } from './chunk-E5DC4VZL.js';
|
|
5
5
|
import { RUNNER_DIR_MODE, runnerDir, RUNNER_FILE_MODE } from './chunk-ZM2IMMYN.js';
|
|
6
6
|
import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
|
|
7
7
|
import { dirname } from 'path';
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { C } from './chunk-YRYMNBGQ.js';
|
|
4
4
|
import { readCloudConfig } from './chunk-EABW6AJQ.js';
|
|
5
|
-
import {
|
|
5
|
+
import { existsSync, writeFileSync, mkdirSync, readFileSync } from 'fs';
|
|
6
6
|
import { join, dirname } from 'path';
|
|
7
7
|
|
|
8
8
|
createRequire(import.meta.url);
|
|
@@ -47,7 +47,7 @@ function readMcpDoc(absPath, relPath) {
|
|
|
47
47
|
function mcpTargetPath(repoRoot) {
|
|
48
48
|
return existsSync(join(repoRoot, ".outerlayer", "mcp.json")) ? ".outerlayer/mcp.json" : ".mcp.json";
|
|
49
49
|
}
|
|
50
|
-
function
|
|
50
|
+
function addMcpEntryIfAbsent(repoRoot, name, entry) {
|
|
51
51
|
const relPath = mcpTargetPath(repoRoot);
|
|
52
52
|
const absPath = join(repoRoot, relPath);
|
|
53
53
|
const doc = readMcpDoc(absPath, relPath);
|
|
@@ -57,12 +57,19 @@ function addStdioMcpEntryIfAbsent(repoRoot, name = "outerlayer") {
|
|
|
57
57
|
}
|
|
58
58
|
const existing = servers ?? {};
|
|
59
59
|
if (name in existing) return { path: relPath, added: false };
|
|
60
|
-
const entry = buildStdioServerEntry(DEFAULT_MCP_COMMAND, void 0, void 0);
|
|
61
60
|
mkdirSync(dirname(absPath), { recursive: true });
|
|
62
61
|
writeFileSync(absPath, `${JSON.stringify({ ...doc, mcpServers: { ...existing, [name]: entry } }, null, 2)}
|
|
63
62
|
`);
|
|
64
63
|
return { path: relPath, added: true };
|
|
65
64
|
}
|
|
65
|
+
function addStdioMcpEntryIfAbsent(repoRoot, name = "outerlayer") {
|
|
66
|
+
return addMcpEntryIfAbsent(repoRoot, name, buildStdioServerEntry(DEFAULT_MCP_COMMAND, void 0, void 0));
|
|
67
|
+
}
|
|
68
|
+
var DOCS_MCP_SERVER_NAME = "outerlayer-docs";
|
|
69
|
+
var DOCS_MCP_URL = "https://docs.outerlayer.ai/mcp";
|
|
70
|
+
function addDocsMcpEntryIfAbsent(repoRoot) {
|
|
71
|
+
return addMcpEntryIfAbsent(repoRoot, DOCS_MCP_SERVER_NAME, { type: "http", url: DOCS_MCP_URL });
|
|
72
|
+
}
|
|
66
73
|
function runMcpInstall(opts = {}) {
|
|
67
74
|
const cwd = opts.cwd ?? process.cwd();
|
|
68
75
|
if (!existsSync(cwd)) throw new McpInstallError(`no such directory: ${cwd}`);
|
|
@@ -92,4 +99,4 @@ function handleMcpInstallError(err) {
|
|
|
92
99
|
process.exitCode = 1;
|
|
93
100
|
}
|
|
94
101
|
|
|
95
|
-
export { DEFAULT_MCP_COMMAND, McpInstallError, addStdioMcpEntryIfAbsent, buildServerEntry, buildStdioServerEntry, defaultMcpUrl, handleMcpInstallError, runMcpInstall };
|
|
102
|
+
export { DEFAULT_MCP_COMMAND, DOCS_MCP_SERVER_NAME, McpInstallError, addDocsMcpEntryIfAbsent, addStdioMcpEntryIfAbsent, buildServerEntry, buildStdioServerEntry, defaultMcpUrl, handleMcpInstallError, runMcpInstall };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { MIN_ENGINE_MAJOR } from './chunk-
|
|
3
|
+
import { MIN_ENGINE_MAJOR } from './chunk-E5DC4VZL.js';
|
|
4
4
|
import { firecrackerArch, MICROVM_ARCHES, guestAssetsPinned } from './chunk-CX22S5BA.js';
|
|
5
5
|
import { spawnSync } from 'child_process';
|
|
6
6
|
import { existsSync, accessSync, constants, statSync, readFileSync } from 'fs';
|