@sleds/cli 0.1.68 → 0.1.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/sleds.mjs +176 -63
- package/package.json +1 -1
package/dist/sleds.mjs
CHANGED
|
@@ -11563,7 +11563,20 @@ var mainCheckoutOf = (gitCommonDir, cwd) => {
|
|
|
11563
11563
|
const main = dir.slice(0, -"/.git".length);
|
|
11564
11564
|
return main && main !== cwd.replace(/\/+$/, "") ? main : null;
|
|
11565
11565
|
};
|
|
11566
|
-
var
|
|
11566
|
+
var trimDir = (dir) => dir.replace(/\/+$/, "") || "/";
|
|
11567
|
+
var within = (path, dir) => {
|
|
11568
|
+
const p = trimDir(path);
|
|
11569
|
+
const d = trimDir(dir);
|
|
11570
|
+
return p === d || p.startsWith(d === "/" ? "/" : `${d}/`);
|
|
11571
|
+
};
|
|
11572
|
+
var sessionReadDirs = (o) => {
|
|
11573
|
+
const cwd = trimDir(o.cwd);
|
|
11574
|
+
const dirs = [o.mainCheckout, ...o.worktrees ?? [], o.pnpmStore].filter((d) => !!d?.trim()).map(trimDir);
|
|
11575
|
+
return [...new Set(dirs)].filter((d) => d !== cwd);
|
|
11576
|
+
};
|
|
11577
|
+
var readOnlyDirs = (readDirs, cwd, keep = []) => readDirs.filter((d) => ![cwd, ...keep].some((p) => within(p, d)));
|
|
11578
|
+
var readOnlyDenyRules = (dirs) => dirs.map((d) => `Edit(${absRule(d)})`);
|
|
11579
|
+
var claudeAddDirFlag = (dirs = []) => dirs.map((d) => ` --add-dir=${shq(d)}`).join("");
|
|
11567
11580
|
var shq = (s) => `'${s.replace(/'/g, `'\\''`)}'`;
|
|
11568
11581
|
|
|
11569
11582
|
// src/runners/exec.ts
|
|
@@ -11609,15 +11622,15 @@ var agentShellCommand = (o) => {
|
|
|
11609
11622
|
const prompt = `"$(cat ${shq2(o.promptFile)})"`;
|
|
11610
11623
|
const agent = o.agent?.trim();
|
|
11611
11624
|
if (agent)
|
|
11612
|
-
return `${sandboxedAgent(agent, o.sandbox, o.
|
|
11625
|
+
return `${sandboxedAgent(agent, o.sandbox, o.readDirs)} ${prompt}`;
|
|
11613
11626
|
const model = o.model ? ` --model ${shq2(o.model)}` : "";
|
|
11614
11627
|
const effort = o.effort ? ` --effort ${shq2(o.effort)}` : "";
|
|
11615
|
-
return `${sandboxedAgent("claude", o.sandbox, o.
|
|
11628
|
+
return `${sandboxedAgent("claude", o.sandbox, o.readDirs)}${hookSettingsFlag(o)}${mcpConfigFlag(o)} --permission-mode ${shq2(o.permissionMode)}${model}${effort} ${prompt}`;
|
|
11616
11629
|
};
|
|
11617
11630
|
var execLine = (cmd) => /^[A-Za-z_][A-Za-z0-9_]*=/.test(cmd) ? `exec env ${cmd}` : `exec ${cmd}`;
|
|
11618
|
-
var sandboxedAgent = (agent, sandbox,
|
|
11631
|
+
var sandboxedAgent = (agent, sandbox, readDirs) => {
|
|
11619
11632
|
const kind = sandboxAgentKind(agent);
|
|
11620
|
-
const line = kind === "claude" ? `${agent}${claudeAddDirFlag(
|
|
11633
|
+
const line = kind === "claude" ? `${agent}${claudeAddDirFlag(readDirs)}` : agent;
|
|
11621
11634
|
if (!sandbox)
|
|
11622
11635
|
return line;
|
|
11623
11636
|
if (kind === "claude")
|
|
@@ -12340,7 +12353,7 @@ function beatBody(state, flags, host = {}, cap = {}) {
|
|
|
12340
12353
|
name: flags.name,
|
|
12341
12354
|
os: host.os ?? process.platform,
|
|
12342
12355
|
runner: flags.runner,
|
|
12343
|
-
version: host.version ?? "0.1.
|
|
12356
|
+
version: host.version ?? "0.1.69" ?? "dev",
|
|
12344
12357
|
running: live.length,
|
|
12345
12358
|
items: live.slice(0, BEAT_ITEMS).map((r) => `${r.item}/${r.node}`),
|
|
12346
12359
|
...cap.atOnce !== undefined ? { atOnce: cap.atOnce } : {},
|
|
@@ -14955,21 +14968,29 @@ function fingerprint(text) {
|
|
|
14955
14968
|
function wordsPrint(screen) {
|
|
14956
14969
|
return fingerprint(stripTuiChrome(screen));
|
|
14957
14970
|
}
|
|
14958
|
-
function sandboxFor(d, name, cwd, allow) {
|
|
14971
|
+
function sandboxFor(d, name, cwd, allow, readOnly) {
|
|
14959
14972
|
if (!d.sandbox)
|
|
14960
14973
|
return {};
|
|
14961
14974
|
if (!d.writeSandboxSettings)
|
|
14962
14975
|
throw new Error("sessions are sandboxed, but nothing writes their settings — not started");
|
|
14963
|
-
return { sandbox: d.writeSandboxSettings(name, cwd, allow) };
|
|
14976
|
+
return { sandbox: d.writeSandboxSettings(name, cwd, allow, readOnly) };
|
|
14964
14977
|
}
|
|
14965
|
-
function hooksFor(d, name, allow) {
|
|
14978
|
+
function hooksFor(d, name, allow, readOnly) {
|
|
14966
14979
|
if (d.sandbox || !d.writeHookSettings)
|
|
14967
14980
|
return {};
|
|
14968
|
-
return { settingsFile: d.writeHookSettings(name, allow) };
|
|
14981
|
+
return { settingsFile: d.writeHookSettings(name, allow, readOnly) };
|
|
14969
14982
|
}
|
|
14970
|
-
function
|
|
14971
|
-
|
|
14972
|
-
|
|
14983
|
+
function wallsFor(d, name, cwd, allow) {
|
|
14984
|
+
let readDirs = [];
|
|
14985
|
+
try {
|
|
14986
|
+
readDirs = d.readDirsOf?.(cwd) ?? [];
|
|
14987
|
+
} catch {}
|
|
14988
|
+
const readOnly = readOnlyDirs(readDirs, cwd);
|
|
14989
|
+
return {
|
|
14990
|
+
...sandboxFor(d, name, cwd, allow, readOnly),
|
|
14991
|
+
...hooksFor(d, name, allow, readOnly),
|
|
14992
|
+
...readDirs.length ? { readDirs } : {}
|
|
14993
|
+
};
|
|
14973
14994
|
}
|
|
14974
14995
|
function engineMcpConfigFor(d, name, runToken, at, cwd) {
|
|
14975
14996
|
if (d.source.name !== "sleds" || d.agent?.trim() || !d.writeMcpConfig)
|
|
@@ -15519,9 +15540,7 @@ async function tickOnce(d) {
|
|
|
15519
15540
|
...launch.effort && !launch.agent ? { effort: launch.effort } : {},
|
|
15520
15541
|
...launch.agent ? { agent: launch.agent } : {},
|
|
15521
15542
|
...mcpConfig ? { mcpConfig, ...d.strictMcp ? { strictMcp: true } : {} } : {},
|
|
15522
|
-
...
|
|
15523
|
-
...hooksFor(d, name, allow),
|
|
15524
|
-
...mainCheckoutFor(d, worktree),
|
|
15543
|
+
...wallsFor(d, name, worktree, allow),
|
|
15525
15544
|
...claim.group ? { group: claim.group } : {}
|
|
15526
15545
|
};
|
|
15527
15546
|
} catch (e) {
|
|
@@ -16398,9 +16417,7 @@ async function startAnswerer(d, answers, run) {
|
|
|
16398
16417
|
permissionMode: d.permissionMode,
|
|
16399
16418
|
...launchOptions(launch),
|
|
16400
16419
|
...mcpConfig ? { mcpConfig, ...d.strictMcp ? { strictMcp: true } : {} } : {},
|
|
16401
|
-
...
|
|
16402
|
-
...hooksFor(d, name),
|
|
16403
|
-
...mainCheckoutFor(d, run.handle.cwd),
|
|
16420
|
+
...wallsFor(d, name, run.handle.cwd),
|
|
16404
16421
|
...run.group ? { group: run.group } : {}
|
|
16405
16422
|
});
|
|
16406
16423
|
} catch (e) {
|
|
@@ -16608,9 +16625,7 @@ async function startDraft(d, claim, why, state, started, finished) {
|
|
|
16608
16625
|
permissionMode: d.permissionMode,
|
|
16609
16626
|
...launchOptions(launch),
|
|
16610
16627
|
...mcpConfig ? { mcpConfig, ...d.strictMcp ? { strictMcp: true } : {} } : {},
|
|
16611
|
-
...
|
|
16612
|
-
...hooksFor(d, name),
|
|
16613
|
-
...mainCheckoutFor(d, worktree)
|
|
16628
|
+
...wallsFor(d, name, worktree)
|
|
16614
16629
|
});
|
|
16615
16630
|
} catch (e) {
|
|
16616
16631
|
d.log(`${at}: could not start the drafter: ${message(e)}`);
|
|
@@ -16789,9 +16804,7 @@ async function startMock(d, claim, state, started, finished) {
|
|
|
16789
16804
|
promptFile: d.writePrompt(name, prompt),
|
|
16790
16805
|
permissionMode: d.permissionMode,
|
|
16791
16806
|
...launchOptions(launch),
|
|
16792
|
-
...
|
|
16793
|
-
...hooksFor(d, name, allow),
|
|
16794
|
-
...mainCheckoutFor(d, worktree)
|
|
16807
|
+
...wallsFor(d, name, worktree, allow)
|
|
16795
16808
|
});
|
|
16796
16809
|
} catch (e) {
|
|
16797
16810
|
await fail(`the engine could not start the session: ${message(e)}`);
|
|
@@ -17678,9 +17691,7 @@ function restartInWorktree(d, run, name, prompt, base) {
|
|
|
17678
17691
|
permissionMode: d.permissionMode,
|
|
17679
17692
|
...launchOptions(launch),
|
|
17680
17693
|
...run.mcpConfig ? { mcpConfig: run.mcpConfig, ...d.strictMcp ? { strictMcp: true } : {} } : {},
|
|
17681
|
-
...
|
|
17682
|
-
...hooksFor(d, name),
|
|
17683
|
-
...mainCheckoutFor(d, run.handle.cwd),
|
|
17694
|
+
...wallsFor(d, name, run.handle.cwd),
|
|
17684
17695
|
...run.group ? { group: run.group } : {}
|
|
17685
17696
|
};
|
|
17686
17697
|
run.handle = runner.makesWorktree ? runner.reopen(run.handle, o) : runner.start(o);
|
|
@@ -17814,9 +17825,7 @@ async function startEventAnswerer(d, answers, state, dec, decided) {
|
|
|
17814
17825
|
permissionMode: d.permissionMode,
|
|
17815
17826
|
...launchOptions(launch),
|
|
17816
17827
|
...mcpConfig ? { mcpConfig, ...d.strictMcp ? { strictMcp: true } : {} } : {},
|
|
17817
|
-
...
|
|
17818
|
-
...hooksFor(d, name),
|
|
17819
|
-
...mainCheckoutFor(d, worktree)
|
|
17828
|
+
...wallsFor(d, name, worktree)
|
|
17820
17829
|
});
|
|
17821
17830
|
} catch (e) {
|
|
17822
17831
|
d.log(`${at}: could not start the ${KIND_SAYS[kind]} answerer — it goes to a person: ${message(e)}`);
|
|
@@ -18344,8 +18353,8 @@ ${renderTranscript(messages)}`;
|
|
|
18344
18353
|
var headlessScript = (o, log) => {
|
|
18345
18354
|
const prompt = `"$(cat ${shq2(o.promptFile)})"`;
|
|
18346
18355
|
const agent = o.agent?.trim();
|
|
18347
|
-
const cmd = agent ? `${sandboxedAgent(agent, o.sandbox, o.
|
|
18348
|
-
`${sandboxedAgent("claude", o.sandbox, o.
|
|
18356
|
+
const cmd = agent ? `${sandboxedAgent(agent, o.sandbox, o.readDirs)} ${prompt}` : [
|
|
18357
|
+
`${sandboxedAgent("claude", o.sandbox, o.readDirs)} -p`,
|
|
18349
18358
|
prompt,
|
|
18350
18359
|
...o.mcpConfig ? [mcpConfigFlag(o).trim()] : [],
|
|
18351
18360
|
"--output-format stream-json --verbose",
|
|
@@ -19224,7 +19233,7 @@ async function fetchVersion(o) {
|
|
|
19224
19233
|
const platform = o.platform ?? process.platform;
|
|
19225
19234
|
const arch = o.arch ?? process.arch;
|
|
19226
19235
|
const publicKey = o.publicKey ?? RELEASE_PUBLIC_KEY;
|
|
19227
|
-
const running = o.running ?? "0.1.
|
|
19236
|
+
const running = o.running ?? "0.1.69";
|
|
19228
19237
|
if (!publicKey)
|
|
19229
19238
|
return { ok: false, why: "no release key yet" };
|
|
19230
19239
|
if (!VERSION_RE2.test(o.version))
|
|
@@ -20450,7 +20459,7 @@ function engineUpdater(o) {
|
|
|
20450
20459
|
|
|
20451
20460
|
// src/version.ts
|
|
20452
20461
|
function cliVersion(env) {
|
|
20453
|
-
return "0.1.
|
|
20462
|
+
return "0.1.69";
|
|
20454
20463
|
}
|
|
20455
20464
|
|
|
20456
20465
|
// src/commands/update.ts
|
|
@@ -20836,7 +20845,7 @@ function engineClient(o, org, breaker) {
|
|
|
20836
20845
|
...src,
|
|
20837
20846
|
...breaker ? { fetchFn: breaker.fetch } : {},
|
|
20838
20847
|
timeoutMs: ENGINE_TIMEOUT_MS,
|
|
20839
|
-
version: "0.1.
|
|
20848
|
+
version: "0.1.69"
|
|
20840
20849
|
});
|
|
20841
20850
|
const asked = org?.trim() || env.SLEDS_ORG?.trim();
|
|
20842
20851
|
if (asked && !selectOrg(readConfig(o.home), org, env).seat)
|
|
@@ -20912,6 +20921,7 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
20912
20921
|
const reposDirs = splitReposDirs(flags.reposDir).map((d) => resolve9(cwd, d));
|
|
20913
20922
|
const { branch, prTitle } = flags;
|
|
20914
20923
|
const hooksDir = join25(stateDir, "hooks");
|
|
20924
|
+
const pnpmStores = new Map;
|
|
20915
20925
|
const permissionMark = (name) => join25(hooksDir, `${name}.permission.json`);
|
|
20916
20926
|
const withHook = (name, settings) => applyPermissionHook(settings, [...o.sledsArgv ?? ["sleds"], "permission-event", "--mark", permissionMark(name)].map(shq2).join(" "));
|
|
20917
20927
|
return {
|
|
@@ -20935,7 +20945,7 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
20935
20945
|
...flags.strictMcp ? { strictMcp: true } : {},
|
|
20936
20946
|
...flags.sandbox ? {
|
|
20937
20947
|
sandbox: true,
|
|
20938
|
-
writeSandboxSettings: o.writeSandboxSettings ?? ((name, cwd, allow) => {
|
|
20948
|
+
writeSandboxSettings: o.writeSandboxSettings ?? ((name, cwd, allow, readOnly) => {
|
|
20939
20949
|
const gitCommonDir = gitCommonDirOf(exec, cwd);
|
|
20940
20950
|
const dir = join25(stateDir, "sandbox");
|
|
20941
20951
|
mkdirSync18(dir, { recursive: true, mode: 448 });
|
|
@@ -20947,6 +20957,12 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
20947
20957
|
walls.permissions.allow = [
|
|
20948
20958
|
...new Set([...walls.permissions.allow, ...allow ?? []])
|
|
20949
20959
|
];
|
|
20960
|
+
walls.permissions.deny = [
|
|
20961
|
+
...new Set([
|
|
20962
|
+
...walls.permissions.deny,
|
|
20963
|
+
...readOnlyDenyRules(readOnlyDirs(readOnly ?? [], cwd, [gitCommonDir]))
|
|
20964
|
+
])
|
|
20965
|
+
];
|
|
20950
20966
|
const settings = withHook(name, { ...walls });
|
|
20951
20967
|
writeFileSync16(p, `${JSON.stringify(settings, null, 2)}
|
|
20952
20968
|
`, { mode: 384 });
|
|
@@ -20954,23 +20970,22 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
20954
20970
|
return { settingsFile: p, gitCommonDir };
|
|
20955
20971
|
})
|
|
20956
20972
|
} : {},
|
|
20957
|
-
writeHookSettings: (name, allow) => {
|
|
20973
|
+
writeHookSettings: (name, allow, readOnly) => {
|
|
20958
20974
|
mkdirSync18(hooksDir, { recursive: true, mode: 448 });
|
|
20959
20975
|
const p = join25(hooksDir, `${name}.json`);
|
|
20960
|
-
const
|
|
20976
|
+
const deny = readOnlyDenyRules(readOnly ?? []);
|
|
20977
|
+
const permissions = {
|
|
20978
|
+
...allow?.length ? { allow: [...allow] } : {},
|
|
20979
|
+
...deny.length ? { deny } : {}
|
|
20980
|
+
};
|
|
20981
|
+
const base = Object.keys(permissions).length ? { permissions } : {};
|
|
20961
20982
|
writeFileSync16(p, `${JSON.stringify(withHook(name, base), null, 2)}
|
|
20962
20983
|
`, { mode: 384 });
|
|
20963
20984
|
chmodSync5(p, 384);
|
|
20964
20985
|
return p;
|
|
20965
20986
|
},
|
|
20966
20987
|
permissionMark,
|
|
20967
|
-
|
|
20968
|
-
try {
|
|
20969
|
-
return mainCheckoutOf(gitCommonDirOf(exec, cwd), cwd);
|
|
20970
|
-
} catch {
|
|
20971
|
-
return null;
|
|
20972
|
-
}
|
|
20973
|
-
}),
|
|
20988
|
+
readDirsOf: o.readDirsOf ?? ((dir) => engineReadDirs(exec, dir, exists, pnpmStores)),
|
|
20974
20989
|
...branch ? { branchOf: (claim) => branchFor(branch, claim) } : {},
|
|
20975
20990
|
...prTitle ? { prTitleOf: (claim) => prTitleFor(prTitle, claim) } : {},
|
|
20976
20991
|
now: o.now ?? Date.now,
|
|
@@ -21072,6 +21087,52 @@ function gitCommonDirOf(exec, cwd) {
|
|
|
21072
21087
|
throw new Error(`git has no common dir for ${cwd}, so the sandbox has nowhere to commit`);
|
|
21073
21088
|
return resolve9(cwd, dir);
|
|
21074
21089
|
}
|
|
21090
|
+
function worktreeListPaths(porcelain) {
|
|
21091
|
+
return porcelain.split(/\n\s*\n/).map((block) => block.split(`
|
|
21092
|
+
`).map((l) => l.trim())).filter((lines) => !lines.some((l) => l === "bare" || l.startsWith("prunable"))).flatMap((lines) => {
|
|
21093
|
+
const wt = lines.find((l) => l.startsWith("worktree "));
|
|
21094
|
+
return wt ? [wt.slice("worktree ".length)] : [];
|
|
21095
|
+
});
|
|
21096
|
+
}
|
|
21097
|
+
var PNPM_STORE_TIMEOUT_MS = 1e4;
|
|
21098
|
+
function engineReadDirs(exec, cwd, exists, stores) {
|
|
21099
|
+
let common = null;
|
|
21100
|
+
try {
|
|
21101
|
+
common = gitCommonDirOf(exec, cwd);
|
|
21102
|
+
} catch {}
|
|
21103
|
+
const worktrees = (() => {
|
|
21104
|
+
try {
|
|
21105
|
+
const r = exec("git", ["-C", cwd, "worktree", "list", "--porcelain"]);
|
|
21106
|
+
return r.status === 0 ? worktreeListPaths(r.stdout) : [];
|
|
21107
|
+
} catch {
|
|
21108
|
+
return [];
|
|
21109
|
+
}
|
|
21110
|
+
})();
|
|
21111
|
+
const pnpmStore = (() => {
|
|
21112
|
+
try {
|
|
21113
|
+
if (!exists(join25(cwd, "pnpm-lock.yaml")))
|
|
21114
|
+
return null;
|
|
21115
|
+
const key = common ?? cwd;
|
|
21116
|
+
const known = stores.get(key);
|
|
21117
|
+
if (known)
|
|
21118
|
+
return known;
|
|
21119
|
+
const r = exec("pnpm", ["store", "path"], { cwd, timeoutMs: PNPM_STORE_TIMEOUT_MS });
|
|
21120
|
+
const dir = r.status === 0 ? r.stdout.split(`
|
|
21121
|
+
`).map((l) => l.trim()).filter((l) => l.startsWith("/")).pop() : undefined;
|
|
21122
|
+
if (dir)
|
|
21123
|
+
stores.set(key, dir);
|
|
21124
|
+
return dir ?? null;
|
|
21125
|
+
} catch {
|
|
21126
|
+
return null;
|
|
21127
|
+
}
|
|
21128
|
+
})();
|
|
21129
|
+
return sessionReadDirs({
|
|
21130
|
+
mainCheckout: common ? mainCheckoutOf(common, cwd) : null,
|
|
21131
|
+
worktrees,
|
|
21132
|
+
pnpmStore,
|
|
21133
|
+
cwd
|
|
21134
|
+
});
|
|
21135
|
+
}
|
|
21075
21136
|
var LENT_NEEDS_SANDBOX = "a lent engine runs every session sandboxed (spec 48 rule 10) — add --sandbox to --lent-by";
|
|
21076
21137
|
function lenderHome(accountHome, lentBy) {
|
|
21077
21138
|
return isAbsolute3(lentBy) ? resolve9(lentBy) : join25(dirname16(accountHome), lentBy);
|
|
@@ -21142,7 +21203,7 @@ async function driveEngine(o, flags, deps, until = {}) {
|
|
|
21142
21203
|
runner: deps.runner.name,
|
|
21143
21204
|
atOnce: flags.atOnce,
|
|
21144
21205
|
interval: flags.interval,
|
|
21145
|
-
cliVersion: "0.1.
|
|
21206
|
+
cliVersion: "0.1.69"
|
|
21146
21207
|
};
|
|
21147
21208
|
const beat = (checkedAt) => {
|
|
21148
21209
|
const m = deps.machine;
|
|
@@ -23020,7 +23081,7 @@ function engineClient2(o, org, breaker) {
|
|
|
23020
23081
|
...src,
|
|
23021
23082
|
...breaker ? { fetchFn: breaker.fetch } : {},
|
|
23022
23083
|
timeoutMs: ENGINE_TIMEOUT_MS2,
|
|
23023
|
-
version: "0.1.
|
|
23084
|
+
version: "0.1.69"
|
|
23024
23085
|
});
|
|
23025
23086
|
const asked = org?.trim() || env.SLEDS_ORG?.trim();
|
|
23026
23087
|
if (asked && !selectOrg(readConfig(o.home), org, env).seat)
|
|
@@ -23118,6 +23179,7 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
23118
23179
|
const reposDirs = splitReposDirs(flags.reposDir).map((d) => resolve11(cwd, d));
|
|
23119
23180
|
const { branch, prTitle } = flags;
|
|
23120
23181
|
const hooksDir = join28(stateDir, "hooks");
|
|
23182
|
+
const pnpmStores = new Map;
|
|
23121
23183
|
const permissionMark = (name) => join28(hooksDir, `${name}.permission.json`);
|
|
23122
23184
|
const withHook = (name, settings) => applyPermissionHook(settings, [...o.sledsArgv ?? ["sleds"], "permission-event", "--mark", permissionMark(name)].map(shq2).join(" "));
|
|
23123
23185
|
return {
|
|
@@ -23141,7 +23203,7 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
23141
23203
|
...flags.strictMcp ? { strictMcp: true } : {},
|
|
23142
23204
|
...flags.sandbox ? {
|
|
23143
23205
|
sandbox: true,
|
|
23144
|
-
writeSandboxSettings: o.writeSandboxSettings ?? ((name, cwd, allow) => {
|
|
23206
|
+
writeSandboxSettings: o.writeSandboxSettings ?? ((name, cwd, allow, readOnly) => {
|
|
23145
23207
|
const gitCommonDir = gitCommonDirOf2(exec, cwd);
|
|
23146
23208
|
const dir = join28(stateDir, "sandbox");
|
|
23147
23209
|
mkdirSync21(dir, { recursive: true, mode: 448 });
|
|
@@ -23153,6 +23215,12 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
23153
23215
|
walls.permissions.allow = [
|
|
23154
23216
|
...new Set([...walls.permissions.allow, ...allow ?? []])
|
|
23155
23217
|
];
|
|
23218
|
+
walls.permissions.deny = [
|
|
23219
|
+
...new Set([
|
|
23220
|
+
...walls.permissions.deny,
|
|
23221
|
+
...readOnlyDenyRules(readOnlyDirs(readOnly ?? [], cwd, [gitCommonDir]))
|
|
23222
|
+
])
|
|
23223
|
+
];
|
|
23156
23224
|
const settings = withHook(name, { ...walls });
|
|
23157
23225
|
writeFileSync20(p, `${JSON.stringify(settings, null, 2)}
|
|
23158
23226
|
`, { mode: 384 });
|
|
@@ -23160,23 +23228,22 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
23160
23228
|
return { settingsFile: p, gitCommonDir };
|
|
23161
23229
|
})
|
|
23162
23230
|
} : {},
|
|
23163
|
-
writeHookSettings: (name, allow) => {
|
|
23231
|
+
writeHookSettings: (name, allow, readOnly) => {
|
|
23164
23232
|
mkdirSync21(hooksDir, { recursive: true, mode: 448 });
|
|
23165
23233
|
const p = join28(hooksDir, `${name}.json`);
|
|
23166
|
-
const
|
|
23234
|
+
const deny = readOnlyDenyRules(readOnly ?? []);
|
|
23235
|
+
const permissions = {
|
|
23236
|
+
...allow?.length ? { allow: [...allow] } : {},
|
|
23237
|
+
...deny.length ? { deny } : {}
|
|
23238
|
+
};
|
|
23239
|
+
const base = Object.keys(permissions).length ? { permissions } : {};
|
|
23167
23240
|
writeFileSync20(p, `${JSON.stringify(withHook(name, base), null, 2)}
|
|
23168
23241
|
`, { mode: 384 });
|
|
23169
23242
|
chmodSync6(p, 384);
|
|
23170
23243
|
return p;
|
|
23171
23244
|
},
|
|
23172
23245
|
permissionMark,
|
|
23173
|
-
|
|
23174
|
-
try {
|
|
23175
|
-
return mainCheckoutOf(gitCommonDirOf2(exec, cwd), cwd);
|
|
23176
|
-
} catch {
|
|
23177
|
-
return null;
|
|
23178
|
-
}
|
|
23179
|
-
}),
|
|
23246
|
+
readDirsOf: o.readDirsOf ?? ((dir) => engineReadDirs2(exec, dir, exists, pnpmStores)),
|
|
23180
23247
|
...branch ? { branchOf: (claim) => branchFor(branch, claim) } : {},
|
|
23181
23248
|
...prTitle ? { prTitleOf: (claim) => prTitleFor(prTitle, claim) } : {},
|
|
23182
23249
|
now: o.now ?? Date.now,
|
|
@@ -23278,6 +23345,52 @@ function gitCommonDirOf2(exec, cwd) {
|
|
|
23278
23345
|
throw new Error(`git has no common dir for ${cwd}, so the sandbox has nowhere to commit`);
|
|
23279
23346
|
return resolve11(cwd, dir);
|
|
23280
23347
|
}
|
|
23348
|
+
function worktreeListPaths2(porcelain) {
|
|
23349
|
+
return porcelain.split(/\n\s*\n/).map((block) => block.split(`
|
|
23350
|
+
`).map((l) => l.trim())).filter((lines) => !lines.some((l) => l === "bare" || l.startsWith("prunable"))).flatMap((lines) => {
|
|
23351
|
+
const wt = lines.find((l) => l.startsWith("worktree "));
|
|
23352
|
+
return wt ? [wt.slice("worktree ".length)] : [];
|
|
23353
|
+
});
|
|
23354
|
+
}
|
|
23355
|
+
var PNPM_STORE_TIMEOUT_MS2 = 1e4;
|
|
23356
|
+
function engineReadDirs2(exec, cwd, exists, stores) {
|
|
23357
|
+
let common = null;
|
|
23358
|
+
try {
|
|
23359
|
+
common = gitCommonDirOf2(exec, cwd);
|
|
23360
|
+
} catch {}
|
|
23361
|
+
const worktrees = (() => {
|
|
23362
|
+
try {
|
|
23363
|
+
const r = exec("git", ["-C", cwd, "worktree", "list", "--porcelain"]);
|
|
23364
|
+
return r.status === 0 ? worktreeListPaths2(r.stdout) : [];
|
|
23365
|
+
} catch {
|
|
23366
|
+
return [];
|
|
23367
|
+
}
|
|
23368
|
+
})();
|
|
23369
|
+
const pnpmStore = (() => {
|
|
23370
|
+
try {
|
|
23371
|
+
if (!exists(join28(cwd, "pnpm-lock.yaml")))
|
|
23372
|
+
return null;
|
|
23373
|
+
const key = common ?? cwd;
|
|
23374
|
+
const known = stores.get(key);
|
|
23375
|
+
if (known)
|
|
23376
|
+
return known;
|
|
23377
|
+
const r = exec("pnpm", ["store", "path"], { cwd, timeoutMs: PNPM_STORE_TIMEOUT_MS2 });
|
|
23378
|
+
const dir = r.status === 0 ? r.stdout.split(`
|
|
23379
|
+
`).map((l) => l.trim()).filter((l) => l.startsWith("/")).pop() : undefined;
|
|
23380
|
+
if (dir)
|
|
23381
|
+
stores.set(key, dir);
|
|
23382
|
+
return dir ?? null;
|
|
23383
|
+
} catch {
|
|
23384
|
+
return null;
|
|
23385
|
+
}
|
|
23386
|
+
})();
|
|
23387
|
+
return sessionReadDirs({
|
|
23388
|
+
mainCheckout: common ? mainCheckoutOf(common, cwd) : null,
|
|
23389
|
+
worktrees,
|
|
23390
|
+
pnpmStore,
|
|
23391
|
+
cwd
|
|
23392
|
+
});
|
|
23393
|
+
}
|
|
23281
23394
|
function sandboxRefusal(flags) {
|
|
23282
23395
|
if (flags.lentBy && !flags.sandbox)
|
|
23283
23396
|
return LENT_NEEDS_SANDBOX2;
|
|
@@ -23361,7 +23474,7 @@ async function driveEngine2(o, flags, deps, until = {}) {
|
|
|
23361
23474
|
runner: deps.runner.name,
|
|
23362
23475
|
atOnce: flags.atOnce,
|
|
23363
23476
|
interval: flags.interval,
|
|
23364
|
-
cliVersion: "0.1.
|
|
23477
|
+
cliVersion: "0.1.69"
|
|
23365
23478
|
};
|
|
23366
23479
|
const beat = (checkedAt) => {
|
|
23367
23480
|
const m = deps.machine;
|
|
@@ -25472,7 +25585,7 @@ function contextFor(deps) {
|
|
|
25472
25585
|
...src,
|
|
25473
25586
|
fetchFn: deps.fetchFn,
|
|
25474
25587
|
timeoutMs: deps.timeoutMs,
|
|
25475
|
-
version: "0.1.
|
|
25588
|
+
version: "0.1.69"
|
|
25476
25589
|
}), deps.home, now) : null;
|
|
25477
25590
|
return {
|
|
25478
25591
|
channel: "code",
|
|
@@ -32040,7 +32153,7 @@ var realPidAlive4 = (pid) => {
|
|
|
32040
32153
|
};
|
|
32041
32154
|
function machineClient(home, env) {
|
|
32042
32155
|
const src = meterSource(home, undefined, { env });
|
|
32043
|
-
return src ? fetchClient({ ...src, version: "0.1.
|
|
32156
|
+
return src ? fetchClient({ ...src, version: "0.1.69" }) : null;
|
|
32044
32157
|
}
|
|
32045
32158
|
async function noteAnswer2(home, a, now) {
|
|
32046
32159
|
try {
|
|
@@ -32991,7 +33104,7 @@ var main = async (argv) => {
|
|
|
32991
33104
|
now: Date.now(),
|
|
32992
33105
|
stderr: (line) => console.error(line),
|
|
32993
33106
|
isTTY: !!process.stderr.isTTY,
|
|
32994
|
-
version: "0.1.
|
|
33107
|
+
version: "0.1.69"
|
|
32995
33108
|
});
|
|
32996
33109
|
switch (cmd) {
|
|
32997
33110
|
case "update":
|
|
@@ -33255,7 +33368,7 @@ ${renderHelpText(argv[1])}`);
|
|
|
33255
33368
|
case "version":
|
|
33256
33369
|
case "--version":
|
|
33257
33370
|
case "-v":
|
|
33258
|
-
console.log("sleds 0.1.
|
|
33371
|
+
console.log("sleds 0.1.69");
|
|
33259
33372
|
return 0;
|
|
33260
33373
|
default:
|
|
33261
33374
|
console.error(`unknown command: ${cmd}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sleds/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.69",
|
|
4
4
|
"description": "SLEDS CLI — the cost and limits of AI agent work, decided at the wall. Point Claude Code at a SLEDS proxy; estimate before you run; hold, switch model, or run overnight when you hit a limit.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|