@outerlayer/cli 0.11.0 → 0.13.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 +23 -0
- package/README.md +16 -7
- package/dist/{agent-setup-YEFN74Y4.js → agent-setup-QE6PSCEZ.js} +8 -8
- package/dist/build-info.json +1 -1
- package/dist/{builder-PP436VGZ.js → builder-UUS4ORDH.js} +3 -3
- package/dist/{check-YDXOLVJ5.js → check-63IDCEEV.js} +31 -30
- package/dist/{chunk-XR3BJN33.js → chunk-22RMZBGW.js} +20 -1
- package/dist/{chunk-TB7EP24C.js → chunk-2M63GG56.js} +1 -1
- package/dist/{chunk-Y6P5XX2B.js → chunk-3D4OYFCD.js} +4 -4
- package/dist/{chunk-2GBCTEN4.js → chunk-3KTA5UU2.js} +1 -1
- package/dist/{chunk-USO2DKBD.js → chunk-4KSQKQXE.js} +8 -2
- package/dist/{chunk-UES67HLJ.js → chunk-4QVZCVWT.js} +5 -5
- package/dist/{chunk-I263FZ3A.js → chunk-6S3H3J6H.js} +3 -3
- package/dist/{chunk-BHOBM3IZ.js → chunk-C6IV5BV7.js} +10 -10
- package/dist/{chunk-VDI5POCC.js → chunk-CNFVHDHG.js} +1 -1
- package/dist/{chunk-EOWWTFUU.js → chunk-DPKX26LT.js} +92 -16
- package/dist/{chunk-SUMWRA7K.js → chunk-DXQ5MHCO.js} +1 -1
- package/dist/{chunk-ZQ5JGHUO.js → chunk-EFZLAYPE.js} +2 -2
- package/dist/{chunk-RWQWPZB4.js → chunk-GI4XXD4I.js} +3 -3
- package/dist/{chunk-YU5GL7QS.js → chunk-HDTVTA6I.js} +2 -2
- package/dist/{chunk-BFESLKPP.js → chunk-IP7BIBXJ.js} +19 -1
- package/dist/{chunk-YT35WGIP.js → chunk-J5M7BSJQ.js} +99 -7
- package/dist/{chunk-IU4NZROR.js → chunk-JXYVA45C.js} +1 -1
- package/dist/{chunk-BMX3L7CR.js → chunk-LCEXHCHD.js} +1 -1
- package/dist/{chunk-7C4T5BGN.js → chunk-MJXXRX4M.js} +54 -12
- package/dist/{chunk-E5DC4VZL.js → chunk-MZN7AQOB.js} +8 -8
- package/dist/{chunk-CJGQQZWB.js → chunk-NX57IBNK.js} +1 -1
- package/dist/{chunk-DTDZXDQ3.js → chunk-P4MM66C6.js} +31 -18
- package/dist/{chunk-BEZSECPA.js → chunk-P6FX4D43.js} +1 -1
- package/dist/{chunk-A56PYPDF.js → chunk-R7OQTKWT.js} +2 -1
- package/dist/{chunk-TFIOXPZT.js → chunk-RLYZLUQ7.js} +67 -5
- package/dist/chunk-RMWLBUCJ.js +50 -0
- package/dist/{chunk-4HMXH2OA.js → chunk-SFFHGX3G.js} +1 -1
- package/dist/{chunk-3YFCWYBU.js → chunk-SVEP7PVH.js} +14 -14
- package/dist/chunk-T5VPP6H7.js +65 -0
- package/dist/{chunk-BGWTYRSS.js → chunk-TCIW27FM.js} +1 -1
- package/dist/{chunk-R7BJYFD2.js → chunk-TOPDNXHZ.js} +5 -5
- package/dist/{chunk-HKUH5AR2.js → chunk-XJKL4BNU.js} +3 -3
- package/dist/{cli-RQZXTOEI.js → cli-WSBIAVZU.js} +176 -88
- package/dist/{command-U6UGIBVT.js → command-N7BAB4XJ.js} +21 -22
- package/dist/{config-MKBX2ZQD.js → config-N3C6DFQA.js} +1 -1
- package/dist/{connect-cmd-5MIUNYAY.js → connect-cmd-FGYRLLXL.js} +5 -5
- package/dist/{context-adopt-A77G67CP.js → context-adopt-B3PWGFHL.js} +5 -5
- package/dist/{context-materialize-KQZYATQZ.js → context-materialize-7S6NLLRO.js} +5 -5
- package/dist/{dist-3M3ZMEZF.js → dist-LKDWQWZ7.js} +2 -2
- package/dist/{docker-WVRRMK6R.js → docker-BZ55BMBJ.js} +4 -4
- package/dist/{doctor-ZF4PYWVN.js → doctor-3H25Q7WT.js} +23 -20
- package/dist/{emit-artifact-cmd-VKPW577P.js → emit-artifact-cmd-IQCRXOH7.js} +9 -9
- package/dist/{emit-cmd-SU62J2PB.js → emit-cmd-KDSM5VAO.js} +4 -4
- package/dist/{emit-criteria-cmd-U2TL6FYY.js → emit-criteria-cmd-EYUXME26.js} +7 -7
- package/dist/emit-finding-cmd-P4RKBPBB.js +465 -0
- package/dist/{emit-result-cmd-GKBVPMU4.js → emit-result-cmd-6XYENU6H.js} +9 -9
- package/dist/{hook-fast-AQCAQIA6.js → hook-fast-PXWKQPN6.js} +1 -1
- package/dist/{import-capture-cmd-5NJVL2HN.js → import-capture-cmd-2BKM5I2N.js} +3 -3
- package/dist/{import-ruler-cmd-TUK3MRPC.js → import-ruler-cmd-IXR7YK47.js} +2 -2
- package/dist/index.js +3 -3
- package/dist/{init-PUY2BUHH.js → init-2LWVS4AH.js} +21 -17
- package/dist/{init-M5IBAGVE.js → init-ZL7ORPTF.js} +53 -32
- package/dist/{init-cmd-NPNR23UL.js → init-cmd-JXOBCOIB.js} +16 -14
- package/dist/{install-HKOVISUP.js → install-HDBIPHTX.js} +2 -4
- package/dist/{login-browser-7XGSV7MA.js → login-browser-QZCS3WW6.js} +2 -1
- package/dist/{loop-3FNROLW7.js → loop-XOAE6ZIY.js} +32 -30
- package/dist/{machine-RWDDJRWB.js → machine-G6PY2J2J.js} +16 -16
- package/dist/{mcp-install-cmd-XZARXNYT.js → mcp-install-cmd-VXVIH7PH.js} +1 -1
- package/dist/runner-env-XTC53CHN.js +15 -0
- package/dist/runner-key-TDTLNAKJ.js +154 -0
- package/dist/{session-sender-E3UHGSNV.js → session-sender-XVGZFWRK.js} +7 -7
- package/dist/{starter-pack-I35VNYAR.js → starter-pack-B7JPGEDO.js} +4 -4
- package/dist/{status-2OW5AKWL.js → status-MRTPG34B.js} +22 -22
- package/dist/{sync-cmd-ULKXCHO2.js → sync-cmd-UBUZMMDN.js} +6 -6
- package/dist/{watch-IU6NHB4K.js → watch-STNPEWD6.js} +6 -6
- package/dist/{work-claim-cmd-LXXSNEGF.js → work-claim-cmd-CWGYEIJE.js} +11 -11
- package/dist/{work-cmd-ZJY3NA2G.js → work-cmd-X7NMJDFL.js} +8 -8
- package/dist/{work-comment-cmd-34FTLPUO.js → work-comment-cmd-FI2TMAYQ.js} +8 -8
- package/dist/{work-open-pr-cmd-YZAENDP6.js → work-open-pr-cmd-OVHJ5I5H.js} +9 -9
- package/dist/{work-pr-cmd-EXTOGBJC.js → work-pr-cmd-Y5TDMQ4O.js} +8 -8
- package/package.json +1 -1
- package/skill-pack/maintained/reporting-findings/SKILL.md +84 -5
- package/skill-pack/template/build/SKILL.md +60 -33
- package/skill-pack/template/build/references/agent-briefs.md +4 -2
- package/skill-pack/template/build/references/release.md +1 -1
- package/skill-pack/template/build/references/review-loop.md +6 -2
- package/skill-pack/template/build/scripts/record-criteria.mjs +109 -143
- package/skill-pack/validators/code-review.yaml +4 -2
- package/dist/chunk-FBTE2A2X.js +0 -38
- package/dist/chunk-JKIWMRFH.js +0 -27
- package/dist/chunk-T6OIJQRT.js +0 -31
- package/dist/emit-finding-cmd-TMOOKHPD.js +0 -251
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { autoConnect } from './chunk-
|
|
4
|
-
import { detectActiveSession } from './chunk-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import { autoConnect } from './chunk-EFZLAYPE.js';
|
|
4
|
+
import { detectActiveSession } from './chunk-IP7BIBXJ.js';
|
|
5
|
+
import { workPageUrl } from './chunk-4QVZCVWT.js';
|
|
6
|
+
import { sanitizeTerminal } from './chunk-CNFVHDHG.js';
|
|
7
|
+
import { resolveRepoIdentity } from './chunk-JXYVA45C.js';
|
|
8
|
+
import { C } from './chunk-YRYMNBGQ.js';
|
|
7
9
|
import { parseTrackerNumber, trackerNumberError } from './chunk-WZBHBH3J.js';
|
|
8
10
|
import { defaultFetch } from './chunk-YO4PSLVB.js';
|
|
9
11
|
import { resolveGatewayCredentials, unauthorizedMessage } from './chunk-PLMTLGYH.js';
|
|
10
12
|
import { signRunnerRequest } from './chunk-V7NIVOFD.js';
|
|
13
|
+
import { readRepoConnection } from './chunk-BJ3KTMDH.js';
|
|
11
14
|
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
12
15
|
|
|
13
16
|
createRequire(import.meta.url);
|
|
@@ -39,10 +42,6 @@ function isSignatureRefusal(code) {
|
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
// src/work-cmd.ts
|
|
42
|
-
var GREEN = "\x1B[32m";
|
|
43
|
-
var YELLOW = "\x1B[33m";
|
|
44
|
-
var DIM = "\x1B[2m";
|
|
45
|
-
var RESET = "\x1B[0m";
|
|
46
45
|
async function signatureHeaders(method, endpoint, payload, signer) {
|
|
47
46
|
if (signer === void 0) return {};
|
|
48
47
|
return { ...await signRunnerRequest({ method, url: endpoint, body: new TextEncoder().encode(payload), signer }) };
|
|
@@ -298,7 +297,19 @@ function tokenWarning(data) {
|
|
|
298
297
|
if (tokens === void 0 || tokens === null || tokens.earnable !== false) return "";
|
|
299
298
|
const why = typeof tokens.message === "string" ? sanitizeTerminal(tokens.message) : "the gateway named no reason";
|
|
300
299
|
return `
|
|
301
|
-
${
|
|
300
|
+
${C.yellow}!${C.reset} a container host will fail this build: ${why}`;
|
|
301
|
+
}
|
|
302
|
+
function itemLabel(data) {
|
|
303
|
+
return data.number != null ? `item #${data.number}` : `item ${sanitizeTerminal(String(data.workItemId))}`;
|
|
304
|
+
}
|
|
305
|
+
function issueLabel(subject) {
|
|
306
|
+
if ("issue" in subject) return `issue ${sanitizeTerminal(subject.repository)}#${subject.issue}`;
|
|
307
|
+
return `issue ${sanitizeTerminal(subject.key)}`;
|
|
308
|
+
}
|
|
309
|
+
function itemPageUrl(home, cwd, appId, workItemId) {
|
|
310
|
+
const connection = readRepoConnection(cwd);
|
|
311
|
+
if (connection === void 0 || connection.appId !== appId || typeof workItemId !== "string" || workItemId === "") return void 0;
|
|
312
|
+
return `${workPageUrl(home, connection.organization.name, connection.factory.name)}/${encodeURIComponent(workItemId)}`;
|
|
302
313
|
}
|
|
303
314
|
async function runWorkBuild(opts) {
|
|
304
315
|
const cwd = opts.cwd ?? process.cwd();
|
|
@@ -326,7 +337,7 @@ async function runWorkBuild(opts) {
|
|
|
326
337
|
const label = data2.number != null ? `#${data2.number}` : String(data2.workItemId);
|
|
327
338
|
const launch = data2.number != null ? `OUTERLAYER_WORK=${data2.number} claude` : null;
|
|
328
339
|
const branch = typeof data2.branch === "string" && data2.branch !== "" ? data2.branch : null;
|
|
329
|
-
const output2 = opts.json ? JSON.stringify({ ...data2, ...launch !== null ? { launchCommand: launch } : {} }) : `${
|
|
340
|
+
const output2 = opts.json ? JSON.stringify({ ...data2, ...launch !== null ? { launchCommand: launch } : {} }) : `${C.green}\u2713${C.reset} on Work for you to build ${C.dim}\xB7${C.reset} ${label} ${C.dim}\xB7${C.reset} no host will take it` + (branch !== null ? `
|
|
330
341
|
branch: ${branch}` : "") + (launch !== null ? `
|
|
331
342
|
start your session with: ${launch}` : "");
|
|
332
343
|
if (!opts.quiet) process.stdout.write(output2 + "\n");
|
|
@@ -338,7 +349,9 @@ async function runWorkBuild(opts) {
|
|
|
338
349
|
...facts
|
|
339
350
|
};
|
|
340
351
|
const { data } = await postJsonWithRetry(url, "/v1/work-items/build", apiKey, appId, body, fetchImpl, retries, sleep);
|
|
341
|
-
const
|
|
352
|
+
const page = itemPageUrl(home, cwd, appId, data.workItemId);
|
|
353
|
+
const output = opts.json ? JSON.stringify(data) : `${C.green}\u2713${C.reset} build requested ${C.dim}\xB7${C.reset} ${itemLabel(data)}${"subject" in body ? ` (${issueLabel(body.subject)})` : ""} ${C.dim}\xB7${C.reset} by ${data.attestor}` + (page !== void 0 ? `
|
|
354
|
+
${page}` : "") + tokenWarning(data);
|
|
342
355
|
if (!opts.quiet) process.stdout.write(output + "\n");
|
|
343
356
|
return { data, output };
|
|
344
357
|
}
|
|
@@ -347,7 +360,7 @@ async function runWorkLinkSession(opts) {
|
|
|
347
360
|
return await linkSession(opts);
|
|
348
361
|
} catch (err) {
|
|
349
362
|
if (opts.logFailures) {
|
|
350
|
-
const { logHookError } = await import('./hook-fast-
|
|
363
|
+
const { logHookError } = await import('./hook-fast-PXWKQPN6.js');
|
|
351
364
|
const reason = err instanceof Error ? err.message : String(err);
|
|
352
365
|
logHookError(opts.home ?? homeFromEnv(opts.env ?? process.env), new Error(`work link-session #${opts.number} failed: ${reason}`));
|
|
353
366
|
}
|
|
@@ -387,7 +400,7 @@ async function linkSession(opts) {
|
|
|
387
400
|
}
|
|
388
401
|
const heldBy = typeof data.heldBy === "string" ? data.heldBy : void 0;
|
|
389
402
|
const linked = data.linked === true;
|
|
390
|
-
const output = opts.json ? JSON.stringify(data) : opts.ended ? linked ? `${
|
|
403
|
+
const output = opts.json ? JSON.stringify(data) : opts.ended ? linked ? `${C.green}\u2713${C.reset} ended ${C.dim}\xB7${C.reset} session ${sessionId} ${C.dim}\xB7${C.reset} #${number}` : `${C.dim}\xB7${C.reset} session ${sessionId} was not linked to #${number}` : heldBy ? `${C.dim}\xB7${C.reset} session ${sessionId} linked to #${number}, held by ${sanitizeTerminal(heldBy)} \u2014 no lease taken` : `${C.green}\u2713${C.reset} linked ${C.dim}\xB7${C.reset} session ${sessionId} ${C.dim}\xB7${C.reset} #${number}`;
|
|
391
404
|
if (!opts.quiet) process.stdout.write(output + "\n");
|
|
392
405
|
return { data, output };
|
|
393
406
|
}
|
|
@@ -411,7 +424,7 @@ async function runWorkRemove(opts) {
|
|
|
411
424
|
{ reason: opts.reason, ...environmentFacts({ cwd, env, home }) },
|
|
412
425
|
fetchImpl
|
|
413
426
|
);
|
|
414
|
-
const output2 = opts.json ? JSON.stringify(data2) : `${
|
|
427
|
+
const output2 = opts.json ? JSON.stringify(data2) : `${C.green}\u2713${C.reset} removed ${C.dim}\xB7${C.reset} ${data2.workItemId} ${C.dim}\xB7${C.reset} withdrawn ${data2.itemWithdrawn}`;
|
|
415
428
|
if (!opts.quiet) process.stdout.write(output2 + "\n");
|
|
416
429
|
return { data: data2, output: output2 };
|
|
417
430
|
}
|
|
@@ -421,7 +434,7 @@ async function runWorkRemove(opts) {
|
|
|
421
434
|
const item = await findLiveItem(creds, repository, subject, fetchImpl);
|
|
422
435
|
if (!item) {
|
|
423
436
|
const data2 = { workItemId: null, removed: true, itemWithdrawn: false, noLiveAddition: true };
|
|
424
|
-
const output2 = opts.json ? JSON.stringify(data2) : `${
|
|
437
|
+
const output2 = opts.json ? JSON.stringify(data2) : `${C.green}\u2713${C.reset} nothing to remove ${C.dim}\xB7${C.reset} no live addition on ${repository}#${number}`;
|
|
425
438
|
if (!opts.quiet) process.stdout.write(output2 + "\n");
|
|
426
439
|
return { data: data2, output: output2 };
|
|
427
440
|
}
|
|
@@ -433,7 +446,7 @@ async function runWorkRemove(opts) {
|
|
|
433
446
|
{ reason: opts.reason, ...environmentFacts({ cwd, env, home }) },
|
|
434
447
|
fetchImpl
|
|
435
448
|
);
|
|
436
|
-
const output = opts.json ? JSON.stringify(data) : `${
|
|
449
|
+
const output = opts.json ? JSON.stringify(data) : `${C.green}\u2713${C.reset} removed ${C.dim}\xB7${C.reset} ${data.workItemId} ${C.dim}\xB7${C.reset} withdrawn ${data.itemWithdrawn}`;
|
|
437
450
|
if (!opts.quiet) process.stdout.write(output + "\n");
|
|
438
451
|
return { data, output };
|
|
439
452
|
}
|
|
@@ -496,10 +509,10 @@ async function runWorkList(opts) {
|
|
|
496
509
|
const claimSuffix = (claim) => {
|
|
497
510
|
if (!claim) return "";
|
|
498
511
|
const holder = claim.holderKind === "session" ? `${claim.memberName || "a member"} (local session` : `${sanitizeTerminal(claim.host)} (${claim.kind}`;
|
|
499
|
-
return ` ${
|
|
512
|
+
return ` ${C.dim}\xB7${C.reset} claimed by ${holder}, since ${claim.createdAt}, until ${claim.expiresAt})`;
|
|
500
513
|
};
|
|
501
514
|
const output = opts.json ? JSON.stringify(data) : items.length === 0 ? "no live work items" : items.map(
|
|
502
|
-
(i) => `${i.trackerKey} ${
|
|
515
|
+
(i) => `${i.trackerKey} ${C.dim}\xB7${C.reset} ${i.stage} ${C.dim}\xB7${C.reset} ${i.section} ${C.dim}\xB7${C.reset} ${i.title}${claimSuffix(i.claim)}`
|
|
503
516
|
).join("\n");
|
|
504
517
|
if (!opts.quiet) process.stdout.write(output + "\n");
|
|
505
518
|
return { data, output };
|
|
@@ -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-MZN7AQOB.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';
|
|
@@ -62,8 +62,9 @@ function addMcpEntryIfAbsent(repoRoot, name, entry) {
|
|
|
62
62
|
`);
|
|
63
63
|
return { path: relPath, added: true };
|
|
64
64
|
}
|
|
65
|
+
var INIT_STDIO_ENTRY = { type: "stdio", command: "npx", args: ["-y", "@outerlayer/cli", "mcp", "serve"] };
|
|
65
66
|
function addStdioMcpEntryIfAbsent(repoRoot, name = "outerlayer") {
|
|
66
|
-
return addMcpEntryIfAbsent(repoRoot, name,
|
|
67
|
+
return addMcpEntryIfAbsent(repoRoot, name, { ...INIT_STDIO_ENTRY, args: [...INIT_STDIO_ENTRY.args] });
|
|
67
68
|
}
|
|
68
69
|
var DOCS_MCP_SERVER_NAME = "outerlayer-docs";
|
|
69
70
|
var DOCS_MCP_URL = "https://docs.outerlayer.ai/mcp";
|
|
@@ -1,13 +1,64 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { builtinKind } from './chunk-XR3BJN33.js';
|
|
3
|
+
import { builtinKind } from './chunk-22RMZBGW.js';
|
|
4
|
+
import { parseSize } from './chunk-7RQ73DLO.js';
|
|
6
5
|
import { runnerDir } from './chunk-ZM2IMMYN.js';
|
|
7
6
|
import { dirname } from 'path';
|
|
8
7
|
import { spawnSync } from 'child_process';
|
|
9
8
|
|
|
10
9
|
createRequire(import.meta.url);
|
|
10
|
+
|
|
11
|
+
// src/runner/vm/service.ts
|
|
12
|
+
var VM_SERVICE_NAME = "outerlayer-runner";
|
|
13
|
+
var UNIT_MARKER = "# Written by outerlayer runner install --service; edit the runner config, not this file.";
|
|
14
|
+
var STOP_MARGIN_MINUTES = 10;
|
|
15
|
+
function escapeUnitPath(path) {
|
|
16
|
+
return path.replace(/%/g, "%%").replace(/ /g, "\\x20");
|
|
17
|
+
}
|
|
18
|
+
function runnerUnit(unit) {
|
|
19
|
+
return `${UNIT_MARKER}
|
|
20
|
+
[Unit]
|
|
21
|
+
Description=OuterLayer runner
|
|
22
|
+
After=network-online.target${unit.docker ? " docker.service" : ""}
|
|
23
|
+
Wants=network-online.target
|
|
24
|
+
${unit.docker ? "Requires=docker.service\n" : ""}
|
|
25
|
+
[Service]
|
|
26
|
+
User=${unit.user}
|
|
27
|
+
ExecStart=${unit.execStart}
|
|
28
|
+
EnvironmentFile=-${escapeUnitPath(`${unit.configDir}/runner.env`)}
|
|
29
|
+
Restart=on-failure
|
|
30
|
+
RestartForceExitStatus=75
|
|
31
|
+
RestartSec=30
|
|
32
|
+
KillSignal=SIGTERM
|
|
33
|
+
KillMode=mixed
|
|
34
|
+
TimeoutStopSec=${unit.timeLimitMinutes + STOP_MARGIN_MINUTES}min
|
|
35
|
+
OOMPolicy=continue
|
|
36
|
+
Delegate=yes
|
|
37
|
+
|
|
38
|
+
[Install]
|
|
39
|
+
WantedBy=multi-user.target
|
|
40
|
+
`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// src/runner/service/fit.ts
|
|
44
|
+
var GIB = 1024 ** 3;
|
|
45
|
+
var RUNNER_RESERVE_BYTES = 2 * GIB;
|
|
46
|
+
function gib(bytes) {
|
|
47
|
+
return `${Number((bytes / GIB).toFixed(1))} GiB`;
|
|
48
|
+
}
|
|
49
|
+
function checkFit(input) {
|
|
50
|
+
const perBuild = parseSize(input.buildMemory);
|
|
51
|
+
if (perBuild === void 0) return { fits: true };
|
|
52
|
+
const neededBytes = input.concurrency * perBuild;
|
|
53
|
+
const availableBytes = Math.max(0, input.usableBytes - RUNNER_RESERVE_BYTES);
|
|
54
|
+
if (neededBytes <= availableBytes) return { fits: true };
|
|
55
|
+
return {
|
|
56
|
+
fits: false,
|
|
57
|
+
neededBytes,
|
|
58
|
+
availableBytes,
|
|
59
|
+
message: `runner.concurrency ${input.concurrency} times runner.build.memory ${input.buildMemory} needs ${gib(neededBytes)}, and ${gib(availableBytes)} is available (${gib(input.usableBytes)} of memory less ${gib(RUNNER_RESERVE_BYTES)} for the runner and the system)`
|
|
60
|
+
};
|
|
61
|
+
}
|
|
11
62
|
function withSystemd(conf) {
|
|
12
63
|
const lines = (conf ?? "").split("\n");
|
|
13
64
|
if (lines.at(-1) === "") lines.pop();
|
|
@@ -130,7 +181,18 @@ function installService(request, deps) {
|
|
|
130
181
|
if (deps.platform === "wsl2") lines.push(...ensureLoginTask(deps, unitName));
|
|
131
182
|
};
|
|
132
183
|
if (existing === unit) {
|
|
133
|
-
|
|
184
|
+
const wasRunning = running();
|
|
185
|
+
if (!wasRunning && !asRoot(deps, lines, say, ["enable", "--now", unitName])) return outcome(false, "refused", lines);
|
|
186
|
+
if (wasRunning && request.restart === true) {
|
|
187
|
+
ensureTask();
|
|
188
|
+
if (deps.buildsRunning(runnerDir(request.configPath))) {
|
|
189
|
+
lines.push(`the service ${unitName} is current; a build is running, so it was not restarted and reads runner.env at its next restart`);
|
|
190
|
+
return outcome(true, "pending-restart", lines);
|
|
191
|
+
}
|
|
192
|
+
if (!asRoot(deps, lines, say, ["restart", unitName])) return outcome(false, "refused", lines);
|
|
193
|
+
lines.push(`restarted the service ${unitName}, so it reads runner.env`);
|
|
194
|
+
return outcome(true, "updated", lines);
|
|
195
|
+
}
|
|
134
196
|
lines.push(`the service ${unitName} is current: the unit already matches the config, so nothing was changed`);
|
|
135
197
|
ensureTask();
|
|
136
198
|
return outcome(true, "current", lines);
|
|
@@ -212,4 +274,4 @@ function uninstallService(request, deps) {
|
|
|
212
274
|
return outcome(true, "removed", lines);
|
|
213
275
|
}
|
|
214
276
|
|
|
215
|
-
export { DEFAULT_UNIT_NAME, installService, realTaskScheduler, uninstallService, unitPathFor };
|
|
277
|
+
export { DEFAULT_UNIT_NAME, RUNNER_RESERVE_BYTES, VM_SERVICE_NAME, checkFit, installService, realTaskScheduler, uninstallService, unitPathFor };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { RUNNER_DIR_MODE, RUNNER_FILE_MODE } from './chunk-ZM2IMMYN.js';
|
|
4
|
+
import { existsSync, readFileSync, mkdirSync, chmodSync, writeFileSync } from 'fs';
|
|
5
|
+
import { dirname, join } from 'path';
|
|
6
|
+
|
|
7
|
+
createRequire(import.meta.url);
|
|
8
|
+
var ITEM_KEY_FILE = "item-key";
|
|
9
|
+
function itemKeyPath(jobPath) {
|
|
10
|
+
return join(dirname(jobPath), ITEM_KEY_FILE);
|
|
11
|
+
}
|
|
12
|
+
function withItemKey(jobPath, job) {
|
|
13
|
+
let key;
|
|
14
|
+
try {
|
|
15
|
+
key = readFileSync(itemKeyPath(jobPath), "utf8").trim();
|
|
16
|
+
} catch {
|
|
17
|
+
return job;
|
|
18
|
+
}
|
|
19
|
+
return key === "" ? job : { ...job, itemKey: key };
|
|
20
|
+
}
|
|
21
|
+
function writeOwnerOnly(path, content) {
|
|
22
|
+
if (existsSync(path)) chmodSync(path, RUNNER_FILE_MODE);
|
|
23
|
+
writeFileSync(path, content, { mode: RUNNER_FILE_MODE });
|
|
24
|
+
}
|
|
25
|
+
function readJobFile(path) {
|
|
26
|
+
if (!existsSync(path)) return null;
|
|
27
|
+
try {
|
|
28
|
+
return withItemKey(path, JSON.parse(readFileSync(path, "utf8")));
|
|
29
|
+
} catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function readJobFileChecked(path) {
|
|
34
|
+
if (!existsSync(path)) return { kind: "missing" };
|
|
35
|
+
try {
|
|
36
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
37
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return { kind: "unreadable" };
|
|
38
|
+
return { kind: "ok", job: withItemKey(path, parsed) };
|
|
39
|
+
} catch {
|
|
40
|
+
return { kind: "unreadable" };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function writeJobFile(path, job) {
|
|
44
|
+
mkdirSync(dirname(path), { recursive: true, mode: RUNNER_DIR_MODE });
|
|
45
|
+
const { itemKey, ...rest } = job;
|
|
46
|
+
if (itemKey !== void 0) writeOwnerOnly(itemKeyPath(path), itemKey);
|
|
47
|
+
writeOwnerOnly(path, JSON.stringify(rest, null, 2));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { readJobFile, readJobFileChecked, writeJobFile };
|
|
@@ -634,7 +634,7 @@ async function runHookFast(event, home = homeFromEnv(), read = readStdin, env =
|
|
|
634
634
|
recordHookErrorsSeen(home, hookErrorsBytes);
|
|
635
635
|
if (contextPossiblyGoverned(sessionCwd, home)) {
|
|
636
636
|
try {
|
|
637
|
-
const { materializeContext: materialize } = await import('./context-materialize-
|
|
637
|
+
const { materializeContext: materialize } = await import('./context-materialize-7S6NLLRO.js');
|
|
638
638
|
const sessionId = typeof payload.session_id === "string" ? payload.session_id : "unknown";
|
|
639
639
|
const result = await materialize({ cwd: sessionCwd, sessionId, home });
|
|
640
640
|
materializeMessage = result.message;
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
+
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-C6IV5BV7.js';
|
|
4
|
+
import { writePendingUpdate } from './chunk-O765JR4W.js';
|
|
3
5
|
import { readHousekeepingRecord, writeHousekeepingRecord } from './chunk-UGP76IZ5.js';
|
|
4
6
|
import { decideInstalledSwitch } from './chunk-3JVYMD4G.js';
|
|
5
|
-
import { compareVersions, satisfiesRange } from './chunk-I2UOAV7X.js';
|
|
6
7
|
import { fetchVersionMeta, npmVersion, npmSupportsProvenance, fetchTarballDigest, fetchProvenance, installVersion, auditSignatures } from './chunk-YETTWTAY.js';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
8
|
+
import { writeJobFile, readJobFile, readJobFileChecked } from './chunk-RMWLBUCJ.js';
|
|
9
|
+
import { compareVersions, satisfiesRange } from './chunk-I2UOAV7X.js';
|
|
9
10
|
import { RUNNER_PROTOCOL } from './chunk-FI5UYJMQ.js';
|
|
10
|
-
import {
|
|
11
|
-
import { placeholderQueues, placeholderProblem } from './chunk-R7BJYFD2.js';
|
|
12
|
-
import { writeMarker, readMarker, currentVersion, removeMarker, entryIn, versionDir, startedThroughCurrent, switchCurrent, cleanVersions, isInLayout, stagingDir } from './chunk-TI7B7UEO.js';
|
|
11
|
+
import { placeholderQueues, placeholderProblem } from './chunk-TOPDNXHZ.js';
|
|
13
12
|
import { freeBytes, formatBytes } from './chunk-YYYRBYWG.js';
|
|
13
|
+
import { writeMarker, readMarker, currentVersion, removeMarker, entryIn, versionDir, startedThroughCurrent, switchCurrent, cleanVersions, isInLayout, stagingDir } from './chunk-TI7B7UEO.js';
|
|
14
14
|
import { RepoFilter } from './chunk-TBT347UY.js';
|
|
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-
|
|
16
|
-
import { checkFit } 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-MZN7AQOB.js';
|
|
16
|
+
import { checkFit } from './chunk-RLYZLUQ7.js';
|
|
17
17
|
import { startTimeOf, claimPidFile, readPidFile, isSameProcess, releasePidFile } from './chunk-N5FOE5PS.js';
|
|
18
|
-
import { spawnRun } from './chunk-
|
|
19
|
-
import { builderName, runnerLabelValue, ensureFailureCount, builderSpec, ensureBuilder, BUILD_LABEL, RUNNER_LABEL } from './chunk-
|
|
20
|
-
import { isSignatureRefusal, WorkCommandError, getJson, postJson } from './chunk-
|
|
21
|
-
import { isBuiltinContainer, isBuiltinVm, isBuiltinProcess, loadRunnerConfig, checkHooks, builtinKind, DEFAULT_UPDATE_MAX_WAIT_HOURS } from './chunk-
|
|
18
|
+
import { spawnRun } from './chunk-3KTA5UU2.js';
|
|
19
|
+
import { builderName, runnerLabelValue, ensureFailureCount, builderSpec, ensureBuilder, BUILD_LABEL, RUNNER_LABEL } from './chunk-NX57IBNK.js';
|
|
20
|
+
import { isSignatureRefusal, WorkCommandError, getJson, postJson } from './chunk-P4MM66C6.js';
|
|
21
|
+
import { isBuiltinContainer, isBuiltinVm, isBuiltinProcess, loadRunnerConfig, checkHooks, builtinKind, DEFAULT_UPDATE_MAX_WAIT_HOURS } from './chunk-22RMZBGW.js';
|
|
22
22
|
import { exceedsDisk } from './chunk-7RQ73DLO.js';
|
|
23
23
|
import { parseClaimedRepositories, repositoriesOf, primaryOf, sharedUserEnvironment, JOB_MOUNT, claudeCredential } from './chunk-4Q7OMKAT.js';
|
|
24
24
|
import { parseClaimIdentity } from './chunk-BYT5O5RV.js';
|
|
@@ -1315,7 +1315,7 @@ var CLAIM_REFUSAL_CODES = new Set(
|
|
|
1315
1315
|
"pull_request_from_fork pull_request_on_default_branch pull_request_ambiguous pull_request_repository_not_connected branch_claimed_elsewhere".split(" ")
|
|
1316
1316
|
);
|
|
1317
1317
|
async function tryClaimAndStart(state, item, queue) {
|
|
1318
|
-
const { postJson: postJson2 } = await import('./work-cmd-
|
|
1318
|
+
const { postJson: postJson2 } = await import('./work-cmd-X7NMJDFL.js');
|
|
1319
1319
|
const log = logOf(state);
|
|
1320
1320
|
const hostKey = await loadHostKey(state.config.configPath);
|
|
1321
1321
|
const claim = await retrySend(
|
|
@@ -2072,7 +2072,7 @@ async function start(configPath, deps = { fetchImpl: fetch }) {
|
|
|
2072
2072
|
const outcome = await onStartUnderMarker({
|
|
2073
2073
|
configPath,
|
|
2074
2074
|
own: ownVersionOf(deps),
|
|
2075
|
-
check: update.check ? () => update.check(configPath) : async () => (await import('./check-
|
|
2075
|
+
check: update.check ? () => update.check(configPath) : async () => (await import('./check-63IDCEEV.js')).runRunnerCheck(configPath, { fetchImpl: deps.fetchImpl }),
|
|
2076
2076
|
now: () => (deps.now ?? (() => /* @__PURE__ */ new Date()))().getTime(),
|
|
2077
2077
|
log
|
|
2078
2078
|
});
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { DEFAULT_UNIT_NAME } from './chunk-RLYZLUQ7.js';
|
|
4
|
+
import { parseRunnerEnv } from './chunk-6MZSX4M7.js';
|
|
5
|
+
import { RUNNER_FILE_MODE } from './chunk-ZM2IMMYN.js';
|
|
6
|
+
import { existsSync, readFileSync, writeFileSync, renameSync, rmSync } from 'fs';
|
|
7
|
+
import { join, dirname } from 'path';
|
|
8
|
+
|
|
9
|
+
createRequire(import.meta.url);
|
|
10
|
+
var AGENT_COMMANDS = {
|
|
11
|
+
claude: {
|
|
12
|
+
implement: 'claude -p "/build" --permission-mode bypassPermissions',
|
|
13
|
+
amend: 'claude -p "/amend" --permission-mode bypassPermissions'
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
function isAgentName(name) {
|
|
17
|
+
return Object.hasOwn(AGENT_COMMANDS, name);
|
|
18
|
+
}
|
|
19
|
+
var CLAUDE_CREDENTIAL_NAMES = ["CLAUDE_CODE_OAUTH_TOKEN", "ANTHROPIC_API_KEY"];
|
|
20
|
+
var RunnerEnvError = class extends Error {
|
|
21
|
+
};
|
|
22
|
+
var CREDENTIAL_SHAPE = /^sk-ant-(oat|api)[0-9]*-[A-Za-z0-9_-]+$/;
|
|
23
|
+
var SETS = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)=/;
|
|
24
|
+
function runnerEnvPath(configPath) {
|
|
25
|
+
return join(dirname(configPath), "runner.env");
|
|
26
|
+
}
|
|
27
|
+
function credentialFromStdin(text) {
|
|
28
|
+
const value = (text ?? "").trim();
|
|
29
|
+
if (value === "") return void 0;
|
|
30
|
+
const kind = CREDENTIAL_SHAPE.exec(value)?.[1];
|
|
31
|
+
if (kind === void 0) {
|
|
32
|
+
throw new RunnerEnvError(
|
|
33
|
+
"the value on stdin is not a Claude credential, so nothing was written. Pipe one value: a token from `claude setup-token`, which starts sk-ant-oat, or an Anthropic API key, which starts sk-ant-api."
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
return { variable: kind === "oat" ? "CLAUDE_CODE_OAUTH_TOKEN" : "ANTHROPIC_API_KEY", value };
|
|
37
|
+
}
|
|
38
|
+
function hasStoredCredential(configPath) {
|
|
39
|
+
const path = runnerEnvPath(configPath);
|
|
40
|
+
if (!existsSync(path)) return false;
|
|
41
|
+
const env = parseRunnerEnv(readFileSync(path, "utf8"));
|
|
42
|
+
return CLAUDE_CREDENTIAL_NAMES.some((name) => env[name]);
|
|
43
|
+
}
|
|
44
|
+
function storeClaudeCredential(configPath, credential) {
|
|
45
|
+
const path = runnerEnvPath(configPath);
|
|
46
|
+
const kept = existsSync(path) ? readFileSync(path, "utf8").split("\n").filter((line) => !CLAUDE_CREDENTIAL_NAMES.includes(SETS.exec(line)?.[1] ?? "")) : [];
|
|
47
|
+
while (kept[kept.length - 1] === "") kept.pop();
|
|
48
|
+
const text = `${[...kept, `${credential.variable}=${credential.value}`].join("\n")}
|
|
49
|
+
`;
|
|
50
|
+
const temporary = `${path}.${process.pid}.tmp`;
|
|
51
|
+
try {
|
|
52
|
+
writeFileSync(temporary, text, { mode: RUNNER_FILE_MODE, flag: "wx" });
|
|
53
|
+
renameSync(temporary, path);
|
|
54
|
+
} catch (err) {
|
|
55
|
+
rmSync(temporary, { force: true });
|
|
56
|
+
throw err;
|
|
57
|
+
}
|
|
58
|
+
return path;
|
|
59
|
+
}
|
|
60
|
+
function restartForCredential(state, unitName = DEFAULT_UNIT_NAME) {
|
|
61
|
+
if (state !== "pending-restart" && state !== "differs") return void 0;
|
|
62
|
+
return `The service ${unitName} reads runner.env only when it starts. Restart it so it uses the stored credential: sudo systemctl restart ${unitName}`;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export { AGENT_COMMANDS, RunnerEnvError, credentialFromStdin, hasStoredCredential, isAgentName, restartForCredential, storeClaudeCredential };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { splitRawFile } from './chunk-
|
|
3
|
+
import { splitRawFile } from './chunk-2M63GG56.js';
|
|
4
4
|
import { resolvePackageVersion } from './chunk-RA3O54FC.js';
|
|
5
5
|
import { existsSync, readFileSync, mkdirSync, writeFileSync, readdirSync } from 'fs';
|
|
6
6
|
import { join, dirname } from 'path';
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { isPlaceholderCommand } from './chunk-
|
|
4
|
-
import { describeCallFailure } from './chunk-
|
|
5
|
-
import { WorkCommandError, getJson } from './chunk-
|
|
6
|
-
import { sanitizeTerminal } from './chunk-
|
|
7
|
-
import { builtinKind } from './chunk-
|
|
3
|
+
import { isPlaceholderCommand } from './chunk-MJXXRX4M.js';
|
|
4
|
+
import { describeCallFailure } from './chunk-MZN7AQOB.js';
|
|
5
|
+
import { WorkCommandError, getJson } from './chunk-P4MM66C6.js';
|
|
6
|
+
import { sanitizeTerminal } from './chunk-CNFVHDHG.js';
|
|
7
|
+
import { builtinKind } from './chunk-22RMZBGW.js';
|
|
8
8
|
import { CLAUDE_CREDENTIAL_VARIABLES, claudeCredential } from './chunk-4Q7OMKAT.js';
|
|
9
9
|
import { signerFor } from './chunk-V7NIVOFD.js';
|
|
10
10
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import { LiveUploader } from './chunk-
|
|
4
|
-
import { CaptureDaemon } from './chunk-
|
|
3
|
+
import { LiveUploader } from './chunk-3D4OYFCD.js';
|
|
4
|
+
import { CaptureDaemon } from './chunk-JXYVA45C.js';
|
|
5
5
|
import { parseWorkItemEnv } from './chunk-GQD22KKN.js';
|
|
6
|
-
import { spoolDir } from './chunk-
|
|
6
|
+
import { spoolDir } from './chunk-SFFHGX3G.js';
|
|
7
7
|
import { homeFromEnv } from './chunk-VNVZDWO3.js';
|
|
8
8
|
import { mkdirSync, writeFileSync, rmSync } from 'fs';
|
|
9
9
|
import { join } from 'path';
|