@outerlayer/cli 0.2.0 → 0.4.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 +124 -0
- package/README.md +226 -59
- package/dist/agent-setup-IFH3FB5X.js +197 -0
- package/dist/build-TZUUTRGH.js +9 -0
- package/dist/build-info.json +1 -1
- package/dist/check-WQP2CZDW.js +94 -0
- package/dist/chunk-2E54Z3P5.js +232 -0
- package/dist/chunk-3TT7RQYB.js +55 -0
- package/dist/{chunk-U32VSRLO.js → chunk-3YPKXE5L.js} +90 -632
- package/dist/{chunk-Q6CL5THG.js → chunk-5DLBAXY5.js} +208 -61
- package/dist/{chunk-R5KBGVII.js → chunk-5QRP3MVS.js} +30 -14
- package/dist/chunk-5Y3QQRUH.js +300 -0
- package/dist/chunk-6Y63SXFO.js +383 -0
- package/dist/chunk-774HEQL6.js +178 -0
- package/dist/chunk-7A6RVXPZ.js +2233 -0
- package/dist/chunk-7YIOOFVJ.js +71 -0
- package/dist/chunk-ABIWDUMS.js +104 -0
- package/dist/chunk-AUFG23AA.js +534 -0
- package/dist/chunk-B2G7JHHB.js +42 -0
- package/dist/chunk-BCJNHMZT.js +34 -0
- package/dist/chunk-BCLJSQCV.js +56 -0
- package/dist/chunk-BFESLKPP.js +61 -0
- package/dist/chunk-BJ3KTMDH.js +63 -0
- package/dist/chunk-BKO6JEZI.js +47 -0
- package/dist/chunk-BOLTI6LR.js +37 -0
- package/dist/chunk-CBPPJSAR.js +89 -0
- package/dist/chunk-CBZB6XY6.js +102 -0
- package/dist/{chunk-65WXAANR.js → chunk-DVDEBNQJ.js} +17 -2
- package/dist/{work-pr-cmd-AZQPWH4H.js → chunk-DVYHCMB2.js} +9 -26
- package/dist/{chunk-TFUIDMOB.js → chunk-EABW6AJQ.js} +12 -1
- package/dist/{chunk-KFYJV2ZG.js → chunk-EMY4I27X.js} +1 -1
- package/dist/{chunk-NTTPJV35.js → chunk-F47JBIAW.js} +3 -1
- package/dist/chunk-F6GFZXZ3.js +60 -0
- package/dist/{chunk-YOOSBOKS.js → chunk-F7CU5ABH.js} +1 -1
- package/dist/chunk-FAJSS2WN.js +1357 -0
- package/dist/chunk-FS2VYGZT.js +1764 -0
- package/dist/chunk-FV2CCGXK.js +9 -0
- package/dist/{chunk-4TNZMO7V.js → chunk-G7FSV7JX.js} +3452 -751
- package/dist/{emit-cmd-TWSYYEZI.js → chunk-H5NCNVDA.js} +68 -17
- package/dist/chunk-HE2D4EY5.js +83 -0
- package/dist/chunk-L2DBRKRA.js +94 -0
- package/dist/chunk-LF6MLJCY.js +38 -0
- package/dist/chunk-M5POMKKW.js +1051 -0
- package/dist/{mcp-install-cmd-FDQH6SEN.js → chunk-MQ3IPHIZ.js} +35 -18
- package/dist/{chunk-D77LS3UI.js → chunk-N5FOE5PS.js} +33 -4
- package/dist/chunk-N6LURUEF.js +64 -0
- package/dist/chunk-NYC54VBD.js +1084 -0
- package/dist/chunk-OGFGZQA3.js +23 -0
- package/dist/chunk-QOZKPLVJ.js +226 -0
- package/dist/chunk-RA3O54FC.js +30 -0
- package/dist/chunk-TBT347UY.js +41 -0
- package/dist/{chunk-NXLLURA4.js → chunk-UFFXNXLQ.js} +115 -71
- package/dist/chunk-USO2DKBD.js +421 -0
- package/dist/chunk-W4SQCOZU.js +206 -0
- package/dist/{chunk-A3WLZX2F.js → chunk-WIOZAJ2W.js} +15 -2
- package/dist/chunk-WO2BXCTQ.js +83 -0
- package/dist/{chunk-I3ETLSNE.js → chunk-XCCLFVXM.js} +120 -11
- package/dist/{context-materialize-6WKT3RBQ.js → chunk-XDDW4FRS.js} +134 -26
- package/dist/chunk-YYYXRJUW.js +101 -0
- package/dist/chunk-ZM2IMMYN.js +76 -0
- package/dist/chunk-ZMYPLFG3.js +71 -0
- package/dist/chunk-ZNA27WEV.js +470 -0
- package/dist/{cli-G7DILYJY.js → cli-NHUXABYH.js} +590 -876
- package/dist/{paths-D2VGWWFI.js → cli-build-K56DK4DS.js} +1 -1
- package/dist/config-XVJYZ4IQ.js +9 -0
- package/dist/connect-cmd-OOG4TPU7.js +16 -0
- package/dist/context-adopt-UMA4O5NY.js +105 -0
- package/dist/context-materialize-G2FUFC72.js +19 -0
- package/dist/dist-RW4UPPC2.js +6 -0
- package/dist/docker-NEGDLU6D.js +7 -0
- package/dist/doctor-53F2PYY7.js +43 -0
- package/dist/doctor-UFVL4PZY.js +426 -0
- package/dist/{emit-artifact-cmd-UQVT3OKW.js → emit-artifact-cmd-KTYW2TN2.js} +24 -20
- package/dist/emit-cmd-DCERAU27.js +9 -0
- package/dist/emit-criteria-cmd-VAUUSAYD.js +166 -0
- package/dist/{emit-finding-cmd-FDOU2OPD.js → emit-finding-cmd-UR4ID45Z.js} +34 -31
- package/dist/{emit-result-cmd-H2T4C2K3.js → emit-result-cmd-FDTUKGKE.js} +34 -62
- package/dist/exec-client-4XGXV3XN.js +8 -0
- package/dist/guest-init-GENRHNP7.js +8 -0
- package/dist/hook-fast-EYENPK6F.js +9 -0
- package/dist/{hook-wrap-fast-KXYNX3AD.js → hook-wrap-fast-NPLHJXFK.js} +2 -2
- package/dist/host-key-KDYZ5ECC.js +7 -0
- package/dist/import-capture-cmd-AVZ4VIVJ.js +68 -0
- package/dist/{import-ruler-cmd-7LH2QOMG.js → import-ruler-cmd-GUHL6IY5.js} +1 -1
- package/dist/index.js +4 -4
- package/dist/init-DXBCOAJK.js +36 -0
- package/dist/init-YEXK35CF.js +221 -0
- package/dist/init-cmd-NHR7PRSQ.js +135 -0
- package/dist/install-cmd-7WXOIFDO.js +55 -0
- package/dist/lima-XN65D7GN.js +55 -0
- package/dist/login-browser-7XGSV7MA.js +10 -0
- package/dist/{config-POF7DEQW.js → logout-cmd-QAUFDJ6J.js} +3 -1
- package/dist/{logs-TRNPQM42.js → logs-7RYUH5A6.js} +1 -1
- package/dist/loop-VZOLL4WQ.js +43 -0
- package/dist/machine-WSG52J75.js +35 -0
- package/dist/mcp-install-cmd-RLK4SO3N.js +9 -0
- package/dist/{mcp-serve-cmd-57EZZOTL.js → mcp-serve-cmd-JPTP5FMS.js} +20 -9
- package/dist/paths-OYKMVYJP.js +6 -0
- package/dist/{pidfile-PTW76F56.js → pidfile-UZRH774M.js} +2 -3
- package/dist/real-deps-SU24ZA2K.js +21 -0
- package/dist/relay-L76HDX72.js +46 -0
- package/dist/settings-J2652U5N.js +7 -0
- package/dist/starter-pack-LIZYMKYQ.js +10 -0
- package/dist/{status-I27IST4L.js → status-2UZKKNB7.js} +30 -13
- package/dist/{statusline-fast-3C5OXHDD.js → statusline-fast-SVTMBMD7.js} +3 -2
- package/dist/sync-cmd-VPPYCNNM.js +28 -0
- package/dist/version-BWM6VLDI.js +6 -0
- package/dist/{watch-3DTPJETH.js → watch-5C4ZBBGO.js} +19 -8
- package/dist/{work-claim-cmd-5AUNCLS2.js → work-claim-cmd-LSO2B2EX.js} +33 -20
- package/dist/work-cmd-UOQO2AD4.js +17 -0
- package/dist/work-comment-cmd-WF3EOLAE.js +106 -0
- package/dist/{work-launch-LT663PB3.js → work-launch-YI4CJDAP.js} +1 -1
- package/dist/work-open-pr-cmd-4SSQZMYG.js +156 -0
- package/dist/work-pr-cmd-6AN6RRQJ.js +16 -0
- package/package.json +13 -3
- package/skill-pack/maintained/amend/SKILL.md +104 -0
- package/skill-pack/maintained/emitting-evidence/SKILL.md +99 -0
- package/skill-pack/maintained/emitting-evidence/references/agents-snippet.md +20 -0
- package/skill-pack/maintained/outerlayer/SKILL.md +55 -0
- package/skill-pack/maintained/reporting-findings/SKILL.md +148 -0
- package/skill-pack/template/build/SKILL.md +193 -0
- package/skill-pack/template/build/references/agent-briefs.md +243 -0
- package/skill-pack/template/build/references/criteria-judge.md +91 -0
- package/skill-pack/template/build/references/evidence.md +42 -0
- package/skill-pack/template/build/references/release.md +74 -0
- package/skill-pack/template/build/references/review-briefs.md +275 -0
- package/skill-pack/template/build/references/review-loop.md +158 -0
- package/skill-pack/template/build/scripts/record-criteria.mjs +235 -0
- package/skill-pack/template/spec/SKILL.md +84 -0
- package/skill-pack/template/writing-specs/SKILL.md +134 -0
- package/dist/chunk-DCNOXRMV.js +0 -589
- package/dist/chunk-JJP7YLMN.js +0 -25
- package/dist/chunk-OZ7C3XUE.js +0 -34
- package/dist/chunk-WQ6VGRGZ.js +0 -150
- package/dist/hook-fast-J5LCDHUJ.js +0 -8
- package/dist/import-capture-cmd-EUMBGIV3.js +0 -176
- package/dist/init-PTBITAUO.js +0 -103
- package/dist/login-cmd-IRX6LZT7.js +0 -62
- package/dist/loop-ASZRX3CZ.js +0 -648
- package/dist/sync-cmd-BBAUZ5JD.js +0 -17
- package/dist/work-cmd-2P4BVX47.js +0 -18
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import {
|
|
4
|
-
import './chunk-
|
|
3
|
+
import { maintainedFilesForExistingSkills, loadMaintainedFiles, writeMaintainedFiles } from './chunk-WO2BXCTQ.js';
|
|
4
|
+
import { emitTree, parseOuterlayerConfig, classifyTree, generatedHeaderSource, CONTEXT_PIN_FILENAME, normalizePath } from './chunk-EMY4I27X.js';
|
|
5
5
|
import { existsSync, readFileSync, mkdirSync, writeFileSync, copyFileSync, readdirSync } from 'fs';
|
|
6
6
|
import { join, dirname, relative, sep } from 'path';
|
|
7
7
|
|
|
@@ -53,19 +53,21 @@ function walk(dir, repoRoot, insideOuterlayer, out) {
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
-
function buildEmitInput(repoRoot, targets) {
|
|
57
|
-
const
|
|
56
|
+
function buildEmitInput(repoRoot, targets, maintained) {
|
|
57
|
+
const bundled = new Map(maintained.map((f) => [f.path, f.content]));
|
|
58
|
+
const discovered = [.../* @__PURE__ */ new Set([...discoverOuterlayerPaths(repoRoot), ...bundled.keys()])].sort();
|
|
58
59
|
const { entries } = classifyTree(discovered);
|
|
59
60
|
const classified = new Set(entries.map((e) => e.path));
|
|
60
61
|
const contents = /* @__PURE__ */ new Map();
|
|
61
62
|
for (const entry of entries) {
|
|
62
63
|
if (!CONTENT_KINDS.has(entry.kind)) continue;
|
|
63
|
-
contents.set(entry.path, readFileSync(join(repoRoot, entry.path), "utf8"));
|
|
64
|
+
contents.set(entry.path, bundled.get(entry.path) ?? readFileSync(join(repoRoot, entry.path), "utf8"));
|
|
64
65
|
}
|
|
65
66
|
const assetPaths = discovered.filter((p) => !classified.has(p));
|
|
66
67
|
return { input: { entries, contents, assetPaths, targets }, sourcePaths: classified };
|
|
67
68
|
}
|
|
68
|
-
function writeOutputs(repoRoot, result) {
|
|
69
|
+
function writeOutputs(repoRoot, result, maintained) {
|
|
70
|
+
const changedMaintained = writeMaintainedFiles(repoRoot, maintained);
|
|
69
71
|
const files = [];
|
|
70
72
|
for (const file of result.files) {
|
|
71
73
|
const abs = join(repoRoot, file.path);
|
|
@@ -80,11 +82,15 @@ function writeOutputs(repoRoot, result) {
|
|
|
80
82
|
copyFileSync(join(repoRoot, copy.fromSourcePath), abs);
|
|
81
83
|
copies.push(copy.toPath);
|
|
82
84
|
}
|
|
83
|
-
return { files, copies };
|
|
85
|
+
return { files, copies, maintained: [...changedMaintained.created, ...changedMaintained.rewritten] };
|
|
84
86
|
}
|
|
85
|
-
function renderSuccess(targets, files, copies) {
|
|
87
|
+
function renderSuccess(targets, files, copies, maintained) {
|
|
86
88
|
const copySuffix = copies.length > 0 ? `, ${copies.length} ${copies.length === 1 ? "copy" : "copies"}` : "";
|
|
87
|
-
|
|
89
|
+
const lines = [
|
|
90
|
+
`${GREEN}\u2713${RESET} emitted ${files.length} file${files.length === 1 ? "" : "s"}${copySuffix} for ${DIM}${targets.join(", ")}${RESET}`
|
|
91
|
+
];
|
|
92
|
+
for (const path of maintained) lines.push(` ${DIM}updated ${path} to this CLI's version${RESET}`);
|
|
93
|
+
return lines.join("\n");
|
|
88
94
|
}
|
|
89
95
|
function renderFailure(errors) {
|
|
90
96
|
const lines = [`${RED}\u2717${RESET} emit failed \u2014 nothing written`];
|
|
@@ -150,17 +156,48 @@ function findOrphans(repoRoot, computedFiles, sourcePaths) {
|
|
|
150
156
|
}
|
|
151
157
|
return orphans;
|
|
152
158
|
}
|
|
159
|
+
function withholdKept(repoRoot, result, keep) {
|
|
160
|
+
if (keep === void 0) return { result, kept: [] };
|
|
161
|
+
const kept = [];
|
|
162
|
+
const files = result.files.filter((file) => {
|
|
163
|
+
const abs = join(repoRoot, file.path);
|
|
164
|
+
if (!existsSync(abs)) return true;
|
|
165
|
+
const existing = readFileSync(abs, "utf8");
|
|
166
|
+
if (existing === file.content || !keep({ kind: "file", path: file.path, existing, content: file.content })) return true;
|
|
167
|
+
kept.push(file.path);
|
|
168
|
+
return false;
|
|
169
|
+
});
|
|
170
|
+
const copies = result.copies.filter((copy) => {
|
|
171
|
+
const abs = join(repoRoot, copy.toPath);
|
|
172
|
+
if (!existsSync(abs)) return true;
|
|
173
|
+
const src = join(repoRoot, copy.fromSourcePath);
|
|
174
|
+
if (existsSync(src) && readFileSync(abs).equals(readFileSync(src))) return true;
|
|
175
|
+
if (!keep({ kind: "copy", path: copy.toPath, source: copy.fromSourcePath })) return true;
|
|
176
|
+
kept.push(copy.toPath);
|
|
177
|
+
return false;
|
|
178
|
+
});
|
|
179
|
+
return { result: { ...result, files, copies }, kept: kept.sort() };
|
|
180
|
+
}
|
|
153
181
|
function runEmit(opts = {}) {
|
|
154
182
|
const cwd = opts.cwd ?? process.cwd();
|
|
155
183
|
if (!existsSync(cwd)) throw new EmitError(`no such directory: ${cwd}`);
|
|
156
184
|
const targets = resolveTargetsFromConfig(cwd);
|
|
157
|
-
const
|
|
158
|
-
const
|
|
185
|
+
const maintained = maintainedFilesForExistingSkills(cwd, loadMaintainedFiles());
|
|
186
|
+
const built = buildEmitInput(cwd, targets, maintained);
|
|
187
|
+
const emitted = emitTree(built.input);
|
|
188
|
+
const { result, kept } = withholdKept(cwd, emitted, opts.keep);
|
|
159
189
|
const hasErrors = result.errors.length > 0;
|
|
160
|
-
if (opts.check) return runCheck(cwd, opts, targets, result, hasErrors, built.sourcePaths);
|
|
161
|
-
const written = hasErrors ? { files: [], copies: [] } : writeOutputs(cwd, result);
|
|
190
|
+
if (opts.check) return runCheck(cwd, opts, targets, result, hasErrors, built.sourcePaths, maintained, kept);
|
|
191
|
+
const written = hasErrors ? { files: [], copies: [], maintained: [] } : writeOutputs(cwd, result, maintained);
|
|
162
192
|
const exitCode = hasErrors ? 1 : 0;
|
|
163
|
-
const output = opts.json ? JSON.stringify({
|
|
193
|
+
const output = opts.json ? JSON.stringify({
|
|
194
|
+
targets,
|
|
195
|
+
files: written.files,
|
|
196
|
+
copies: written.copies,
|
|
197
|
+
maintained: written.maintained,
|
|
198
|
+
warnings: result.warnings,
|
|
199
|
+
errors: result.errors
|
|
200
|
+
}) : hasErrors ? renderFailure(result.errors) : renderSuccess(targets, written.files, written.copies, written.maintained);
|
|
164
201
|
if (!opts.quiet) {
|
|
165
202
|
if (opts.json) {
|
|
166
203
|
process.stdout.write(output + "\n");
|
|
@@ -172,11 +209,25 @@ function runEmit(opts = {}) {
|
|
|
172
209
|
`);
|
|
173
210
|
}
|
|
174
211
|
}
|
|
175
|
-
return {
|
|
212
|
+
return {
|
|
213
|
+
targets,
|
|
214
|
+
files: written.files,
|
|
215
|
+
copies: written.copies,
|
|
216
|
+
maintained: written.maintained,
|
|
217
|
+
kept,
|
|
218
|
+
warnings: result.warnings,
|
|
219
|
+
errors: result.errors,
|
|
220
|
+
output,
|
|
221
|
+
exitCode
|
|
222
|
+
};
|
|
176
223
|
}
|
|
177
|
-
function runCheck(cwd, opts, targets, result, hasErrors, sourcePaths) {
|
|
224
|
+
function runCheck(cwd, opts, targets, result, hasErrors, sourcePaths, maintained, kept) {
|
|
178
225
|
const drift = [];
|
|
179
226
|
if (!hasErrors) {
|
|
227
|
+
for (const file of maintained) {
|
|
228
|
+
const d = compareFile(cwd, file.path, file.content);
|
|
229
|
+
if (d) drift.push(d);
|
|
230
|
+
}
|
|
180
231
|
const computedFiles = new Set(result.files.map((f) => f.path));
|
|
181
232
|
for (const file of result.files) {
|
|
182
233
|
const d = compareFile(cwd, file.path, file.content);
|
|
@@ -202,7 +253,7 @@ function runCheck(cwd, opts, targets, result, hasErrors, sourcePaths) {
|
|
|
202
253
|
`);
|
|
203
254
|
}
|
|
204
255
|
}
|
|
205
|
-
return { targets, files: [], copies: [], warnings: result.warnings, errors: result.errors, drift, output, exitCode };
|
|
256
|
+
return { targets, files: [], copies: [], maintained: [], kept, warnings: result.warnings, errors: result.errors, drift, output, exitCode };
|
|
206
257
|
}
|
|
207
258
|
|
|
208
259
|
export { EmitError, runEmit };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { setCustomScrubbers, setLocalIdentity, setRepoRoot, resolveRepoIdentity, scrubDeep, downconvertSession, isHumanUserTurn, turnCountBound } from './chunk-G7FSV7JX.js';
|
|
4
|
+
import { execFileSync } from 'child_process';
|
|
5
|
+
import { hostname, userInfo } from 'os';
|
|
6
|
+
|
|
7
|
+
createRequire(import.meta.url);
|
|
8
|
+
function detectCi(env = process.env) {
|
|
9
|
+
return env.CI === "true" || env.CI === "1" || !!env.JENKINS_URL;
|
|
10
|
+
}
|
|
11
|
+
function gitGlobalConfig(key) {
|
|
12
|
+
try {
|
|
13
|
+
return execFileSync("git", ["config", "--global", key], { encoding: "utf8", timeout: 2e3 }).trim() || void 0;
|
|
14
|
+
} catch {
|
|
15
|
+
return void 0;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function installScrubContext(home, scrub) {
|
|
19
|
+
setCustomScrubbers(scrub);
|
|
20
|
+
setLocalIdentity({
|
|
21
|
+
name: gitGlobalConfig("user.name"),
|
|
22
|
+
email: gitGlobalConfig("user.email"),
|
|
23
|
+
username: (() => {
|
|
24
|
+
try {
|
|
25
|
+
return userInfo().username;
|
|
26
|
+
} catch {
|
|
27
|
+
return void 0;
|
|
28
|
+
}
|
|
29
|
+
})(),
|
|
30
|
+
hostname: (() => {
|
|
31
|
+
try {
|
|
32
|
+
return hostname();
|
|
33
|
+
} catch {
|
|
34
|
+
return void 0;
|
|
35
|
+
}
|
|
36
|
+
})(),
|
|
37
|
+
home
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function applyContextProvenance(session, record) {
|
|
41
|
+
if (!record) return;
|
|
42
|
+
if (record.repository !== void 0) session.env.contextSourceRepo = record.repository;
|
|
43
|
+
if (record.ref !== void 0) session.env.contextSourceRef = record.ref;
|
|
44
|
+
if (record.sha !== null) session.env.contextSourceSha = record.sha;
|
|
45
|
+
session.env.contextSourceVerification = record.verification;
|
|
46
|
+
}
|
|
47
|
+
function prepareSessionForUpload(session, tier, envVars = process.env) {
|
|
48
|
+
setRepoRoot(resolveRepoIdentity(session.env.cwd).repoRoot);
|
|
49
|
+
scrubDeep(session);
|
|
50
|
+
session.workerKind ??= detectCi(envVars) ? "ci" : "seat";
|
|
51
|
+
return downconvertSession(session, tier);
|
|
52
|
+
}
|
|
53
|
+
var MAX_TOOL_IO_CHARS = 64e3;
|
|
54
|
+
function sliceToolIo(value) {
|
|
55
|
+
const text = typeof value === "string" ? value : JSON.stringify(value);
|
|
56
|
+
if (typeof text !== "string" || text.length <= MAX_TOOL_IO_CHARS) return value;
|
|
57
|
+
return `${text.slice(0, MAX_TOOL_IO_CHARS)}\u2026[sliced: ${text.length} chars exceeded the sync per-call cap]`;
|
|
58
|
+
}
|
|
59
|
+
function sliceTurnIo(turn) {
|
|
60
|
+
return {
|
|
61
|
+
...turn,
|
|
62
|
+
toolCalls: (turn.toolCalls ?? []).map((call) => ({
|
|
63
|
+
...call,
|
|
64
|
+
...call.input !== void 0 ? { input: sliceToolIo(call.input) } : {},
|
|
65
|
+
...call.output !== void 0 ? { output: sliceToolIo(call.output) } : {}
|
|
66
|
+
}))
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function wholeSessionCounts(turns) {
|
|
70
|
+
const allCalls = turns.flatMap((t) => t.toolCalls ?? []);
|
|
71
|
+
return {
|
|
72
|
+
// An index BOUND (`1 + max(turn.index)`), not the shipped turn count —
|
|
73
|
+
// turn indexes are not guaranteed dense from zero, and a late artifact
|
|
74
|
+
// anchored at its real turn index must still validate against the
|
|
75
|
+
// summary row this produces (see turnCountBound).
|
|
76
|
+
turns: turnCountBound(turns),
|
|
77
|
+
toolCalls: allCalls.length,
|
|
78
|
+
errors: allCalls.filter((c) => c.status === "error").length,
|
|
79
|
+
userTurns: turns.filter(isHumanUserTurn).length
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export { applyContextProvenance, detectCi, installScrubContext, prepareSessionForUpload, sliceTurnIo, wholeSessionCounts };
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { MIN_ENGINE_MAJOR } from './chunk-7A6RVXPZ.js';
|
|
4
|
+
import { firecrackerArch, MICROVM_ARCHES, guestAssetsPinned } from './chunk-ZNA27WEV.js';
|
|
5
|
+
import { spawnSync } from 'child_process';
|
|
6
|
+
import { existsSync, accessSync, constants, statSync, readFileSync } from 'fs';
|
|
7
|
+
|
|
8
|
+
createRequire(import.meta.url);
|
|
9
|
+
function groupName(gid) {
|
|
10
|
+
try {
|
|
11
|
+
for (const line of readFileSync("/etc/group", "utf8").split("\n")) {
|
|
12
|
+
const [name, , id] = line.split(":");
|
|
13
|
+
if (name !== void 0 && Number(id) === gid) return name;
|
|
14
|
+
}
|
|
15
|
+
} catch {
|
|
16
|
+
}
|
|
17
|
+
return String(gid);
|
|
18
|
+
}
|
|
19
|
+
function detectKvm(device) {
|
|
20
|
+
if (!existsSync(device)) return { state: "absent" };
|
|
21
|
+
try {
|
|
22
|
+
accessSync(device, constants.R_OK | constants.W_OK);
|
|
23
|
+
return { state: "usable" };
|
|
24
|
+
} catch {
|
|
25
|
+
return { state: "no-permission", group: groupName(statSync(device).gid) };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function readProcVersion() {
|
|
29
|
+
try {
|
|
30
|
+
return readFileSync("/proc/version", "utf8");
|
|
31
|
+
} catch {
|
|
32
|
+
return void 0;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function docker(args) {
|
|
36
|
+
const result = spawnSync("docker", args, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 15e3 });
|
|
37
|
+
const out = result.status === 0 ? result.stdout.trim() : "";
|
|
38
|
+
return out === "" ? void 0 : out;
|
|
39
|
+
}
|
|
40
|
+
function dockerFailure() {
|
|
41
|
+
const result = spawnSync("docker", ["version", "--format", "{{.Server.Version}}"], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], timeout: 15e3 });
|
|
42
|
+
if (result.error?.code === "ENOENT") return void 0;
|
|
43
|
+
return /permission denied/i.test(result.stderr ?? "") ? "permission" : "daemon";
|
|
44
|
+
}
|
|
45
|
+
function platformOf(probes) {
|
|
46
|
+
const platform = probes.platform ?? process.platform;
|
|
47
|
+
if (platform === "win32") return "windows";
|
|
48
|
+
if (platform === "darwin") return "darwin";
|
|
49
|
+
if (platform !== "linux") return "other";
|
|
50
|
+
return /microsoft/i.test((probes.procVersion ?? readProcVersion)() ?? "") ? "wsl2" : "linux";
|
|
51
|
+
}
|
|
52
|
+
function detectMachine(probes = {}) {
|
|
53
|
+
const platform = platformOf(probes);
|
|
54
|
+
const kvm = (probes.kvm ?? (() => detectKvm(probes.kvmDevice ?? "/dev/kvm")))();
|
|
55
|
+
const arch = firecrackerArch(probes.nodeArch ?? process.arch);
|
|
56
|
+
const version = (probes.dockerVersion ?? (() => docker(["version", "--format", "{{.Server.Version}}"])))();
|
|
57
|
+
if (version === void 0) {
|
|
58
|
+
const failure = (probes.dockerFailure ?? (probes.dockerVersion === void 0 ? dockerFailure : () => void 0))();
|
|
59
|
+
return { platform, docker: failure === void 0 ? { kind: "none" } : { kind: "unreachable", reason: failure }, kvm, arch };
|
|
60
|
+
}
|
|
61
|
+
const system = (probes.dockerOperatingSystem ?? (() => docker(["info", "--format", "{{.OperatingSystem}}"])))() ?? "";
|
|
62
|
+
return { platform, docker: { kind: /docker desktop/i.test(system) ? "desktop" : "engine", version }, kvm, arch };
|
|
63
|
+
}
|
|
64
|
+
function supportsContainerBuilds(machine) {
|
|
65
|
+
if (machine.platform !== "linux" && machine.platform !== "wsl2") return false;
|
|
66
|
+
return machine.docker.kind === "engine" && Number.parseInt(machine.docker.version ?? "", 10) >= MIN_ENGINE_MAJOR;
|
|
67
|
+
}
|
|
68
|
+
function supportsMicroVmBuilds(machine) {
|
|
69
|
+
return machine.platform === "linux" && machine.kvm?.state === "usable" && supportsContainerBuilds(machine) && microVmAssetsPinned(machine);
|
|
70
|
+
}
|
|
71
|
+
function microVmArchSupported(machine) {
|
|
72
|
+
return MICROVM_ARCHES.includes(machine.arch ?? "");
|
|
73
|
+
}
|
|
74
|
+
function microVmAssetsPinned(machine) {
|
|
75
|
+
return microVmArchSupported(machine) && guestAssetsPinned(machine.arch);
|
|
76
|
+
}
|
|
77
|
+
function reachDockerStep(machine) {
|
|
78
|
+
if (machine.docker.kind !== "unreachable") return void 0;
|
|
79
|
+
return machine.docker.reason === "permission" ? "give this user access to Docker Engine's socket (add it to the docker group, then log in again)" : "start Docker Engine's daemon (for example, sudo systemctl start docker)";
|
|
80
|
+
}
|
|
81
|
+
function describeMachineDocker(machine) {
|
|
82
|
+
const { kind, version, reason } = machine.docker;
|
|
83
|
+
const where = machine.platform === "windows" ? "Windows" : machine.platform === "darwin" ? "macOS" : machine.platform === "wsl2" ? "WSL2" : "Linux";
|
|
84
|
+
if (kind === "desktop") return `Docker Desktop ${version ?? ""} on ${where}, which cannot pass a Unix socket into a container`.replace(" ", " ");
|
|
85
|
+
if (kind === "none") return `no Docker on ${where}`;
|
|
86
|
+
if (kind === "unreachable") {
|
|
87
|
+
const problem = reason === "permission" ? "this user has no permission on its socket" : "its daemon is not running";
|
|
88
|
+
return `a docker command on ${where} that cannot reach Docker Engine (${problem})`;
|
|
89
|
+
}
|
|
90
|
+
if (machine.platform !== "linux" && machine.platform !== "wsl2") return `Docker Engine ${version ?? ""} on ${where}, which cannot isolate a build`.replace(" ", " ");
|
|
91
|
+
return `Docker Engine ${version ?? "of no known version"}, older than the ${MIN_ENGINE_MAJOR} that container builds need`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export { describeMachineDocker, detectMachine, microVmArchSupported, microVmAssetsPinned, reachDockerStep, supportsContainerBuilds, supportsMicroVmBuilds };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
3
|
+
import { mkdirSync, writeFileSync } from 'fs';
|
|
4
|
+
import { join, dirname } from 'path';
|
|
5
|
+
|
|
6
|
+
createRequire(import.meta.url);
|
|
7
|
+
var LAUNCH_AGENT_LABEL = "ai.outerlayer.runner-vm";
|
|
8
|
+
function launchAgentPath(home) {
|
|
9
|
+
return join(home, "Library", "LaunchAgents", `${LAUNCH_AGENT_LABEL}.plist`);
|
|
10
|
+
}
|
|
11
|
+
var escapeXml = (text) => text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
12
|
+
function launchAgentPlist(limactl, instance) {
|
|
13
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
14
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
15
|
+
<plist version="1.0">
|
|
16
|
+
<dict>
|
|
17
|
+
<key>Label</key>
|
|
18
|
+
<string>${LAUNCH_AGENT_LABEL}</string>
|
|
19
|
+
<key>ProgramArguments</key>
|
|
20
|
+
<array>
|
|
21
|
+
<string>${escapeXml(limactl)}</string>
|
|
22
|
+
<string>start</string>
|
|
23
|
+
<string>${escapeXml(instance)}</string>
|
|
24
|
+
</array>
|
|
25
|
+
<key>RunAtLoad</key>
|
|
26
|
+
<true/>
|
|
27
|
+
</dict>
|
|
28
|
+
</plist>
|
|
29
|
+
`;
|
|
30
|
+
}
|
|
31
|
+
function writeLaunchAgent(home, limactl, instance) {
|
|
32
|
+
const path = launchAgentPath(home);
|
|
33
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
34
|
+
writeFileSync(path, launchAgentPlist(limactl, instance));
|
|
35
|
+
return path;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export { launchAgentPath, writeLaunchAgent };
|