@sleds/cli 0.1.48 → 0.1.50
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 +508 -206
- package/package.json +1 -1
package/dist/sleds.mjs
CHANGED
|
@@ -4246,7 +4246,7 @@ async function actualTool(ctx, args, to = { path: "/proxy/estimate/actual" }) {
|
|
|
4246
4246
|
const from = str5(r.elapsedFrom);
|
|
4247
4247
|
const unsized = r.unsized === true;
|
|
4248
4248
|
const bits = [
|
|
4249
|
-
recorded !== undefined ? `${recorded} min${from ? ` measured from the ${from}` : ""}${num3(r.saidMinutes) !== undefined && num3(r.saidMinutes) !== recorded ? ` (you said ${num3(r.saidMinutes)})` : ""}` : phases ? "phases recorded" : null,
|
|
4249
|
+
recorded !== undefined ? `${recorded} min${from === "runs" ? " of engine run time" : from ? ` measured from the ${from}` : ""}${num3(r.saidMinutes) !== undefined && num3(r.saidMinutes) !== recorded ? ` (you said ${num3(r.saidMinutes)})` : ""}` : phases ? "phases recorded" : null,
|
|
4250
4250
|
num3(args.usd) !== undefined ? usd2(num3(args.usd)) : args.usd === null ? "$ cleared" : null,
|
|
4251
4251
|
num3(args.tokensIn) !== undefined || num3(args.tokensOut) !== undefined ? `${(num3(args.tokensIn) ?? 0) + (num3(args.tokensOut) ?? 0)} tokens` : null,
|
|
4252
4252
|
str5(args.model),
|
|
@@ -5479,6 +5479,9 @@ var init_agent = __esm(() => {
|
|
|
5479
5479
|
init_mention();
|
|
5480
5480
|
});
|
|
5481
5481
|
|
|
5482
|
+
// ../../packages/shared/src/slack/channel.ts
|
|
5483
|
+
var init_channel = () => {};
|
|
5484
|
+
|
|
5482
5485
|
// ../../packages/shared/src/item/productHits.ts
|
|
5483
5486
|
var PATH_STOP, COMMON;
|
|
5484
5487
|
var init_productHits = __esm(() => {
|
|
@@ -6531,6 +6534,30 @@ var init_deploys = __esm(() => {
|
|
|
6531
6534
|
SERVICE_RE = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,39}$/;
|
|
6532
6535
|
});
|
|
6533
6536
|
|
|
6537
|
+
// ../../packages/shared/src/deploys/metrics.ts
|
|
6538
|
+
var WEEK_MS;
|
|
6539
|
+
var init_metrics = __esm(() => {
|
|
6540
|
+
WEEK_MS = 7 * 24 * 60 * 60 * 1000;
|
|
6541
|
+
});
|
|
6542
|
+
|
|
6543
|
+
// ../../packages/shared/src/deploys/period.ts
|
|
6544
|
+
var DAY_MS2;
|
|
6545
|
+
var init_period = __esm(() => {
|
|
6546
|
+
DAY_MS2 = 24 * 60 * 60 * 1000;
|
|
6547
|
+
});
|
|
6548
|
+
|
|
6549
|
+
// ../../packages/shared/src/deploys/stability.ts
|
|
6550
|
+
var init_stability = __esm(() => {
|
|
6551
|
+
init_outcome();
|
|
6552
|
+
init_metrics();
|
|
6553
|
+
});
|
|
6554
|
+
|
|
6555
|
+
// ../../packages/shared/src/deploys/batchSize.ts
|
|
6556
|
+
var init_batchSize = __esm(() => {
|
|
6557
|
+
init_outcome();
|
|
6558
|
+
init_metrics();
|
|
6559
|
+
});
|
|
6560
|
+
|
|
6534
6561
|
// ../../packages/shared/src/newrelic/newrelic.ts
|
|
6535
6562
|
var init_newrelic = () => {};
|
|
6536
6563
|
|
|
@@ -7921,6 +7948,7 @@ var init_src = __esm(() => {
|
|
|
7921
7948
|
init_mention();
|
|
7922
7949
|
init_agent();
|
|
7923
7950
|
init_copy();
|
|
7951
|
+
init_channel();
|
|
7924
7952
|
init_productHits();
|
|
7925
7953
|
init_model();
|
|
7926
7954
|
init_parse();
|
|
@@ -7936,6 +7964,10 @@ var init_src = __esm(() => {
|
|
|
7936
7964
|
init_pack2();
|
|
7937
7965
|
init_flags();
|
|
7938
7966
|
init_deploys();
|
|
7967
|
+
init_metrics();
|
|
7968
|
+
init_period();
|
|
7969
|
+
init_stability();
|
|
7970
|
+
init_batchSize();
|
|
7939
7971
|
init_sentry();
|
|
7940
7972
|
init_newrelic();
|
|
7941
7973
|
init_musher();
|
|
@@ -8611,7 +8643,7 @@ var init_seat = __esm(() => {
|
|
|
8611
8643
|
|
|
8612
8644
|
// src/index.ts
|
|
8613
8645
|
import { existsSync as existsSync36, realpathSync as realpathSync3 } from "fs";
|
|
8614
|
-
import { homedir as
|
|
8646
|
+
import { homedir as homedir10, platform as platform3 } from "os";
|
|
8615
8647
|
import { fileURLToPath } from "url";
|
|
8616
8648
|
|
|
8617
8649
|
// ../../packages/shared/src/index.ts
|
|
@@ -8640,6 +8672,7 @@ init_outcome();
|
|
|
8640
8672
|
init_mention();
|
|
8641
8673
|
init_agent();
|
|
8642
8674
|
init_copy();
|
|
8675
|
+
init_channel();
|
|
8643
8676
|
init_productHits();
|
|
8644
8677
|
init_model();
|
|
8645
8678
|
init_parse();
|
|
@@ -8655,6 +8688,10 @@ init_cheatSheet();
|
|
|
8655
8688
|
init_pack2();
|
|
8656
8689
|
init_flags();
|
|
8657
8690
|
init_deploys();
|
|
8691
|
+
init_metrics();
|
|
8692
|
+
init_period();
|
|
8693
|
+
init_stability();
|
|
8694
|
+
init_batchSize();
|
|
8658
8695
|
init_sentry();
|
|
8659
8696
|
init_newrelic();
|
|
8660
8697
|
init_musher();
|
|
@@ -9824,6 +9861,7 @@ var defer = async (o) => {
|
|
|
9824
9861
|
init_src();
|
|
9825
9862
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
9826
9863
|
var DEPLOYS_URL = "https://hooks.sleds.ai/deploys";
|
|
9864
|
+
var DEPLOY_WAIT_MS = 120000;
|
|
9827
9865
|
var USAGE = "usage: sleds deploy --env <slug> [--service <name>] [--sha <sha>] [--repo <owner/name>]";
|
|
9828
9866
|
var FLAGS = ["env", "service", "sha", "repo"];
|
|
9829
9867
|
var set = (x) => x?.trim() ? x.trim() : undefined;
|
|
@@ -9880,7 +9918,7 @@ var defaultPost = async (url, token, body) => {
|
|
|
9880
9918
|
method: "POST",
|
|
9881
9919
|
headers: { authorization: `Bearer ${token}`, "content-type": "application/json" },
|
|
9882
9920
|
body: JSON.stringify(body),
|
|
9883
|
-
signal: AbortSignal.timeout(
|
|
9921
|
+
signal: AbortSignal.timeout(DEPLOY_WAIT_MS)
|
|
9884
9922
|
});
|
|
9885
9923
|
let json = null;
|
|
9886
9924
|
try {
|
|
@@ -9888,7 +9926,8 @@ var defaultPost = async (url, token, body) => {
|
|
|
9888
9926
|
} catch {}
|
|
9889
9927
|
return { status: res.status, json };
|
|
9890
9928
|
} catch (e) {
|
|
9891
|
-
|
|
9929
|
+
const timedOut = e instanceof Error && e.name === "TimeoutError";
|
|
9930
|
+
return { error: e instanceof Error ? e.message : String(e), ...timedOut ? { timedOut } : {} };
|
|
9892
9931
|
}
|
|
9893
9932
|
};
|
|
9894
9933
|
function deployLine(body, json) {
|
|
@@ -9921,6 +9960,10 @@ var deployCmd = async (o) => {
|
|
|
9921
9960
|
const body = resolved.body;
|
|
9922
9961
|
const url = set(env.SLEDS_DEPLOYS_URL) ?? DEPLOYS_URL;
|
|
9923
9962
|
const r = await (o.post ?? defaultPost)(url, token, body);
|
|
9963
|
+
if ("error" in r && r.timedOut) {
|
|
9964
|
+
error(`notice: the report was sent but SLEDS did not answer within ${DEPLOY_WAIT_MS / 1000}s; it is usually still recorded — see Settings › Deploys › Recent deploys`);
|
|
9965
|
+
return 0;
|
|
9966
|
+
}
|
|
9924
9967
|
if ("error" in r) {
|
|
9925
9968
|
error(`warning: SLEDS unreachable, deploy not recorded — ${r.error}`);
|
|
9926
9969
|
return 0;
|
|
@@ -9951,8 +9994,8 @@ import {
|
|
|
9951
9994
|
rmSync as rmSync13,
|
|
9952
9995
|
writeFileSync as writeFileSync19
|
|
9953
9996
|
} from "node:fs";
|
|
9954
|
-
import { tmpdir } from "node:os";
|
|
9955
|
-
import { delimiter as delimiter3, dirname as
|
|
9997
|
+
import { tmpdir, userInfo as userInfo2 } from "node:os";
|
|
9998
|
+
import { delimiter as delimiter3, dirname as dirname17, join as join26, resolve as resolve9 } from "node:path";
|
|
9956
9999
|
|
|
9957
10000
|
// src/agentMcp.ts
|
|
9958
10001
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
@@ -10328,8 +10371,36 @@ var runCockpit = async (cockpit, argv, opts = {}) => {
|
|
|
10328
10371
|
// src/commands/doctor.ts
|
|
10329
10372
|
init_config();
|
|
10330
10373
|
|
|
10374
|
+
// src/engine/credential.ts
|
|
10375
|
+
import { homedir } from "node:os";
|
|
10376
|
+
import { join as join11 } from "node:path";
|
|
10377
|
+
var API_KEY_VAR = "ANTHROPIC_API_KEY";
|
|
10378
|
+
var SEAT_TOKEN_VAR = "CLAUDE_CODE_OAUTH_TOKEN";
|
|
10379
|
+
function namesVar(text, name) {
|
|
10380
|
+
return new RegExp(`^\\s*(?:export\\s+)?${name}\\s*=\\s*\\S`, "m").test(text);
|
|
10381
|
+
}
|
|
10382
|
+
function loginPath(env, home = homedir()) {
|
|
10383
|
+
return join11(env.CLAUDE_CONFIG_DIR?.trim() || join11(home, ".claude"), ".credentials.json");
|
|
10384
|
+
}
|
|
10385
|
+
function detectCredential(env, o) {
|
|
10386
|
+
const file = o.boxEnvText ?? "";
|
|
10387
|
+
const fileWhere = o.boxEnvPath ?? "box.env";
|
|
10388
|
+
const vars = [
|
|
10389
|
+
[API_KEY_VAR, "key", "api_key"],
|
|
10390
|
+
[SEAT_TOKEN_VAR, "seat", "seat_token"]
|
|
10391
|
+
];
|
|
10392
|
+
for (const [name, kind, source] of vars) {
|
|
10393
|
+
if (env[name]?.trim())
|
|
10394
|
+
return { kind, source, where: "this shell" };
|
|
10395
|
+
if (namesVar(file, name))
|
|
10396
|
+
return { kind, source, where: fileWhere };
|
|
10397
|
+
}
|
|
10398
|
+
const login = loginPath(env, o.home);
|
|
10399
|
+
return o.exists(login) ? { kind: "seat", source: "login", where: login } : null;
|
|
10400
|
+
}
|
|
10401
|
+
|
|
10331
10402
|
// src/engine/repos.ts
|
|
10332
|
-
import { basename as basename2, dirname as dirname9, join as
|
|
10403
|
+
import { basename as basename2, dirname as dirname9, join as join12 } from "node:path";
|
|
10333
10404
|
function splitReposDirs(raw) {
|
|
10334
10405
|
return (raw ?? "").split(/[:\n]/).map((d) => d.trim()).filter(Boolean);
|
|
10335
10406
|
}
|
|
@@ -10356,13 +10427,13 @@ function resolveRepoPath(o) {
|
|
|
10356
10427
|
if (name.startsWith("."))
|
|
10357
10428
|
continue;
|
|
10358
10429
|
for (const dir of dirs) {
|
|
10359
|
-
const p =
|
|
10360
|
-
if (o.exists(
|
|
10430
|
+
const p = join12(dir, name);
|
|
10431
|
+
if (o.exists(join12(p, ".git")))
|
|
10361
10432
|
return p;
|
|
10362
10433
|
}
|
|
10363
10434
|
}
|
|
10364
10435
|
const want = o.repos.join(", ");
|
|
10365
|
-
const where = names.flatMap((n) => dirs.map((d) =>
|
|
10436
|
+
const where = names.flatMap((n) => dirs.map((d) => join12(d, n))).join(" or ");
|
|
10366
10437
|
return {
|
|
10367
10438
|
error: `No checkout of ${want} on this engine's machine: expected ${where}. Clone it there (or pass --repo).`
|
|
10368
10439
|
};
|
|
@@ -10370,7 +10441,7 @@ function resolveRepoPath(o) {
|
|
|
10370
10441
|
var isRoot = (p) => dirname9(p) === p;
|
|
10371
10442
|
function insideCheckout(dir, exists) {
|
|
10372
10443
|
for (let d = dir;!isRoot(d); d = dirname9(d)) {
|
|
10373
|
-
if (exists(
|
|
10444
|
+
if (exists(join12(d, ".git")))
|
|
10374
10445
|
return true;
|
|
10375
10446
|
}
|
|
10376
10447
|
return false;
|
|
@@ -10400,12 +10471,12 @@ init_meter();
|
|
|
10400
10471
|
|
|
10401
10472
|
// src/runners/cmux.ts
|
|
10402
10473
|
import { existsSync as existsSync11, rmSync as rmSync2, writeFileSync as writeFileSync10 } from "node:fs";
|
|
10403
|
-
import { delimiter, join as
|
|
10474
|
+
import { delimiter, join as join14 } from "node:path";
|
|
10404
10475
|
|
|
10405
10476
|
// src/runners/exec.ts
|
|
10406
10477
|
import { spawn, spawnSync as spawnSync3 } from "node:child_process";
|
|
10407
10478
|
import { closeSync as closeSync2, fstatSync, openSync as openSync2, readSync as readSync2 } from "node:fs";
|
|
10408
|
-
import { basename as basename3, dirname as dirname10, join as
|
|
10479
|
+
import { basename as basename3, dirname as dirname10, join as join13 } from "node:path";
|
|
10409
10480
|
|
|
10410
10481
|
// src/runners/sandbox.ts
|
|
10411
10482
|
var absRule = (dir) => `/${dir.replace(/\/+$/, "")}/**`;
|
|
@@ -10549,7 +10620,7 @@ var readLogTail = (path) => {
|
|
|
10549
10620
|
};
|
|
10550
10621
|
var logPathFor = (promptFile, ext, dir) => {
|
|
10551
10622
|
const base = basename3(promptFile).replace(/\.md$/i, "");
|
|
10552
|
-
return
|
|
10623
|
+
return join13(dir ?? dirname10(promptFile), `${base}.${ext}`);
|
|
10553
10624
|
};
|
|
10554
10625
|
var tailText = (s, bytes = 4096) => {
|
|
10555
10626
|
if (s.length <= bytes)
|
|
@@ -10573,7 +10644,7 @@ var isRunnerKey = (key) => /^(?:[1-9]|esc)$/.test(key);
|
|
|
10573
10644
|
var CMUX_APP_BIN = "/Applications/cmux.app/Contents/Resources/bin/cmux";
|
|
10574
10645
|
var resolveCmuxBin = (exists = existsSync11, path = process.env.PATH ?? "") => {
|
|
10575
10646
|
for (const dir of path.split(delimiter)) {
|
|
10576
|
-
if (dir && exists(
|
|
10647
|
+
if (dir && exists(join14(dir, "cmux")))
|
|
10577
10648
|
return "cmux";
|
|
10578
10649
|
}
|
|
10579
10650
|
return exists(CMUX_APP_BIN) ? CMUX_APP_BIN : "cmux";
|
|
@@ -10934,7 +11005,7 @@ function cmuxRunner(exec, deps = {}) {
|
|
|
10934
11005
|
|
|
10935
11006
|
// src/runners/orca.ts
|
|
10936
11007
|
import { existsSync as existsSync12, lstatSync, readlinkSync, writeFileSync as writeFileSync11 } from "node:fs";
|
|
10937
|
-
import { join as
|
|
11008
|
+
import { join as join15, resolve as resolve7 } from "node:path";
|
|
10938
11009
|
var obj = (v) => v !== null && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
10939
11010
|
var str8 = (v) => typeof v === "string" && v.length > 0 ? v : null;
|
|
10940
11011
|
var parseOrcaJson = (stdout) => {
|
|
@@ -10995,7 +11066,7 @@ var realFs = { lstat: lstatSync, readlink: readlinkSync, exists: existsSync12 };
|
|
|
10995
11066
|
var ORCA_LINK_FIX = "reinstall Orca's shell command from Orca (it links `orca` onto your PATH)";
|
|
10996
11067
|
function danglingOrca(path, fs) {
|
|
10997
11068
|
for (const dir of path.split(":").filter(Boolean)) {
|
|
10998
|
-
const link =
|
|
11069
|
+
const link = join15(dir, "orca");
|
|
10999
11070
|
try {
|
|
11000
11071
|
if (!fs.lstat(link).isSymbolicLink())
|
|
11001
11072
|
return null;
|
|
@@ -11142,10 +11213,10 @@ function orcaRunner(exec, deps = {}) {
|
|
|
11142
11213
|
}
|
|
11143
11214
|
|
|
11144
11215
|
// src/runtime.ts
|
|
11145
|
-
import { homedir } from "node:os";
|
|
11146
|
-
import { join as
|
|
11216
|
+
import { homedir as homedir2 } from "node:os";
|
|
11217
|
+
import { join as join16, win32 } from "node:path";
|
|
11147
11218
|
var isCompiled = (argv1 = process.argv[1]) => Boolean(argv1 && (argv1.startsWith("/$bunfs/") || argv1.startsWith("B:\\~BUN\\")));
|
|
11148
|
-
var sledsLink = (home =
|
|
11219
|
+
var sledsLink = (home = homedir2(), platform = process.platform) => platform === "win32" ? win32.join(process.env.LOCALAPPDATA ?? win32.join(home, "AppData", "Local"), "sleds", "bin", "sleds.exe") : join16(home, ".sleds", "bin", "sleds");
|
|
11149
11220
|
|
|
11150
11221
|
// src/commands/doctor.ts
|
|
11151
11222
|
init_settings();
|
|
@@ -11161,10 +11232,11 @@ import {
|
|
|
11161
11232
|
readFileSync as readFileSync15,
|
|
11162
11233
|
existsSync as realExists,
|
|
11163
11234
|
rmSync as rmSync10,
|
|
11235
|
+
statSync as statSync5,
|
|
11164
11236
|
writeFileSync as writeFileSync16
|
|
11165
11237
|
} from "node:fs";
|
|
11166
|
-
import { hostname as hostname2 } from "node:os";
|
|
11167
|
-
import { join as
|
|
11238
|
+
import { hostname as hostname2, userInfo } from "node:os";
|
|
11239
|
+
import { dirname as dirname15, isAbsolute as isAbsolute3, join as join24, resolve as resolve8 } from "node:path";
|
|
11168
11240
|
|
|
11169
11241
|
// src/engine/beat.ts
|
|
11170
11242
|
var BEAT_EVERY_MS = 60000;
|
|
@@ -11176,10 +11248,11 @@ function beatBody(state, flags, host = {}, cap = {}) {
|
|
|
11176
11248
|
name: flags.name,
|
|
11177
11249
|
os: host.os ?? process.platform,
|
|
11178
11250
|
runner: flags.runner,
|
|
11179
|
-
version: host.version ?? "0.1.
|
|
11251
|
+
version: host.version ?? "0.1.50" ?? "dev",
|
|
11180
11252
|
running: live.length,
|
|
11181
11253
|
items: live.slice(0, BEAT_ITEMS).map((r) => `${r.item}/${r.node}`),
|
|
11182
11254
|
...cap.atOnce !== undefined ? { atOnce: cap.atOnce } : {},
|
|
11255
|
+
...host.credential ? { credential: host.credential } : {},
|
|
11183
11256
|
...m ? {
|
|
11184
11257
|
machine: {
|
|
11185
11258
|
cpuPct: m.cpuPct,
|
|
@@ -13066,9 +13139,9 @@ function providerFailure(screen) {
|
|
|
13066
13139
|
// src/engine/worktree.ts
|
|
13067
13140
|
init_src();
|
|
13068
13141
|
import { appendFileSync, existsSync as existsSync13, mkdirSync as mkdirSync11 } from "node:fs";
|
|
13069
|
-
import { dirname as dirname11, isAbsolute, join as
|
|
13142
|
+
import { dirname as dirname11, isAbsolute, join as join17 } from "node:path";
|
|
13070
13143
|
function worktreePath(repoPath, name) {
|
|
13071
|
-
return
|
|
13144
|
+
return join17(repoPath, ".worktrees", name);
|
|
13072
13145
|
}
|
|
13073
13146
|
var fail = (what, r) => new Error(`${what} failed: ${(r.stderr || r.stdout).trim() || `exit ${r.status}`}`);
|
|
13074
13147
|
function defaultBranch(exec, repoPath) {
|
|
@@ -13103,7 +13176,7 @@ function ensureIgnored(exec, repoPath, fs = realWorktreeFs) {
|
|
|
13103
13176
|
if (common.status !== 0)
|
|
13104
13177
|
return;
|
|
13105
13178
|
const dir = common.stdout.trim();
|
|
13106
|
-
const exclude =
|
|
13179
|
+
const exclude = join17(isAbsolute(dir) ? dir : join17(repoPath, dir), "info", "exclude");
|
|
13107
13180
|
fs.append(exclude, `
|
|
13108
13181
|
# sleds engine: one worktree per route node
|
|
13109
13182
|
.worktrees/
|
|
@@ -13115,7 +13188,7 @@ function ensureWorktree(exec, repoPath, branch, path, base = "main", fs = realWo
|
|
|
13115
13188
|
return path;
|
|
13116
13189
|
}
|
|
13117
13190
|
function makeWorktree(exec, repoPath, branch, path, base, fs, log) {
|
|
13118
|
-
if (fs.exists(
|
|
13191
|
+
if (fs.exists(join17(path, ".git"))) {
|
|
13119
13192
|
fastForwardUntouched(exec, path, base, log);
|
|
13120
13193
|
return path;
|
|
13121
13194
|
}
|
|
@@ -13191,13 +13264,13 @@ function installArgv(command) {
|
|
|
13191
13264
|
return rest.every((a) => a.startsWith("-")) ? argv : null;
|
|
13192
13265
|
}
|
|
13193
13266
|
function lockfileInstall(path, exists) {
|
|
13194
|
-
if (exists(
|
|
13267
|
+
if (exists(join17(path, "pnpm-lock.yaml")))
|
|
13195
13268
|
return ["pnpm", "install", "--frozen-lockfile"];
|
|
13196
|
-
if (exists(
|
|
13269
|
+
if (exists(join17(path, "bun.lock")) || exists(join17(path, "bun.lockb")))
|
|
13197
13270
|
return ["bun", "install", "--frozen-lockfile"];
|
|
13198
|
-
if (exists(
|
|
13271
|
+
if (exists(join17(path, "yarn.lock")))
|
|
13199
13272
|
return ["yarn", "install", "--frozen-lockfile"];
|
|
13200
|
-
if (exists(
|
|
13273
|
+
if (exists(join17(path, "package-lock.json")))
|
|
13201
13274
|
return ["npm", "ci"];
|
|
13202
13275
|
return null;
|
|
13203
13276
|
}
|
|
@@ -13255,7 +13328,7 @@ function claimRunOf(run, repo) {
|
|
|
13255
13328
|
};
|
|
13256
13329
|
}
|
|
13257
13330
|
function ensureInstalled(exec, path, fs, o = {}) {
|
|
13258
|
-
if (!fs.exists(
|
|
13331
|
+
if (!fs.exists(join17(path, "package.json")) || fs.exists(join17(path, "node_modules")))
|
|
13259
13332
|
return null;
|
|
13260
13333
|
const argv = installArgv(o.command) ?? lockfileInstall(path, fs.exists);
|
|
13261
13334
|
if (!argv)
|
|
@@ -13270,7 +13343,7 @@ function ensureInstalled(exec, path, fs, o = {}) {
|
|
|
13270
13343
|
return { argv, ok };
|
|
13271
13344
|
}
|
|
13272
13345
|
function ensureDetachedWorktree(exec, repoPath, path, base = "main", fs = realWorktreeFs) {
|
|
13273
|
-
if (fs.exists(
|
|
13346
|
+
if (fs.exists(join17(path, ".git")))
|
|
13274
13347
|
return path;
|
|
13275
13348
|
ensureIgnored(exec, repoPath, fs);
|
|
13276
13349
|
const f = exec("git", ["-C", repoPath, "fetch", "origin", base]);
|
|
@@ -16559,8 +16632,8 @@ init_settings();
|
|
|
16559
16632
|
|
|
16560
16633
|
// src/update/drain.ts
|
|
16561
16634
|
import { closeSync as closeSync4, existsSync as existsSync18, mkdirSync as mkdirSync17, openSync as openSync4, rmSync as rmSync9, statSync as statSync4, writeSync as writeSync2 } from "node:fs";
|
|
16562
|
-
import { homedir as
|
|
16563
|
-
import { join as
|
|
16635
|
+
import { homedir as homedir7 } from "node:os";
|
|
16636
|
+
import { join as join23 } from "node:path";
|
|
16564
16637
|
|
|
16565
16638
|
// ../../packages/shared/src/updates/manifest.ts
|
|
16566
16639
|
var CLI_PLATFORMS = [
|
|
@@ -16702,13 +16775,13 @@ import {
|
|
|
16702
16775
|
statSync as statSync2,
|
|
16703
16776
|
writeFileSync as writeFileSync13
|
|
16704
16777
|
} from "node:fs";
|
|
16705
|
-
import { homedir as
|
|
16706
|
-
import { dirname as dirname12, join as
|
|
16778
|
+
import { homedir as homedir3 } from "node:os";
|
|
16779
|
+
import { dirname as dirname12, join as join18, win32 as win322 } from "node:path";
|
|
16707
16780
|
var UPDATE_LOCK_STALE_MS = 10 * 60000;
|
|
16708
|
-
function sledsRoot(home =
|
|
16709
|
-
return platform === "win32" ? win322.join(process.env.LOCALAPPDATA ?? win322.join(home, "AppData", "Local"), "sleds") :
|
|
16781
|
+
function sledsRoot(home = homedir3(), platform = process.platform) {
|
|
16782
|
+
return platform === "win32" ? win322.join(process.env.LOCALAPPDATA ?? win322.join(home, "AppData", "Local"), "sleds") : join18(home, ".sleds");
|
|
16710
16783
|
}
|
|
16711
|
-
var pathFor = (platform) => platform === "win32" ? win322 : { join:
|
|
16784
|
+
var pathFor = (platform) => platform === "win32" ? win322 : { join: join18 };
|
|
16712
16785
|
function versionDir(home, v, platform = process.platform) {
|
|
16713
16786
|
return pathFor(platform).join(sledsRoot(home, platform), "versions", v);
|
|
16714
16787
|
}
|
|
@@ -16900,7 +16973,7 @@ async function fetchVersion(o) {
|
|
|
16900
16973
|
const platform = o.platform ?? process.platform;
|
|
16901
16974
|
const arch = o.arch ?? process.arch;
|
|
16902
16975
|
const publicKey = o.publicKey ?? RELEASE_PUBLIC_KEY;
|
|
16903
|
-
const running = o.running ?? "0.1.
|
|
16976
|
+
const running = o.running ?? "0.1.50";
|
|
16904
16977
|
if (!publicKey)
|
|
16905
16978
|
return { ok: false, why: "no release key yet" };
|
|
16906
16979
|
if (!VERSION_RE2.test(o.version))
|
|
@@ -16977,7 +17050,7 @@ async function fetchVersion(o) {
|
|
|
16977
17050
|
|
|
16978
17051
|
// src/update/guard.ts
|
|
16979
17052
|
import { existsSync as existsSync17 } from "node:fs";
|
|
16980
|
-
import { homedir as
|
|
17053
|
+
import { homedir as homedir6 } from "node:os";
|
|
16981
17054
|
|
|
16982
17055
|
// src/update/migrate.ts
|
|
16983
17056
|
import { spawn as spawn2 } from "node:child_process";
|
|
@@ -16993,20 +17066,20 @@ import {
|
|
|
16993
17066
|
symlinkSync,
|
|
16994
17067
|
writeFileSync as writeFileSync15
|
|
16995
17068
|
} from "node:fs";
|
|
16996
|
-
import { homedir as
|
|
16997
|
-
import { basename as basename5, delimiter as delimiter2, dirname as dirname13, isAbsolute as isAbsolute2, join as
|
|
17069
|
+
import { homedir as homedir4 } from "node:os";
|
|
17070
|
+
import { basename as basename5, delimiter as delimiter2, dirname as dirname13, isAbsolute as isAbsolute2, join as join21, relative } from "node:path";
|
|
16998
17071
|
|
|
16999
17072
|
// src/commands/engineSystemd.ts
|
|
17000
|
-
import { join as
|
|
17073
|
+
import { join as join19 } from "node:path";
|
|
17001
17074
|
var BOX_ENV_UNIT_PATH = "%h/.config/sleds/box.env";
|
|
17002
17075
|
function boxEnvPath(home) {
|
|
17003
|
-
return
|
|
17076
|
+
return join19(home, ".config", "sleds", "box.env");
|
|
17004
17077
|
}
|
|
17005
17078
|
function engineUnitDir(home) {
|
|
17006
|
-
return
|
|
17079
|
+
return join19(home, ".config", "systemd", "user");
|
|
17007
17080
|
}
|
|
17008
17081
|
function engineUnitPath(home, label) {
|
|
17009
|
-
return
|
|
17082
|
+
return join19(engineUnitDir(home), `${label}.service`);
|
|
17010
17083
|
}
|
|
17011
17084
|
function systemdQuote(s) {
|
|
17012
17085
|
const body = s.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n").replace(/%/g, "%%").replace(/\$/g, "$$$$");
|
|
@@ -17048,7 +17121,7 @@ function parseEngineUnit(text) {
|
|
|
17048
17121
|
// src/schedule.ts
|
|
17049
17122
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
17050
17123
|
import { existsSync as existsSync15, mkdirSync as mkdirSync14, rmSync as rmSync6, writeFileSync as writeFileSync14 } from "node:fs";
|
|
17051
|
-
import { join as
|
|
17124
|
+
import { join as join20 } from "node:path";
|
|
17052
17125
|
var REVERT_LABEL = "ai.sleds.revert";
|
|
17053
17126
|
var defaultExec2 = (cmd, args) => {
|
|
17054
17127
|
const r = spawnSync4(cmd, [...args], { stdio: ["ignore", "ignore", "pipe"], encoding: "utf8" });
|
|
@@ -17056,7 +17129,7 @@ var defaultExec2 = (cmd, args) => {
|
|
|
17056
17129
|
return { ok: false, stderr: r.error.message };
|
|
17057
17130
|
return { ok: r.status === 0, stderr: r.stderr ?? "" };
|
|
17058
17131
|
};
|
|
17059
|
-
var plistPath = (home) =>
|
|
17132
|
+
var plistPath = (home) => join20(home, "Library", "LaunchAgents", `${REVERT_LABEL}.plist`);
|
|
17060
17133
|
var xmlEscape2 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
17061
17134
|
var buildLaunchdPlist = (sledsArgv, deadline) => {
|
|
17062
17135
|
const args = [...sledsArgv, "off"].map((a) => ` <string>${xmlEscape2(a)}</string>`).join(`
|
|
@@ -17095,7 +17168,7 @@ var scheduleRevert = (d, deadlineMs) => {
|
|
|
17095
17168
|
if (d.platform === "darwin") {
|
|
17096
17169
|
const p = plistPath(d.home);
|
|
17097
17170
|
try {
|
|
17098
|
-
mkdirSync14(
|
|
17171
|
+
mkdirSync14(join20(d.home, "Library", "LaunchAgents"), { recursive: true });
|
|
17099
17172
|
d.exec("launchctl", ["unload", p]);
|
|
17100
17173
|
writeFileSync14(p, buildLaunchdPlist(d.sledsArgv, deadline));
|
|
17101
17174
|
const r = d.exec("launchctl", ["load", p]);
|
|
@@ -17147,8 +17220,8 @@ var HOOK_SUBS = [
|
|
|
17147
17220
|
"stop-event",
|
|
17148
17221
|
"permission-event"
|
|
17149
17222
|
];
|
|
17150
|
-
var migrateBakDir = (home) =>
|
|
17151
|
-
var manifestPath = (home) =>
|
|
17223
|
+
var migrateBakDir = (home) => join21(sledsRoot(home), "migrate.bak");
|
|
17224
|
+
var manifestPath = (home) => join21(migrateBakDir(home), "manifest.json");
|
|
17152
17225
|
var xmlEscape3 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
17153
17226
|
var xmlUnescape = (s) => s.replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&");
|
|
17154
17227
|
var shQuote = (s) => /^[\w./~-]+$/.test(s) ? s : `'${s.replace(/'/g, "'\\''")}'`;
|
|
@@ -17248,13 +17321,13 @@ function rewriteSettings(text, link) {
|
|
|
17248
17321
|
}
|
|
17249
17322
|
var listDir = (dir, keep) => {
|
|
17250
17323
|
try {
|
|
17251
|
-
return readdirSync2(dir).filter(keep).sort().map((n) =>
|
|
17324
|
+
return readdirSync2(dir).filter(keep).sort().map((n) => join21(dir, n));
|
|
17252
17325
|
} catch {
|
|
17253
17326
|
return [];
|
|
17254
17327
|
}
|
|
17255
17328
|
};
|
|
17256
17329
|
function unitFiles(home) {
|
|
17257
|
-
const agents = listDir(
|
|
17330
|
+
const agents = listDir(join21(home, "Library", "LaunchAgents"), (n) => n.startsWith("ai.sleds.") && n.endsWith(".plist")).map((path) => ({
|
|
17258
17331
|
path,
|
|
17259
17332
|
...basename5(path).startsWith("ai.sleds.revert") ? {} : { reload: "launchd" }
|
|
17260
17333
|
}));
|
|
@@ -17266,7 +17339,7 @@ function unitClaudeDir(text) {
|
|
|
17266
17339
|
return plist ? xmlUnescape(plist) : undefined;
|
|
17267
17340
|
}
|
|
17268
17341
|
function claudeDirs(home, env) {
|
|
17269
|
-
const dirs = [
|
|
17342
|
+
const dirs = [join21(home, ".claude"), claudeDir(home, env)];
|
|
17270
17343
|
for (const u of unitFiles(home)) {
|
|
17271
17344
|
try {
|
|
17272
17345
|
const d = unitClaudeDir(readFileSync14(u.path, "utf8"));
|
|
@@ -17290,7 +17363,7 @@ function migrationPlan(home, link, env = process.env) {
|
|
|
17290
17363
|
out.push({ ...u, text: next });
|
|
17291
17364
|
}
|
|
17292
17365
|
for (const dir of claudeDirs(home, env)) {
|
|
17293
|
-
const path =
|
|
17366
|
+
const path = join21(dir, "settings.json");
|
|
17294
17367
|
let text;
|
|
17295
17368
|
try {
|
|
17296
17369
|
text = readFileSync14(path, "utf8");
|
|
@@ -17305,7 +17378,7 @@ function migrationPlan(home, link, env = process.env) {
|
|
|
17305
17378
|
}
|
|
17306
17379
|
var backupFor = (home, path) => {
|
|
17307
17380
|
const rel = relative(home, path);
|
|
17308
|
-
return rel.startsWith("..") || isAbsolute2(rel) ?
|
|
17381
|
+
return rel.startsWith("..") || isAbsolute2(rel) ? join21(migrateBakDir(home), "abs", path) : join21(migrateBakDir(home), rel);
|
|
17309
17382
|
};
|
|
17310
17383
|
function writeKeepingMode(path, text) {
|
|
17311
17384
|
let mode = 420;
|
|
@@ -17390,7 +17463,7 @@ function putBack(home, m) {
|
|
|
17390
17463
|
return failed;
|
|
17391
17464
|
}
|
|
17392
17465
|
function restoreMigration(s, o) {
|
|
17393
|
-
const home = o.home ??
|
|
17466
|
+
const home = o.home ?? homedir4();
|
|
17394
17467
|
const m = readManifest(home);
|
|
17395
17468
|
const to = m?.to ?? s.pending?.to ?? "?";
|
|
17396
17469
|
const failed = m ? putBack(home, m) : [];
|
|
@@ -17402,7 +17475,7 @@ function restoreMigration(s, o) {
|
|
|
17402
17475
|
return failed.length ? `moved back to the npm install, but could not restore ${failed.join(", ")} — the copies are in ${migrateBakDir(home)}` : "moved back to the npm install";
|
|
17403
17476
|
}
|
|
17404
17477
|
async function migrateToBinary(o) {
|
|
17405
|
-
const home = o.home ??
|
|
17478
|
+
const home = o.home ?? homedir4();
|
|
17406
17479
|
const log = o.log ?? console.error;
|
|
17407
17480
|
const env = o.env ?? process.env;
|
|
17408
17481
|
const platform = o.platform ?? process.platform;
|
|
@@ -17496,11 +17569,11 @@ import {
|
|
|
17496
17569
|
rmSync as rmSync8,
|
|
17497
17570
|
symlinkSync as symlinkSync2
|
|
17498
17571
|
} from "node:fs";
|
|
17499
|
-
import { homedir as
|
|
17500
|
-
import { dirname as dirname14, join as
|
|
17572
|
+
import { homedir as homedir5 } from "node:os";
|
|
17573
|
+
import { dirname as dirname14, join as join22 } from "node:path";
|
|
17501
17574
|
var NO_PREVIOUS = "no previous version on this machine";
|
|
17502
|
-
function allStateFiles(home =
|
|
17503
|
-
const roots = [...new Set([configDir(home, env),
|
|
17575
|
+
function allStateFiles(home = homedir5(), env = process.env) {
|
|
17576
|
+
const roots = [...new Set([configDir(home, env), join22(home, ".config", "sleds")])];
|
|
17504
17577
|
const out = [];
|
|
17505
17578
|
const walk = (dir) => {
|
|
17506
17579
|
let names;
|
|
@@ -17511,20 +17584,20 @@ function allStateFiles(home = homedir4(), env = process.env) {
|
|
|
17511
17584
|
}
|
|
17512
17585
|
for (const n of names.sort())
|
|
17513
17586
|
if (n.endsWith(".json") && n !== "removed-engines.json")
|
|
17514
|
-
out.push(
|
|
17587
|
+
out.push(join22(dir, n));
|
|
17515
17588
|
for (const sub of ["orgs", "seats"]) {
|
|
17516
17589
|
let kids;
|
|
17517
17590
|
try {
|
|
17518
|
-
kids = readdirSync3(
|
|
17591
|
+
kids = readdirSync3(join22(dir, sub));
|
|
17519
17592
|
} catch {
|
|
17520
17593
|
continue;
|
|
17521
17594
|
}
|
|
17522
17595
|
for (const k of kids.sort())
|
|
17523
|
-
walk(
|
|
17596
|
+
walk(join22(dir, sub, k));
|
|
17524
17597
|
}
|
|
17525
17598
|
};
|
|
17526
17599
|
for (const r of roots)
|
|
17527
|
-
walk(
|
|
17600
|
+
walk(join22(r, "engine"));
|
|
17528
17601
|
return out;
|
|
17529
17602
|
}
|
|
17530
17603
|
var backupPath2 = (file, v) => `${file}.${v}.bak`;
|
|
@@ -17620,7 +17693,7 @@ function applyConfirm(s, home, o = {}) {
|
|
|
17620
17693
|
}
|
|
17621
17694
|
for (const n of names)
|
|
17622
17695
|
if (n.startsWith(prefix) && n.endsWith(".bak"))
|
|
17623
|
-
rmSync8(
|
|
17696
|
+
rmSync8(join22(dir, n), { force: true });
|
|
17624
17697
|
}
|
|
17625
17698
|
const keep = new Set([s.current, s.previous, s.drain?.to].filter(Boolean));
|
|
17626
17699
|
const versions = dirname14(versionDir(home, s.current, platform));
|
|
@@ -17710,7 +17783,7 @@ function movedAway(s, home, version, platform) {
|
|
|
17710
17783
|
return at && at !== version ? at : null;
|
|
17711
17784
|
}
|
|
17712
17785
|
async function startGuard(o) {
|
|
17713
|
-
const home = o.home ??
|
|
17786
|
+
const home = o.home ?? homedir6();
|
|
17714
17787
|
const platform = o.platform ?? process.platform;
|
|
17715
17788
|
const version = o.version;
|
|
17716
17789
|
if (!version || !guarded(home, version, platform))
|
|
@@ -17742,7 +17815,7 @@ async function startGuard(o) {
|
|
|
17742
17815
|
}
|
|
17743
17816
|
}
|
|
17744
17817
|
function firstBeatWatchdog(o) {
|
|
17745
|
-
const home = o.home ??
|
|
17818
|
+
const home = o.home ?? homedir6();
|
|
17746
17819
|
const platform = o.platform ?? process.platform;
|
|
17747
17820
|
const version = o.version;
|
|
17748
17821
|
const idle = { beat: async () => {}, stop: () => {} };
|
|
@@ -17883,7 +17956,7 @@ async function machineAnswer(client, tokens) {
|
|
|
17883
17956
|
}
|
|
17884
17957
|
async function fetchOnce(o) {
|
|
17885
17958
|
const dir = versionDir(o.home, o.version, o.platform);
|
|
17886
|
-
const lock =
|
|
17959
|
+
const lock = join23(dir, "fetch.lock");
|
|
17887
17960
|
mkdirSync17(dir, { recursive: true, mode: 493 });
|
|
17888
17961
|
let fd;
|
|
17889
17962
|
try {
|
|
@@ -17927,7 +18000,7 @@ var realPidAlive = (pid) => {
|
|
|
17927
18000
|
}
|
|
17928
18001
|
};
|
|
17929
18002
|
function engineUpdater(o) {
|
|
17930
|
-
const home = o.home ??
|
|
18003
|
+
const home = o.home ?? homedir7();
|
|
17931
18004
|
const platform = o.platform ?? process.platform;
|
|
17932
18005
|
const version = o.version;
|
|
17933
18006
|
if (!version || !VERSION_RE3.test(version))
|
|
@@ -18166,10 +18239,11 @@ var VALUE_FLAGS = [
|
|
|
18166
18239
|
"hold-cpu",
|
|
18167
18240
|
"hold-load",
|
|
18168
18241
|
"hold-pressure",
|
|
18169
|
-
"hold"
|
|
18242
|
+
"hold",
|
|
18243
|
+
"lent-by"
|
|
18170
18244
|
];
|
|
18171
18245
|
var BOOL_FLAGS = ["once", "strict-mcp", "no-strict-mcp", "sandbox", "no-sandbox"];
|
|
18172
|
-
var ENGINE_USAGE = "usage: sleds engine [--name <n>] [--at-once <n>] [--runner tmux|headless|command|orca|cmux] [--runner-cmd '<launcher>'] [--agent '<command>'] [--interval <s>] [--lease <min>] [--idle <min>] [--repo <path>] [--repos-dir <dir[:dir…]>] [--jira <EPIC>] [--mode <permission-mode>] [--model <id>] [--decider-model <id>] [--effort <e>] [--decider-effort <e>] [--drafter-model <id>] [--drafter-effort <e>] [--branch '<template>'] [--pr-title '<template>'] [--events <file>] [--org <slug>] [--strict-mcp [--mcp-allow <a,b>] | --no-strict-mcp] [--sandbox [--sandbox-allow <a,b>] | --no-sandbox] [--hold-cpu <%>] [--hold-load <per-core>] [--hold-pressure warn|critical] [--hold on|off] [--once]";
|
|
18246
|
+
var ENGINE_USAGE = "usage: sleds engine [--name <n>] [--at-once <n>] [--runner tmux|headless|command|orca|cmux] [--runner-cmd '<launcher>'] [--agent '<command>'] [--interval <s>] [--lease <min>] [--idle <min>] [--repo <path>] [--repos-dir <dir[:dir…]>] [--jira <EPIC>] [--mode <permission-mode>] [--model <id>] [--decider-model <id>] [--effort <e>] [--decider-effort <e>] [--drafter-model <id>] [--drafter-effort <e>] [--branch '<template>'] [--pr-title '<template>'] [--events <file>] [--org <slug>] [--strict-mcp [--mcp-allow <a,b>] | --no-strict-mcp] [--sandbox [--sandbox-allow <a,b>] | --no-sandbox] [--lent-by <lender> --sandbox] [--hold-cpu <%>] [--hold-load <per-core>] [--hold-pressure warn|critical] [--hold on|off] [--once]";
|
|
18173
18247
|
function templateProblem(flag, template, jira = false) {
|
|
18174
18248
|
const known = flag === "branch" ? BRANCH_FIELDS : PR_TITLE_FIELDS;
|
|
18175
18249
|
const used = templateFields(template);
|
|
@@ -18267,6 +18341,9 @@ function parseEngineArgs(argv, host) {
|
|
|
18267
18341
|
return {
|
|
18268
18342
|
error: `--sandbox-allow takes hosts like pypi.org or *.example.com — no scheme, port or path (got ${badHost})`
|
|
18269
18343
|
};
|
|
18344
|
+
const lentBy = s("lent-by")?.trim();
|
|
18345
|
+
if (lentBy && !raw.sandbox)
|
|
18346
|
+
return { error: LENT_NEEDS_SANDBOX };
|
|
18270
18347
|
const opt = (k, v) => v ? { [k]: v } : {};
|
|
18271
18348
|
return {
|
|
18272
18349
|
flags: {
|
|
@@ -18297,6 +18374,7 @@ function parseEngineArgs(argv, host) {
|
|
|
18297
18374
|
...mcpAllow.length ? { mcpAllow } : {},
|
|
18298
18375
|
...raw.sandbox ? { sandbox: true } : raw["no-sandbox"] ? { sandbox: false } : {},
|
|
18299
18376
|
...sandboxAllow.length ? { sandboxAllow: [...new Set(sandboxAllow)] } : {},
|
|
18377
|
+
...opt("lentBy", lentBy),
|
|
18300
18378
|
...holdCpu !== undefined ? { holdCpu } : {},
|
|
18301
18379
|
...holdLoad !== undefined ? { holdLoad } : {},
|
|
18302
18380
|
...holdPressure ? { holdPressure } : {},
|
|
@@ -18385,7 +18463,7 @@ function flagsFromProfile(flags, given, profile, home) {
|
|
|
18385
18463
|
}
|
|
18386
18464
|
}
|
|
18387
18465
|
if (profile.reposDir && !has("repos-dir") && !has("repo")) {
|
|
18388
|
-
out.reposDir = splitReposDirs(profile.reposDir).map((d) => home && /^~(\/|$)/.test(d) ?
|
|
18466
|
+
out.reposDir = splitReposDirs(profile.reposDir).map((d) => home && /^~(\/|$)/.test(d) ? join24(home, d.slice(1)) : d).join(":");
|
|
18389
18467
|
used.push(`repos ${profile.reposDir}`);
|
|
18390
18468
|
}
|
|
18391
18469
|
if (profile.mcpStrict !== undefined && !has("strict-mcp") && !has("no-strict-mcp")) {
|
|
@@ -18479,7 +18557,7 @@ function engineClient(o, org) {
|
|
|
18479
18557
|
return fetchClient({
|
|
18480
18558
|
...src,
|
|
18481
18559
|
timeoutMs: ENGINE_TIMEOUT_MS,
|
|
18482
|
-
version: "0.1.
|
|
18560
|
+
version: "0.1.50"
|
|
18483
18561
|
});
|
|
18484
18562
|
const asked = org?.trim() || env.SLEDS_ORG?.trim();
|
|
18485
18563
|
if (asked && !selectOrg(readConfig(o.home), org, env).seat)
|
|
@@ -18519,12 +18597,12 @@ function memberMcpConfigs(o, cwd) {
|
|
|
18519
18597
|
});
|
|
18520
18598
|
const claudeDir = (o.env ?? process.env).CLAUDE_CONFIG_DIR;
|
|
18521
18599
|
return [
|
|
18522
|
-
read(claudeDir ?
|
|
18523
|
-
...cwd ? [read(
|
|
18600
|
+
read(claudeDir ? join24(claudeDir, ".claude.json") : join24(o.home, ".claude.json")),
|
|
18601
|
+
...cwd ? [read(join24(cwd, ".mcp.json"))] : []
|
|
18524
18602
|
];
|
|
18525
18603
|
}
|
|
18526
18604
|
function engineStateDir(o, org, seat) {
|
|
18527
|
-
return seatStateDir(orgStateDir(o.stateDir ??
|
|
18605
|
+
return seatStateDir(orgStateDir(o.stateDir ?? join24(configDir(o.home, o.env ?? process.env), "engine"), org), seat);
|
|
18528
18606
|
}
|
|
18529
18607
|
function engineSeat(o, org) {
|
|
18530
18608
|
try {
|
|
@@ -18554,8 +18632,8 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
18554
18632
|
const repo = flags.repo ? resolve8(cwd, flags.repo) : undefined;
|
|
18555
18633
|
const reposDirs = splitReposDirs(flags.reposDir).map((d) => resolve8(cwd, d));
|
|
18556
18634
|
const { branch, prTitle } = flags;
|
|
18557
|
-
const hooksDir =
|
|
18558
|
-
const permissionMark = (name) =>
|
|
18635
|
+
const hooksDir = join24(stateDir, "hooks");
|
|
18636
|
+
const permissionMark = (name) => join24(hooksDir, `${name}.permission.json`);
|
|
18559
18637
|
const withHook = (name, settings) => applyPermissionHook(settings, [...o.sledsArgv ?? ["sleds"], "permission-event", "--mark", permissionMark(name)].map(shq2).join(" "));
|
|
18560
18638
|
return {
|
|
18561
18639
|
source,
|
|
@@ -18580,9 +18658,9 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
18580
18658
|
sandbox: true,
|
|
18581
18659
|
writeSandboxSettings: o.writeSandboxSettings ?? ((name, cwd, allow) => {
|
|
18582
18660
|
const gitCommonDir = gitCommonDirOf(exec, cwd);
|
|
18583
|
-
const dir =
|
|
18661
|
+
const dir = join24(stateDir, "sandbox");
|
|
18584
18662
|
mkdirSync18(dir, { recursive: true, mode: 448 });
|
|
18585
|
-
const p =
|
|
18663
|
+
const p = join24(dir, `${name}.json`);
|
|
18586
18664
|
const walls = engineSandboxSettings(o.home, o.env ?? process.env, gitCommonDir, [
|
|
18587
18665
|
...SANDBOX_DEFAULT_ALLOW,
|
|
18588
18666
|
...flags.sandboxAllow ?? []
|
|
@@ -18599,7 +18677,7 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
18599
18677
|
} : {},
|
|
18600
18678
|
writeHookSettings: (name, allow) => {
|
|
18601
18679
|
mkdirSync18(hooksDir, { recursive: true, mode: 448 });
|
|
18602
|
-
const p =
|
|
18680
|
+
const p = join24(hooksDir, `${name}.json`);
|
|
18603
18681
|
const base = allow?.length ? { permissions: { allow: [...allow] } } : {};
|
|
18604
18682
|
writeFileSync16(p, `${JSON.stringify(withHook(name, base), null, 2)}
|
|
18605
18683
|
`, { mode: 384 });
|
|
@@ -18627,9 +18705,9 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
18627
18705
|
exists
|
|
18628
18706
|
}),
|
|
18629
18707
|
writeMcpConfig: o.writeMcpConfig ?? ((name, runToken, worktree) => {
|
|
18630
|
-
const dir =
|
|
18708
|
+
const dir = join24(stateDir, "mcp");
|
|
18631
18709
|
mkdirSync18(dir, { recursive: true, mode: 448 });
|
|
18632
|
-
const p =
|
|
18710
|
+
const p = join24(dir, `${name}.json`);
|
|
18633
18711
|
let others = {};
|
|
18634
18712
|
if (flags.strictMcp && flags.mcpAllow?.length) {
|
|
18635
18713
|
const r = mcpPassThrough(flags.mcpAllow, memberMcpConfigs(o, worktree));
|
|
@@ -18645,9 +18723,9 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
18645
18723
|
}),
|
|
18646
18724
|
removeMcpConfig: o.removeMcpConfig ?? ((p) => rmSync10(p, { force: true })),
|
|
18647
18725
|
writePrompt: o.writePrompt ?? ((name, text) => {
|
|
18648
|
-
const dir =
|
|
18726
|
+
const dir = join24(stateDir, "prompts");
|
|
18649
18727
|
mkdirSync18(dir, { recursive: true, mode: 448 });
|
|
18650
|
-
const p =
|
|
18728
|
+
const p = join24(dir, `${name}.md`);
|
|
18651
18729
|
writeFileSync16(p, text, { mode: 384 });
|
|
18652
18730
|
return p;
|
|
18653
18731
|
}),
|
|
@@ -18674,14 +18752,14 @@ function engineDeps(o, flags, source, runner, stateName) {
|
|
|
18674
18752
|
}
|
|
18675
18753
|
function sandboxDenyRead(home, env) {
|
|
18676
18754
|
return {
|
|
18677
|
-
dirs: [...new Set([configDir(home, env),
|
|
18755
|
+
dirs: [...new Set([configDir(home, env), join24(home, ".config", "sleds")])],
|
|
18678
18756
|
files: [
|
|
18679
18757
|
...new Set([
|
|
18680
18758
|
tokenPath(home, env),
|
|
18681
|
-
|
|
18759
|
+
join24(home, ".sleds-token"),
|
|
18682
18760
|
settingsPath(home, env),
|
|
18683
18761
|
backupPath(home, env),
|
|
18684
|
-
|
|
18762
|
+
join24(claudeDir(home, env), "settings.local.json")
|
|
18685
18763
|
])
|
|
18686
18764
|
]
|
|
18687
18765
|
};
|
|
@@ -18700,6 +18778,36 @@ function gitCommonDirOf(exec, cwd) {
|
|
|
18700
18778
|
throw new Error(`git has no common dir for ${cwd}, so the sandbox has nowhere to commit`);
|
|
18701
18779
|
return resolve8(cwd, dir);
|
|
18702
18780
|
}
|
|
18781
|
+
var LENT_NEEDS_SANDBOX = "a lent engine runs every session sandboxed (spec 48 rule 10) — add --sandbox to --lent-by";
|
|
18782
|
+
function lenderHome(accountHome, lentBy) {
|
|
18783
|
+
return isAbsolute3(lentBy) ? resolve8(lentBy) : join24(dirname15(accountHome), lentBy);
|
|
18784
|
+
}
|
|
18785
|
+
function lentHomeProblems(accountHome, lentBy, modeOf) {
|
|
18786
|
+
const lender = lenderHome(accountHome, lentBy);
|
|
18787
|
+
if (lender === resolve8(accountHome))
|
|
18788
|
+
return [
|
|
18789
|
+
`--lent-by ${lentBy} is this account — a lent engine runs as the borrower's own OS user, not the lender's`
|
|
18790
|
+
];
|
|
18791
|
+
const problems = [];
|
|
18792
|
+
for (const [who, home] of [
|
|
18793
|
+
["the borrower's", resolve8(accountHome)],
|
|
18794
|
+
["the lender's", lender]
|
|
18795
|
+
]) {
|
|
18796
|
+
const mode = modeOf(home);
|
|
18797
|
+
if (mode === null)
|
|
18798
|
+
problems.push(`${who} home ${home} cannot be read — is ${lentBy} right?`);
|
|
18799
|
+
else if ((mode & 63) !== 0)
|
|
18800
|
+
problems.push(`${who} home ${home} is ${(mode & 511).toString(8)}, open to other users — run: sudo chmod 700 ${home}`);
|
|
18801
|
+
}
|
|
18802
|
+
return problems;
|
|
18803
|
+
}
|
|
18804
|
+
var homeMode = (path) => {
|
|
18805
|
+
try {
|
|
18806
|
+
return statSync5(path).mode & 4095;
|
|
18807
|
+
} catch {
|
|
18808
|
+
return null;
|
|
18809
|
+
}
|
|
18810
|
+
};
|
|
18703
18811
|
function pinOrg2(configJson, org) {
|
|
18704
18812
|
if (!org)
|
|
18705
18813
|
return configJson;
|
|
@@ -18740,7 +18848,7 @@ async function driveEngine(o, flags, deps, until = {}) {
|
|
|
18740
18848
|
runner: deps.runner.name,
|
|
18741
18849
|
atOnce: flags.atOnce,
|
|
18742
18850
|
interval: flags.interval,
|
|
18743
|
-
cliVersion: "0.1.
|
|
18851
|
+
cliVersion: "0.1.50"
|
|
18744
18852
|
};
|
|
18745
18853
|
const beat = (checkedAt) => {
|
|
18746
18854
|
const m = deps.machine;
|
|
@@ -18818,6 +18926,7 @@ async function drive(o, flags, deps, until, beat) {
|
|
|
18818
18926
|
deps.log = (line) => event(noteEvent(line));
|
|
18819
18927
|
let running = 0;
|
|
18820
18928
|
let down = 0;
|
|
18929
|
+
await until.beforeFirstTick?.();
|
|
18821
18930
|
for (;; ) {
|
|
18822
18931
|
let report = null;
|
|
18823
18932
|
try {
|
|
@@ -19085,7 +19194,7 @@ import {
|
|
|
19085
19194
|
writeFileSync as writeFileSync17
|
|
19086
19195
|
} from "node:fs";
|
|
19087
19196
|
import { hostname as hostname3 } from "node:os";
|
|
19088
|
-
import { basename as basename6, dirname as
|
|
19197
|
+
import { basename as basename6, dirname as dirname16, isAbsolute as isAbsolute4, join as join25 } from "node:path";
|
|
19089
19198
|
init_state();
|
|
19090
19199
|
var ENGINE_LABEL = "ai.sleds.engine";
|
|
19091
19200
|
var ENGINE_INSTALL_USAGE = `usage: sleds engine install [engine flags] | sleds engine uninstall [--name <n>] [--org <slug>]
|
|
@@ -19093,7 +19202,7 @@ ${ENGINE_USAGE}`;
|
|
|
19093
19202
|
function stableArgv(argv, realpath = realpathSync, home) {
|
|
19094
19203
|
const link = sledsLink(home);
|
|
19095
19204
|
return argv.map((a) => {
|
|
19096
|
-
if (!
|
|
19205
|
+
if (!isAbsolute4(a) || a === link)
|
|
19097
19206
|
return a;
|
|
19098
19207
|
try {
|
|
19099
19208
|
return realpath(a);
|
|
@@ -19106,13 +19215,13 @@ function engineLabel(name, org, seat) {
|
|
|
19106
19215
|
return [ENGINE_LABEL, org, seat?.trim(), name].filter((p) => Boolean(p)).map((p, i) => i === 0 ? p : engineSlug(p)).join(".");
|
|
19107
19216
|
}
|
|
19108
19217
|
function enginePlistPath(home, name, org, seat) {
|
|
19109
|
-
return
|
|
19218
|
+
return join25(home, "Library", "LaunchAgents", `${engineLabel(name, org, seat)}.plist`);
|
|
19110
19219
|
}
|
|
19111
19220
|
function engineLogPath(stateDir, name) {
|
|
19112
|
-
return
|
|
19221
|
+
return join25(stateDir, `${engineSlug(name)}.log`);
|
|
19113
19222
|
}
|
|
19114
19223
|
function engineEventsPath(stateDir, name) {
|
|
19115
|
-
return
|
|
19224
|
+
return join25(stateDir, `${engineSlug(name)}.events.jsonl`);
|
|
19116
19225
|
}
|
|
19117
19226
|
var xmlEscape4 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
19118
19227
|
function buildEnginePlist(o) {
|
|
@@ -19209,7 +19318,7 @@ function readEngines(dir, suffix, manager, parse) {
|
|
|
19209
19318
|
}
|
|
19210
19319
|
const out = [];
|
|
19211
19320
|
for (const name of names.filter((n) => n.startsWith(`${ENGINE_LABEL}.`) && n.endsWith(suffix))) {
|
|
19212
|
-
const path =
|
|
19321
|
+
const path = join25(dir, name);
|
|
19213
19322
|
let parsed;
|
|
19214
19323
|
try {
|
|
19215
19324
|
parsed = parse(readFileSync16(path, "utf8"), name);
|
|
@@ -19229,7 +19338,7 @@ function readEngines(dir, suffix, manager, parse) {
|
|
|
19229
19338
|
}
|
|
19230
19339
|
function installedEngines(home) {
|
|
19231
19340
|
return [
|
|
19232
|
-
...readEngines(
|
|
19341
|
+
...readEngines(join25(home, "Library", "LaunchAgents"), ".plist", "launchd", parseEnginePlist),
|
|
19233
19342
|
...readEngines(engineUnitDir(home), ".service", "systemd", (text, file) => {
|
|
19234
19343
|
const parsed = parseEngineUnit(text);
|
|
19235
19344
|
return parsed && { label: basename6(file, ".service"), ...parsed };
|
|
@@ -19279,7 +19388,7 @@ function engineInstall(o) {
|
|
|
19279
19388
|
if (platform === "linux")
|
|
19280
19389
|
return installUnit({ o, parsed, label, sledsArgv, env: agentEnv, logPath, exec });
|
|
19281
19390
|
const plist = enginePlistPath(o.home, parsed.name, parsed.org, seat);
|
|
19282
|
-
mkdirSync19(
|
|
19391
|
+
mkdirSync19(dirname16(plist), { recursive: true });
|
|
19283
19392
|
if (existsSync19(plist))
|
|
19284
19393
|
exec("launchctl", ["unload", plist]);
|
|
19285
19394
|
for (const other of installedEngines(o.home)) {
|
|
@@ -19321,7 +19430,7 @@ function installUnit(a) {
|
|
|
19321
19430
|
const unit = engineUnitPath(o.home, label);
|
|
19322
19431
|
const unitName = basename6(unit);
|
|
19323
19432
|
const systemctl = (...args) => exec("systemctl", ["--user", ...args]);
|
|
19324
|
-
mkdirSync19(
|
|
19433
|
+
mkdirSync19(dirname16(unit), { recursive: true });
|
|
19325
19434
|
if (existsSync19(unit))
|
|
19326
19435
|
systemctl("stop", unitName);
|
|
19327
19436
|
for (const other of installedEngines(o.home)) {
|
|
@@ -19697,7 +19806,7 @@ async function runDoctor(o) {
|
|
|
19697
19806
|
checks.push({ level: "ok", name: "path", detail: which[0] ?? "" });
|
|
19698
19807
|
const link = sledsLink(home, o.platform);
|
|
19699
19808
|
if (existsSync21(link)) {
|
|
19700
|
-
const binDir =
|
|
19809
|
+
const binDir = dirname17(link);
|
|
19701
19810
|
const onPath = (env.PATH ?? "").split(delimiter3).includes(binDir);
|
|
19702
19811
|
const first = which[0];
|
|
19703
19812
|
const fix = `echo 'export PATH="${binDir}:$PATH"' >> ~/.zshrc`;
|
|
@@ -19886,12 +19995,12 @@ function sandboxChecks(o, env) {
|
|
|
19886
19995
|
}
|
|
19887
19996
|
];
|
|
19888
19997
|
const nonce = o.nonce ?? `sleds-probe-${randomBytes(16).toString("hex")}`;
|
|
19889
|
-
const probe =
|
|
19890
|
-
const work = mkdtempSync(
|
|
19998
|
+
const probe = join26(dir, SANDBOX_PROBE);
|
|
19999
|
+
const work = mkdtempSync(join26(tmpdir(), "sleds-sandbox-"));
|
|
19891
20000
|
try {
|
|
19892
20001
|
writeFileSync19(probe, `${nonce}
|
|
19893
20002
|
`, { mode: 384 });
|
|
19894
|
-
const settingsFile =
|
|
20003
|
+
const settingsFile = join26(work, "settings.json");
|
|
19895
20004
|
const settings = engineSandboxSettings(o.home, env, work, SANDBOX_DEFAULT_ALLOW);
|
|
19896
20005
|
const claudeSettings = settingsPath(o.home, env);
|
|
19897
20006
|
writeFileSync19(settingsFile, JSON.stringify(settings, null, 2), { mode: 384 });
|
|
@@ -19935,6 +20044,8 @@ function engineChecks(o, env) {
|
|
|
19935
20044
|
const org = engineOrg({ home: o.home, env }).slug;
|
|
19936
20045
|
const engines = installedEngines(o.home).filter((e) => e.manager === manager && (e.org === null || !org || e.org === org));
|
|
19937
20046
|
const need = engines.length > 0 ? "fail" : "warn";
|
|
20047
|
+
if (o.lentBy && !engines.some((e) => engineArg(e.programArgs, "lent-by")))
|
|
20048
|
+
checks.push(...lentChecks(o, o.lentBy, null));
|
|
19938
20049
|
const runner = engines.map((e) => engineArg(e.programArgs, "runner")).find(Boolean) ?? "tmux";
|
|
19939
20050
|
const gh = which("gh");
|
|
19940
20051
|
if (!gh)
|
|
@@ -20034,18 +20145,45 @@ function engineChecks(o, env) {
|
|
|
20034
20145
|
detail: `${e.label} names no --repos-dir — it works only if your engine profile sets Repos folders`,
|
|
20035
20146
|
fix: "set Repos folders in Settings › Running work, or sleds engine install --repos-dir ~/code"
|
|
20036
20147
|
});
|
|
20148
|
+
const lentBy = engineArg(e.programArgs, "lent-by");
|
|
20149
|
+
if (lentBy)
|
|
20150
|
+
checks.push(...lentChecks(o, lentBy, e));
|
|
20037
20151
|
}
|
|
20038
20152
|
return checks;
|
|
20039
20153
|
}
|
|
20154
|
+
function lentChecks(o, lentBy, engine) {
|
|
20155
|
+
const checks = [];
|
|
20156
|
+
const problems = lentHomeProblems((o.accountHome ?? (() => userInfo2().homedir))(), lentBy, o.homeMode ?? homeMode);
|
|
20157
|
+
checks.push(problems.length === 0 ? { level: "ok", name: "lent homes", detail: `lent by ${lentBy} · both homes 700` } : {
|
|
20158
|
+
level: "fail",
|
|
20159
|
+
name: "lent homes",
|
|
20160
|
+
detail: problems.join("; "),
|
|
20161
|
+
fix: "sudo chmod 700 on each home named (the lender runs it for theirs)"
|
|
20162
|
+
});
|
|
20163
|
+
if (engine)
|
|
20164
|
+
checks.push(engine.programArgs.includes("--sandbox") ? { level: "ok", name: "lent sandbox", detail: `${engine.label} runs --sandbox` } : {
|
|
20165
|
+
level: "fail",
|
|
20166
|
+
name: "lent sandbox",
|
|
20167
|
+
detail: `${engine.label}: ${LENT_NEEDS_SANDBOX}`,
|
|
20168
|
+
fix: `sleds engine install --lent-by ${lentBy} --sandbox`
|
|
20169
|
+
});
|
|
20170
|
+
return checks;
|
|
20171
|
+
}
|
|
20040
20172
|
function boxChecks(o, env, which, need) {
|
|
20041
20173
|
const claude = which("claude");
|
|
20042
20174
|
const file = boxEnvPath(o.home);
|
|
20043
|
-
let
|
|
20175
|
+
let boxEnvText = null;
|
|
20044
20176
|
try {
|
|
20045
|
-
|
|
20177
|
+
boxEnvText = readFileSync19(file, "utf8");
|
|
20046
20178
|
} catch {
|
|
20047
|
-
|
|
20179
|
+
boxEnvText = null;
|
|
20048
20180
|
}
|
|
20181
|
+
const cred = detectCredential(env, {
|
|
20182
|
+
home: o.home,
|
|
20183
|
+
boxEnvText,
|
|
20184
|
+
boxEnvPath: file,
|
|
20185
|
+
exists: o.exists ?? existsSync21
|
|
20186
|
+
});
|
|
20049
20187
|
return [
|
|
20050
20188
|
claude ? { level: "ok", name: "claude cli", detail: `${claude} · the headless runner's agent` } : {
|
|
20051
20189
|
level: need,
|
|
@@ -20053,14 +20191,20 @@ function boxChecks(o, env, which, need) {
|
|
|
20053
20191
|
detail: "`claude` not on PATH — the headless runner starts Claude Code for each node",
|
|
20054
20192
|
fix: "npm install -g @anthropic-ai/claude-code"
|
|
20055
20193
|
},
|
|
20056
|
-
|
|
20194
|
+
cred ? { level: "ok", name: "credential", detail: credentialDetail(cred) } : {
|
|
20057
20195
|
level: need,
|
|
20058
|
-
name: "
|
|
20059
|
-
detail: `
|
|
20060
|
-
fix: `add
|
|
20196
|
+
name: "credential",
|
|
20197
|
+
detail: `no ${API_KEY_VAR}, ${SEAT_TOKEN_VAR} or claude login here or in ${file} — a headless session cannot sign in`,
|
|
20198
|
+
fix: `add ${API_KEY_VAR}=… (a key) or ${SEAT_TOKEN_VAR}=… (a seat, from \`claude setup-token\`) to ${file}, or sign in once with \`claude\` and /login`
|
|
20061
20199
|
}
|
|
20062
20200
|
];
|
|
20063
20201
|
}
|
|
20202
|
+
function credentialDetail(c) {
|
|
20203
|
+
if (c.source === "login")
|
|
20204
|
+
return `seat · claude login at ${c.where}`;
|
|
20205
|
+
const name = c.source === "api_key" ? API_KEY_VAR : SEAT_TOKEN_VAR;
|
|
20206
|
+
return `${c.kind} · ${name} ${c.where === "this shell" ? "set in this shell" : `named in ${c.where}`}`;
|
|
20207
|
+
}
|
|
20064
20208
|
function cmuxCheck(o, env) {
|
|
20065
20209
|
const exec = o.exec ?? defaultExec3;
|
|
20066
20210
|
const bin = resolveCmuxBin(o.exists ?? existsSync21, env.PATH ?? "");
|
|
@@ -20151,10 +20295,11 @@ import {
|
|
|
20151
20295
|
readFileSync as readFileSync20,
|
|
20152
20296
|
existsSync as realExists2,
|
|
20153
20297
|
rmSync as rmSync14,
|
|
20298
|
+
statSync as statSync6,
|
|
20154
20299
|
writeFileSync as writeFileSync20
|
|
20155
20300
|
} from "node:fs";
|
|
20156
|
-
import { hostname as hostname4 } from "node:os";
|
|
20157
|
-
import { join as
|
|
20301
|
+
import { hostname as hostname4, userInfo as userInfo3 } from "node:os";
|
|
20302
|
+
import { dirname as dirname18, isAbsolute as isAbsolute5, join as join27, resolve as resolve10 } from "node:path";
|
|
20158
20303
|
init_machine();
|
|
20159
20304
|
init_state();
|
|
20160
20305
|
init_meter();
|
|
@@ -20190,10 +20335,11 @@ var VALUE_FLAGS2 = [
|
|
|
20190
20335
|
"hold-cpu",
|
|
20191
20336
|
"hold-load",
|
|
20192
20337
|
"hold-pressure",
|
|
20193
|
-
"hold"
|
|
20338
|
+
"hold",
|
|
20339
|
+
"lent-by"
|
|
20194
20340
|
];
|
|
20195
20341
|
var BOOL_FLAGS2 = ["once", "strict-mcp", "no-strict-mcp", "sandbox", "no-sandbox"];
|
|
20196
|
-
var ENGINE_USAGE2 = "usage: sleds engine [--name <n>] [--at-once <n>] [--runner tmux|headless|command|orca|cmux] [--runner-cmd '<launcher>'] [--agent '<command>'] [--interval <s>] [--lease <min>] [--idle <min>] [--repo <path>] [--repos-dir <dir[:dir…]>] [--jira <EPIC>] [--mode <permission-mode>] [--model <id>] [--decider-model <id>] [--effort <e>] [--decider-effort <e>] [--drafter-model <id>] [--drafter-effort <e>] [--branch '<template>'] [--pr-title '<template>'] [--events <file>] [--org <slug>] [--strict-mcp [--mcp-allow <a,b>] | --no-strict-mcp] [--sandbox [--sandbox-allow <a,b>] | --no-sandbox] [--hold-cpu <%>] [--hold-load <per-core>] [--hold-pressure warn|critical] [--hold on|off] [--once]";
|
|
20342
|
+
var ENGINE_USAGE2 = "usage: sleds engine [--name <n>] [--at-once <n>] [--runner tmux|headless|command|orca|cmux] [--runner-cmd '<launcher>'] [--agent '<command>'] [--interval <s>] [--lease <min>] [--idle <min>] [--repo <path>] [--repos-dir <dir[:dir…]>] [--jira <EPIC>] [--mode <permission-mode>] [--model <id>] [--decider-model <id>] [--effort <e>] [--decider-effort <e>] [--drafter-model <id>] [--drafter-effort <e>] [--branch '<template>'] [--pr-title '<template>'] [--events <file>] [--org <slug>] [--strict-mcp [--mcp-allow <a,b>] | --no-strict-mcp] [--sandbox [--sandbox-allow <a,b>] | --no-sandbox] [--lent-by <lender> --sandbox] [--hold-cpu <%>] [--hold-load <per-core>] [--hold-pressure warn|critical] [--hold on|off] [--once]";
|
|
20197
20343
|
function templateProblem2(flag, template, jira = false) {
|
|
20198
20344
|
const known = flag === "branch" ? BRANCH_FIELDS : PR_TITLE_FIELDS;
|
|
20199
20345
|
const used = templateFields(template);
|
|
@@ -20291,6 +20437,9 @@ function parseEngineArgs2(argv, host) {
|
|
|
20291
20437
|
return {
|
|
20292
20438
|
error: `--sandbox-allow takes hosts like pypi.org or *.example.com — no scheme, port or path (got ${badHost})`
|
|
20293
20439
|
};
|
|
20440
|
+
const lentBy = s("lent-by")?.trim();
|
|
20441
|
+
if (lentBy && !raw.sandbox)
|
|
20442
|
+
return { error: LENT_NEEDS_SANDBOX2 };
|
|
20294
20443
|
const opt = (k, v) => v ? { [k]: v } : {};
|
|
20295
20444
|
return {
|
|
20296
20445
|
flags: {
|
|
@@ -20321,6 +20470,7 @@ function parseEngineArgs2(argv, host) {
|
|
|
20321
20470
|
...mcpAllow.length ? { mcpAllow } : {},
|
|
20322
20471
|
...raw.sandbox ? { sandbox: true } : raw["no-sandbox"] ? { sandbox: false } : {},
|
|
20323
20472
|
...sandboxAllow.length ? { sandboxAllow: [...new Set(sandboxAllow)] } : {},
|
|
20473
|
+
...opt("lentBy", lentBy),
|
|
20324
20474
|
...holdCpu !== undefined ? { holdCpu } : {},
|
|
20325
20475
|
...holdLoad !== undefined ? { holdLoad } : {},
|
|
20326
20476
|
...holdPressure ? { holdPressure } : {},
|
|
@@ -20409,7 +20559,7 @@ function flagsFromProfile2(flags, given, profile, home) {
|
|
|
20409
20559
|
}
|
|
20410
20560
|
}
|
|
20411
20561
|
if (profile.reposDir && !has("repos-dir") && !has("repo")) {
|
|
20412
|
-
out.reposDir = splitReposDirs(profile.reposDir).map((d) => home && /^~(\/|$)/.test(d) ?
|
|
20562
|
+
out.reposDir = splitReposDirs(profile.reposDir).map((d) => home && /^~(\/|$)/.test(d) ? join27(home, d.slice(1)) : d).join(":");
|
|
20413
20563
|
used.push(`repos ${profile.reposDir}`);
|
|
20414
20564
|
}
|
|
20415
20565
|
if (profile.mcpStrict !== undefined && !has("strict-mcp") && !has("no-strict-mcp")) {
|
|
@@ -20555,7 +20705,7 @@ function engineClient2(o, org) {
|
|
|
20555
20705
|
return fetchClient({
|
|
20556
20706
|
...src,
|
|
20557
20707
|
timeoutMs: ENGINE_TIMEOUT_MS2,
|
|
20558
|
-
version: "0.1.
|
|
20708
|
+
version: "0.1.50"
|
|
20559
20709
|
});
|
|
20560
20710
|
const asked = org?.trim() || env.SLEDS_ORG?.trim();
|
|
20561
20711
|
if (asked && !selectOrg(readConfig(o.home), org, env).seat)
|
|
@@ -20604,12 +20754,12 @@ function memberMcpConfigs2(o, cwd) {
|
|
|
20604
20754
|
});
|
|
20605
20755
|
const claudeDir = (o.env ?? process.env).CLAUDE_CONFIG_DIR;
|
|
20606
20756
|
return [
|
|
20607
|
-
read(claudeDir ?
|
|
20608
|
-
...cwd ? [read(
|
|
20757
|
+
read(claudeDir ? join27(claudeDir, ".claude.json") : join27(o.home, ".claude.json")),
|
|
20758
|
+
...cwd ? [read(join27(cwd, ".mcp.json"))] : []
|
|
20609
20759
|
];
|
|
20610
20760
|
}
|
|
20611
20761
|
function engineStateDir2(o, org, seat) {
|
|
20612
|
-
return seatStateDir(orgStateDir(o.stateDir ??
|
|
20762
|
+
return seatStateDir(orgStateDir(o.stateDir ?? join27(configDir(o.home, o.env ?? process.env), "engine"), org), seat);
|
|
20613
20763
|
}
|
|
20614
20764
|
function engineSeat2(o, org) {
|
|
20615
20765
|
try {
|
|
@@ -20628,6 +20778,19 @@ function engineToken2(o, org) {
|
|
|
20628
20778
|
}
|
|
20629
20779
|
}
|
|
20630
20780
|
var withToken2 = (token, now) => token ? { token, tokenNow: now } : {};
|
|
20781
|
+
function engineCredential(o) {
|
|
20782
|
+
const file = boxEnvPath(o.home);
|
|
20783
|
+
let boxEnvText = null;
|
|
20784
|
+
try {
|
|
20785
|
+
boxEnvText = readFileSync20(file, "utf8");
|
|
20786
|
+
} catch {}
|
|
20787
|
+
return detectCredential(o.env ?? process.env, {
|
|
20788
|
+
home: o.home,
|
|
20789
|
+
boxEnvText,
|
|
20790
|
+
boxEnvPath: file,
|
|
20791
|
+
exists: o.exists ?? realExists2
|
|
20792
|
+
})?.kind;
|
|
20793
|
+
}
|
|
20631
20794
|
function engineDeps2(o, flags, source, runner, stateName) {
|
|
20632
20795
|
const exec = guardGit(o.exec ?? defaultExec);
|
|
20633
20796
|
const cwd = o.cwd ?? process.cwd();
|
|
@@ -20639,8 +20802,8 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
20639
20802
|
const repo = flags.repo ? resolve10(cwd, flags.repo) : undefined;
|
|
20640
20803
|
const reposDirs = splitReposDirs(flags.reposDir).map((d) => resolve10(cwd, d));
|
|
20641
20804
|
const { branch, prTitle } = flags;
|
|
20642
|
-
const hooksDir =
|
|
20643
|
-
const permissionMark = (name) =>
|
|
20805
|
+
const hooksDir = join27(stateDir, "hooks");
|
|
20806
|
+
const permissionMark = (name) => join27(hooksDir, `${name}.permission.json`);
|
|
20644
20807
|
const withHook = (name, settings) => applyPermissionHook(settings, [...o.sledsArgv ?? ["sleds"], "permission-event", "--mark", permissionMark(name)].map(shq2).join(" "));
|
|
20645
20808
|
return {
|
|
20646
20809
|
source,
|
|
@@ -20665,9 +20828,9 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
20665
20828
|
sandbox: true,
|
|
20666
20829
|
writeSandboxSettings: o.writeSandboxSettings ?? ((name, cwd, allow) => {
|
|
20667
20830
|
const gitCommonDir = gitCommonDirOf2(exec, cwd);
|
|
20668
|
-
const dir =
|
|
20831
|
+
const dir = join27(stateDir, "sandbox");
|
|
20669
20832
|
mkdirSync21(dir, { recursive: true, mode: 448 });
|
|
20670
|
-
const p =
|
|
20833
|
+
const p = join27(dir, `${name}.json`);
|
|
20671
20834
|
const walls = engineSandboxSettings2(o.home, o.env ?? process.env, gitCommonDir, [
|
|
20672
20835
|
...SANDBOX_DEFAULT_ALLOW,
|
|
20673
20836
|
...flags.sandboxAllow ?? []
|
|
@@ -20684,7 +20847,7 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
20684
20847
|
} : {},
|
|
20685
20848
|
writeHookSettings: (name, allow) => {
|
|
20686
20849
|
mkdirSync21(hooksDir, { recursive: true, mode: 448 });
|
|
20687
|
-
const p =
|
|
20850
|
+
const p = join27(hooksDir, `${name}.json`);
|
|
20688
20851
|
const base = allow?.length ? { permissions: { allow: [...allow] } } : {};
|
|
20689
20852
|
writeFileSync20(p, `${JSON.stringify(withHook(name, base), null, 2)}
|
|
20690
20853
|
`, { mode: 384 });
|
|
@@ -20712,9 +20875,9 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
20712
20875
|
exists
|
|
20713
20876
|
}),
|
|
20714
20877
|
writeMcpConfig: o.writeMcpConfig ?? ((name, runToken, worktree) => {
|
|
20715
|
-
const dir =
|
|
20878
|
+
const dir = join27(stateDir, "mcp");
|
|
20716
20879
|
mkdirSync21(dir, { recursive: true, mode: 448 });
|
|
20717
|
-
const p =
|
|
20880
|
+
const p = join27(dir, `${name}.json`);
|
|
20718
20881
|
let others = {};
|
|
20719
20882
|
if (flags.strictMcp && flags.mcpAllow?.length) {
|
|
20720
20883
|
const r = mcpPassThrough(flags.mcpAllow, memberMcpConfigs2(o, worktree));
|
|
@@ -20730,9 +20893,9 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
20730
20893
|
}),
|
|
20731
20894
|
removeMcpConfig: o.removeMcpConfig ?? ((p) => rmSync14(p, { force: true })),
|
|
20732
20895
|
writePrompt: o.writePrompt ?? ((name, text) => {
|
|
20733
|
-
const dir =
|
|
20896
|
+
const dir = join27(stateDir, "prompts");
|
|
20734
20897
|
mkdirSync21(dir, { recursive: true, mode: 448 });
|
|
20735
|
-
const p =
|
|
20898
|
+
const p = join27(dir, `${name}.md`);
|
|
20736
20899
|
writeFileSync20(p, text, { mode: 384 });
|
|
20737
20900
|
return p;
|
|
20738
20901
|
}),
|
|
@@ -20759,14 +20922,14 @@ function engineDeps2(o, flags, source, runner, stateName) {
|
|
|
20759
20922
|
}
|
|
20760
20923
|
function sandboxDenyRead2(home, env) {
|
|
20761
20924
|
return {
|
|
20762
|
-
dirs: [...new Set([configDir(home, env),
|
|
20925
|
+
dirs: [...new Set([configDir(home, env), join27(home, ".config", "sleds")])],
|
|
20763
20926
|
files: [
|
|
20764
20927
|
...new Set([
|
|
20765
20928
|
tokenPath(home, env),
|
|
20766
|
-
|
|
20929
|
+
join27(home, ".sleds-token"),
|
|
20767
20930
|
settingsPath(home, env),
|
|
20768
20931
|
backupPath(home, env),
|
|
20769
|
-
|
|
20932
|
+
join27(claudeDir(home, env), "settings.local.json")
|
|
20770
20933
|
])
|
|
20771
20934
|
]
|
|
20772
20935
|
};
|
|
@@ -20786,6 +20949,8 @@ function gitCommonDirOf2(exec, cwd) {
|
|
|
20786
20949
|
return resolve10(cwd, dir);
|
|
20787
20950
|
}
|
|
20788
20951
|
function sandboxRefusal(flags) {
|
|
20952
|
+
if (flags.lentBy && !flags.sandbox)
|
|
20953
|
+
return LENT_NEEDS_SANDBOX2;
|
|
20789
20954
|
if (!flags.sandbox)
|
|
20790
20955
|
return null;
|
|
20791
20956
|
if (flags.runner === "conductor")
|
|
@@ -20796,6 +20961,36 @@ function sandboxRefusal(flags) {
|
|
|
20796
20961
|
return "sandboxed sessions: Codex's sandbox walls writes, not reads — the seat token stays readable; use Claude Code, or --no-sandbox";
|
|
20797
20962
|
return null;
|
|
20798
20963
|
}
|
|
20964
|
+
var LENT_NEEDS_SANDBOX2 = "a lent engine runs every session sandboxed (spec 48 rule 10) — add --sandbox to --lent-by";
|
|
20965
|
+
function lenderHome2(accountHome, lentBy) {
|
|
20966
|
+
return isAbsolute5(lentBy) ? resolve10(lentBy) : join27(dirname18(accountHome), lentBy);
|
|
20967
|
+
}
|
|
20968
|
+
function lentHomeProblems2(accountHome, lentBy, modeOf) {
|
|
20969
|
+
const lender = lenderHome2(accountHome, lentBy);
|
|
20970
|
+
if (lender === resolve10(accountHome))
|
|
20971
|
+
return [
|
|
20972
|
+
`--lent-by ${lentBy} is this account — a lent engine runs as the borrower's own OS user, not the lender's`
|
|
20973
|
+
];
|
|
20974
|
+
const problems = [];
|
|
20975
|
+
for (const [who, home] of [
|
|
20976
|
+
["the borrower's", resolve10(accountHome)],
|
|
20977
|
+
["the lender's", lender]
|
|
20978
|
+
]) {
|
|
20979
|
+
const mode = modeOf(home);
|
|
20980
|
+
if (mode === null)
|
|
20981
|
+
problems.push(`${who} home ${home} cannot be read — is ${lentBy} right?`);
|
|
20982
|
+
else if ((mode & 63) !== 0)
|
|
20983
|
+
problems.push(`${who} home ${home} is ${(mode & 511).toString(8)}, open to other users — run: sudo chmod 700 ${home}`);
|
|
20984
|
+
}
|
|
20985
|
+
return problems;
|
|
20986
|
+
}
|
|
20987
|
+
var homeMode2 = (path) => {
|
|
20988
|
+
try {
|
|
20989
|
+
return statSync6(path).mode & 4095;
|
|
20990
|
+
} catch {
|
|
20991
|
+
return null;
|
|
20992
|
+
}
|
|
20993
|
+
};
|
|
20799
20994
|
function pinOrg3(configJson, org) {
|
|
20800
20995
|
if (!org)
|
|
20801
20996
|
return configJson;
|
|
@@ -20836,7 +21031,7 @@ async function driveEngine2(o, flags, deps, until = {}) {
|
|
|
20836
21031
|
runner: deps.runner.name,
|
|
20837
21032
|
atOnce: flags.atOnce,
|
|
20838
21033
|
interval: flags.interval,
|
|
20839
|
-
cliVersion: "0.1.
|
|
21034
|
+
cliVersion: "0.1.50"
|
|
20840
21035
|
};
|
|
20841
21036
|
const beat = (checkedAt) => {
|
|
20842
21037
|
const m = deps.machine;
|
|
@@ -20914,6 +21109,7 @@ async function drive2(o, flags, deps, until, beat) {
|
|
|
20914
21109
|
deps.log = (line) => event(noteEvent(line));
|
|
20915
21110
|
let running = 0;
|
|
20916
21111
|
let down = 0;
|
|
21112
|
+
await until.beforeFirstTick?.();
|
|
20917
21113
|
for (;; ) {
|
|
20918
21114
|
let report = null;
|
|
20919
21115
|
try {
|
|
@@ -21095,6 +21291,14 @@ var engineCmd = async (o) => {
|
|
|
21095
21291
|
error(refusal);
|
|
21096
21292
|
return 2;
|
|
21097
21293
|
}
|
|
21294
|
+
if (flags.lentBy) {
|
|
21295
|
+
const open = lentHomeProblems2((o.accountHome ?? (() => userInfo3().homedir))(), flags.lentBy, o.homeMode ?? homeMode2);
|
|
21296
|
+
if (open.length) {
|
|
21297
|
+
for (const line of open)
|
|
21298
|
+
error(`lent engine: ${line}`);
|
|
21299
|
+
return 2;
|
|
21300
|
+
}
|
|
21301
|
+
}
|
|
21098
21302
|
if (flags.sandbox && flags.runner === "managed")
|
|
21099
21303
|
notes.push("sandboxed sessions: the managed runner's container is its own sandbox — the engine's settings do not reach it");
|
|
21100
21304
|
let source;
|
|
@@ -21186,6 +21390,7 @@ var engineCmd = async (o) => {
|
|
|
21186
21390
|
watch.beat();
|
|
21187
21391
|
return update();
|
|
21188
21392
|
};
|
|
21393
|
+
let beforeFirstTick;
|
|
21189
21394
|
if (client) {
|
|
21190
21395
|
const send = beater(client, o.now ?? Date.now);
|
|
21191
21396
|
let noted;
|
|
@@ -21204,20 +21409,34 @@ var engineCmd = async (o) => {
|
|
|
21204
21409
|
refused = r.refused;
|
|
21205
21410
|
error(r.below ? `${r.refused}. This engine is not shown as up until it beats on a version SLEDS serves.` : `${r.refused}. This engine is not shown as up until it beats under a name of its own.`);
|
|
21206
21411
|
};
|
|
21412
|
+
const credential = engineCredential(o);
|
|
21413
|
+
const body = () => {
|
|
21414
|
+
const m = deps.machine;
|
|
21415
|
+
return beatBody(deps.readState(), { name: flags.name, runner: deps.runner.name }, credential ? { credential } : {}, {
|
|
21416
|
+
atOnce: deps.atOnce,
|
|
21417
|
+
...m?.last ? { machine: m.last } : {},
|
|
21418
|
+
...m?.hold && !m.off ? { hold: m.hold } : {}
|
|
21419
|
+
});
|
|
21420
|
+
};
|
|
21421
|
+
const heard = (r) => {
|
|
21422
|
+
sayRefused(r);
|
|
21423
|
+
if (r.ok) {
|
|
21424
|
+
updater.sawBeat(r.update);
|
|
21425
|
+
noteBeat(r.update);
|
|
21426
|
+
}
|
|
21427
|
+
};
|
|
21428
|
+
beforeFirstTick = async () => {
|
|
21429
|
+
try {
|
|
21430
|
+
heard(await postBeat(client, body()));
|
|
21431
|
+
} catch {}
|
|
21432
|
+
};
|
|
21207
21433
|
afterTick = async () => {
|
|
21208
21434
|
try {
|
|
21209
|
-
|
|
21210
|
-
|
|
21211
|
-
|
|
21212
|
-
|
|
21213
|
-
|
|
21214
|
-
}))?.then((r) => {
|
|
21215
|
-
sayRefused(r);
|
|
21216
|
-
if (r?.ok) {
|
|
21217
|
-
updater.sawBeat(r.update);
|
|
21218
|
-
noteBeat(r.update);
|
|
21219
|
-
}
|
|
21220
|
-
if (r && (r.ok || ("unreachable" in r)))
|
|
21435
|
+
send(body())?.then((r) => {
|
|
21436
|
+
if (!r)
|
|
21437
|
+
return;
|
|
21438
|
+
heard(r);
|
|
21439
|
+
if (r.ok || "unreachable" in r)
|
|
21221
21440
|
watch.beat();
|
|
21222
21441
|
}, () => {});
|
|
21223
21442
|
} catch {}
|
|
@@ -21225,7 +21444,7 @@ var engineCmd = async (o) => {
|
|
|
21225
21444
|
};
|
|
21226
21445
|
}
|
|
21227
21446
|
try {
|
|
21228
|
-
return await driveEngine2(o, flags, deps, { afterTick });
|
|
21447
|
+
return await driveEngine2(o, flags, deps, { afterTick, beforeFirstTick });
|
|
21229
21448
|
} finally {
|
|
21230
21449
|
watch.stop();
|
|
21231
21450
|
}
|
|
@@ -21435,7 +21654,7 @@ import {
|
|
|
21435
21654
|
writeFileSync as writeFileSync21
|
|
21436
21655
|
} from "node:fs";
|
|
21437
21656
|
import { hostname as hostname5 } from "node:os";
|
|
21438
|
-
import { basename as basename7, dirname as
|
|
21657
|
+
import { basename as basename7, dirname as dirname19, isAbsolute as isAbsolute6, join as join28 } from "node:path";
|
|
21439
21658
|
init_state();
|
|
21440
21659
|
var ENGINE_LABEL2 = "ai.sleds.engine";
|
|
21441
21660
|
var ENGINE_INSTALL_USAGE2 = `usage: sleds engine install [engine flags] | sleds engine uninstall [--name <n>] [--org <slug>]
|
|
@@ -21443,7 +21662,7 @@ ${ENGINE_USAGE}`;
|
|
|
21443
21662
|
function stableArgv2(argv, realpath = realpathSync2, home) {
|
|
21444
21663
|
const link = sledsLink(home);
|
|
21445
21664
|
return argv.map((a) => {
|
|
21446
|
-
if (!
|
|
21665
|
+
if (!isAbsolute6(a) || a === link)
|
|
21447
21666
|
return a;
|
|
21448
21667
|
try {
|
|
21449
21668
|
return realpath(a);
|
|
@@ -21456,13 +21675,13 @@ function engineLabel2(name, org, seat) {
|
|
|
21456
21675
|
return [ENGINE_LABEL2, org, seat?.trim(), name].filter((p) => Boolean(p)).map((p, i) => i === 0 ? p : engineSlug(p)).join(".");
|
|
21457
21676
|
}
|
|
21458
21677
|
function enginePlistPath2(home, name, org, seat) {
|
|
21459
|
-
return
|
|
21678
|
+
return join28(home, "Library", "LaunchAgents", `${engineLabel2(name, org, seat)}.plist`);
|
|
21460
21679
|
}
|
|
21461
21680
|
function engineLogPath2(stateDir, name) {
|
|
21462
|
-
return
|
|
21681
|
+
return join28(stateDir, `${engineSlug(name)}.log`);
|
|
21463
21682
|
}
|
|
21464
21683
|
function engineEventsPath2(stateDir, name) {
|
|
21465
|
-
return
|
|
21684
|
+
return join28(stateDir, `${engineSlug(name)}.events.jsonl`);
|
|
21466
21685
|
}
|
|
21467
21686
|
var xmlEscape5 = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
21468
21687
|
function buildEnginePlist2(o) {
|
|
@@ -21559,7 +21778,7 @@ function readEngines2(dir, suffix, manager, parse) {
|
|
|
21559
21778
|
}
|
|
21560
21779
|
const out = [];
|
|
21561
21780
|
for (const name of names.filter((n) => n.startsWith(`${ENGINE_LABEL2}.`) && n.endsWith(suffix))) {
|
|
21562
|
-
const path =
|
|
21781
|
+
const path = join28(dir, name);
|
|
21563
21782
|
let parsed;
|
|
21564
21783
|
try {
|
|
21565
21784
|
parsed = parse(readFileSync21(path, "utf8"), name);
|
|
@@ -21579,7 +21798,7 @@ function readEngines2(dir, suffix, manager, parse) {
|
|
|
21579
21798
|
}
|
|
21580
21799
|
function installedEngines2(home) {
|
|
21581
21800
|
return [
|
|
21582
|
-
...readEngines2(
|
|
21801
|
+
...readEngines2(join28(home, "Library", "LaunchAgents"), ".plist", "launchd", parseEnginePlist2),
|
|
21583
21802
|
...readEngines2(engineUnitDir(home), ".service", "systemd", (text, file) => {
|
|
21584
21803
|
const parsed = parseEngineUnit(text);
|
|
21585
21804
|
return parsed && { label: basename7(file, ".service"), ...parsed };
|
|
@@ -21617,7 +21836,7 @@ async function ensureReposDir(o) {
|
|
|
21617
21836
|
return false;
|
|
21618
21837
|
}
|
|
21619
21838
|
const exists = o.exists ?? existsSync22;
|
|
21620
|
-
const missing = dirs.filter((d) => !exists(/^~(\/|$)/.test(d) ?
|
|
21839
|
+
const missing = dirs.filter((d) => !exists(/^~(\/|$)/.test(d) ? join28(o.home, d.slice(1)) : d));
|
|
21621
21840
|
if (missing.length) {
|
|
21622
21841
|
error(`Not a folder on this machine: ${missing.join(", ")}. ${REPOS_DIR_NEEDED}`);
|
|
21623
21842
|
return false;
|
|
@@ -21673,7 +21892,7 @@ function engineInstall2(o) {
|
|
|
21673
21892
|
if (platform === "linux")
|
|
21674
21893
|
return installUnit2({ o, parsed, label, sledsArgv, env: agentEnv, logPath, exec });
|
|
21675
21894
|
const plist = enginePlistPath2(o.home, parsed.name, parsed.org, seat);
|
|
21676
|
-
mkdirSync22(
|
|
21895
|
+
mkdirSync22(dirname19(plist), { recursive: true });
|
|
21677
21896
|
if (existsSync22(plist))
|
|
21678
21897
|
exec("launchctl", ["unload", plist]);
|
|
21679
21898
|
for (const other of installedEngines2(o.home)) {
|
|
@@ -21715,7 +21934,7 @@ function installUnit2(a) {
|
|
|
21715
21934
|
const unit = engineUnitPath(o.home, label);
|
|
21716
21935
|
const unitName = basename7(unit);
|
|
21717
21936
|
const systemctl = (...args) => exec("systemctl", ["--user", ...args]);
|
|
21718
|
-
mkdirSync22(
|
|
21937
|
+
mkdirSync22(dirname19(unit), { recursive: true });
|
|
21719
21938
|
if (existsSync22(unit))
|
|
21720
21939
|
systemctl("stop", unitName);
|
|
21721
21940
|
for (const other of installedEngines2(o.home)) {
|
|
@@ -22740,9 +22959,9 @@ init_meter();
|
|
|
22740
22959
|
// src/owed.ts
|
|
22741
22960
|
init_config();
|
|
22742
22961
|
import { existsSync as existsSync26, mkdirSync as mkdirSync23, readFileSync as readFileSync25, renameSync as renameSync11, writeFileSync as writeFileSync22 } from "node:fs";
|
|
22743
|
-
import { dirname as
|
|
22744
|
-
var owedPath = (home) =>
|
|
22745
|
-
var sessionPath = (home) =>
|
|
22962
|
+
import { dirname as dirname20, join as join29 } from "node:path";
|
|
22963
|
+
var owedPath = (home) => join29(configDir(home), "owed.json");
|
|
22964
|
+
var sessionPath = (home) => join29(configDir(home), "session.json");
|
|
22746
22965
|
var OWED_TTL_MS = 3 * 24 * 60 * 60000;
|
|
22747
22966
|
var str14 = (v) => typeof v === "string" ? v : undefined;
|
|
22748
22967
|
function sourceKey(s) {
|
|
@@ -22766,7 +22985,7 @@ var readJson = (p) => {
|
|
|
22766
22985
|
}
|
|
22767
22986
|
};
|
|
22768
22987
|
var writeJson = (p, v) => {
|
|
22769
|
-
mkdirSync23(
|
|
22988
|
+
mkdirSync23(dirname20(p), { recursive: true, mode: 448 });
|
|
22770
22989
|
const tmp = `${p}.${process.pid}.tmp`;
|
|
22771
22990
|
writeFileSync22(tmp, `${JSON.stringify(v, null, 2)}
|
|
22772
22991
|
`, { mode: 384 });
|
|
@@ -22900,7 +23119,7 @@ function contextFor(deps) {
|
|
|
22900
23119
|
...src,
|
|
22901
23120
|
fetchFn: deps.fetchFn,
|
|
22902
23121
|
timeoutMs: deps.timeoutMs,
|
|
22903
|
-
version: "0.1.
|
|
23122
|
+
version: "0.1.50"
|
|
22904
23123
|
}), deps.home, now) : null;
|
|
22905
23124
|
return {
|
|
22906
23125
|
channel: "code",
|
|
@@ -24029,7 +24248,7 @@ init_meter();
|
|
|
24029
24248
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
24030
24249
|
import { existsSync as existsSync28, mkdirSync as mkdirSync25, readFileSync as readFileSync27, rmSync as rmSync17, writeFileSync as writeFileSync24 } from "node:fs";
|
|
24031
24250
|
import { hostname as hostname11 } from "node:os";
|
|
24032
|
-
import { dirname as
|
|
24251
|
+
import { dirname as dirname21 } from "node:path";
|
|
24033
24252
|
var defaultWhich3 = (cmd) => {
|
|
24034
24253
|
const path = process.env.PATH ?? "";
|
|
24035
24254
|
for (const dir of path.split(":").filter(Boolean)) {
|
|
@@ -24067,7 +24286,7 @@ var musherInstall = (o) => {
|
|
|
24067
24286
|
const plist = musherPlistPath(o.home, env);
|
|
24068
24287
|
const label = musherLabel(env);
|
|
24069
24288
|
const dir = configDir(o.home, env);
|
|
24070
|
-
mkdirSync25(
|
|
24289
|
+
mkdirSync25(dirname21(plist), { recursive: true });
|
|
24071
24290
|
mkdirSync25(dir, { recursive: true, mode: 448 });
|
|
24072
24291
|
const execPath = o.sledsArgv[0] ?? process.execPath;
|
|
24073
24292
|
const agentEnv = {
|
|
@@ -24467,7 +24686,7 @@ var orgCmd = (o) => {
|
|
|
24467
24686
|
init_src();
|
|
24468
24687
|
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
24469
24688
|
import { writeFileSync as writeFileSync25 } from "node:fs";
|
|
24470
|
-
import { join as
|
|
24689
|
+
import { join as join30 } from "node:path";
|
|
24471
24690
|
function packFileName(key) {
|
|
24472
24691
|
return `pack-${slugify(key, 80) || "item"}.md`;
|
|
24473
24692
|
}
|
|
@@ -24495,7 +24714,7 @@ var packCmd = async (o) => {
|
|
|
24495
24714
|
log(r.text);
|
|
24496
24715
|
return 0;
|
|
24497
24716
|
}
|
|
24498
|
-
const path =
|
|
24717
|
+
const path = join30(o.cwd ?? process.cwd(), packFileName(key));
|
|
24499
24718
|
(o.write ?? ((p, t) => writeFileSync25(p, t.endsWith(`
|
|
24500
24719
|
`) ? t : `${t}
|
|
24501
24720
|
`)))(path, r.text);
|
|
@@ -24505,7 +24724,7 @@ var packCmd = async (o) => {
|
|
|
24505
24724
|
|
|
24506
24725
|
// src/commands/permissionEvent.ts
|
|
24507
24726
|
import { chmodSync as chmodSync7, mkdirSync as mkdirSync26, readFileSync as readFileSync28, renameSync as renameSync12, rmSync as rmSync19, writeFileSync as writeFileSync26 } from "node:fs";
|
|
24508
|
-
import { dirname as
|
|
24727
|
+
import { dirname as dirname22 } from "node:path";
|
|
24509
24728
|
var isObject13 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
24510
24729
|
var messageOf = (text) => {
|
|
24511
24730
|
try {
|
|
@@ -24529,7 +24748,7 @@ var permissionEvent = async (o) => {
|
|
|
24529
24748
|
if (!isToolPermission2(message))
|
|
24530
24749
|
return 0;
|
|
24531
24750
|
const mark = { message, at: (o.now ?? Date.now)() };
|
|
24532
|
-
mkdirSync26(
|
|
24751
|
+
mkdirSync26(dirname22(o.mark), { recursive: true, mode: 448 });
|
|
24533
24752
|
const tmp = `${o.mark}.${process.pid}.tmp`;
|
|
24534
24753
|
writeFileSync26(tmp, `${JSON.stringify(mark)}
|
|
24535
24754
|
`, { mode: 384 });
|
|
@@ -25569,16 +25788,86 @@ var seatEvent = async (o) => {
|
|
|
25569
25788
|
return 0;
|
|
25570
25789
|
};
|
|
25571
25790
|
|
|
25791
|
+
// src/commands/seatRevoke.ts
|
|
25792
|
+
var SEAT_REVOKE_USAGE = "usage: sleds seat revoke [--box <name>] [--yes] [--json]";
|
|
25793
|
+
var LAG = "a proxy may honour it for up to 60 s more";
|
|
25794
|
+
function parseSeatRevokeArgs(argv) {
|
|
25795
|
+
let box = null;
|
|
25796
|
+
let yes = false;
|
|
25797
|
+
let json = false;
|
|
25798
|
+
for (let i = 0;i < argv.length; i++) {
|
|
25799
|
+
const a = argv[i];
|
|
25800
|
+
if (a === "--json")
|
|
25801
|
+
json = true;
|
|
25802
|
+
else if (a === "--yes" || a === "-y")
|
|
25803
|
+
yes = true;
|
|
25804
|
+
else if (a === "--box") {
|
|
25805
|
+
const value = argv[i + 1]?.trim();
|
|
25806
|
+
if (!value || value.startsWith("--"))
|
|
25807
|
+
return { error: "--box needs the box's name" };
|
|
25808
|
+
box = value.replace(/^box:/, "");
|
|
25809
|
+
i++;
|
|
25810
|
+
} else
|
|
25811
|
+
return { error: `unknown argument ${a}` };
|
|
25812
|
+
}
|
|
25813
|
+
return { box, yes, json };
|
|
25814
|
+
}
|
|
25815
|
+
function why(j, status) {
|
|
25816
|
+
if (typeof j?.reason === "string")
|
|
25817
|
+
return j.reason;
|
|
25818
|
+
if (typeof j?.error === "string")
|
|
25819
|
+
return j.error;
|
|
25820
|
+
const e = j?.error;
|
|
25821
|
+
return typeof e?.message === "string" ? e.message : `HTTP ${status}`;
|
|
25822
|
+
}
|
|
25823
|
+
async function seatRevokeCmd(o) {
|
|
25824
|
+
const log = o.log ?? console.log;
|
|
25825
|
+
const error = o.error ?? console.error;
|
|
25826
|
+
const a = parseSeatRevokeArgs(o.argv);
|
|
25827
|
+
if ("error" in a) {
|
|
25828
|
+
error(a.error);
|
|
25829
|
+
error(SEAT_REVOKE_USAGE);
|
|
25830
|
+
return 2;
|
|
25831
|
+
}
|
|
25832
|
+
if (!a.box && !a.yes) {
|
|
25833
|
+
error("this revokes this machine's own seat — SLEDS stops here until `sleds init` again.");
|
|
25834
|
+
error("Add --yes to go ahead, or --box <name> to revoke one of your boxes instead.");
|
|
25835
|
+
return 2;
|
|
25836
|
+
}
|
|
25837
|
+
const client = engineClient({ home: o.home, ...o.client ? { client: o.client } : {} });
|
|
25838
|
+
if ("error" in client) {
|
|
25839
|
+
error(client.error);
|
|
25840
|
+
return 1;
|
|
25841
|
+
}
|
|
25842
|
+
const r = await client.postFull("/proxy/seat/revoke", a.box ? { box: a.box } : {});
|
|
25843
|
+
if (!r) {
|
|
25844
|
+
error("SLEDS unreachable — nothing revoked");
|
|
25845
|
+
return 1;
|
|
25846
|
+
}
|
|
25847
|
+
const ok = r.status < 300 && r.json?.ok !== false;
|
|
25848
|
+
if (a.json) {
|
|
25849
|
+
log(JSON.stringify({ v: 1, ...r.json ?? { ok: false, reason: `HTTP ${r.status}` } }));
|
|
25850
|
+
return ok ? 0 : 1;
|
|
25851
|
+
}
|
|
25852
|
+
if (!ok) {
|
|
25853
|
+
error(clean(`nothing revoked — ${why(r.json, r.status)}`));
|
|
25854
|
+
return 1;
|
|
25855
|
+
}
|
|
25856
|
+
const label = typeof r.json?.label === "string" ? r.json.label : a.box ? `box:${a.box}` : "";
|
|
25857
|
+
log(clean(a.box ? `${label} revoked — its token is dead; ${LAG}` : `this machine's seat${label ? ` (${label})` : ""} revoked — its token is dead; ${LAG}. Run \`sleds init\` with a new one to use SLEDS here again`));
|
|
25858
|
+
return 0;
|
|
25859
|
+
}
|
|
25860
|
+
|
|
25572
25861
|
// src/commands/seatSync.ts
|
|
25573
25862
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
25574
25863
|
import { existsSync as existsSync30, mkdirSync as mkdirSync27, readFileSync as readFileSync30, readdirSync as readdirSync7, rmSync as rmSync21, writeFileSync as writeFileSync27 } from "node:fs";
|
|
25575
25864
|
import { platform as platform2 } from "node:os";
|
|
25576
|
-
import { dirname as
|
|
25865
|
+
import { dirname as dirname23, join as join32 } from "node:path";
|
|
25577
25866
|
|
|
25578
25867
|
// src/cookieDb.ts
|
|
25579
25868
|
import { copyFileSync as copyFileSync3, rmSync as rmSync20 } from "node:fs";
|
|
25580
25869
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
25581
|
-
import { join as
|
|
25870
|
+
import { join as join31 } from "node:path";
|
|
25582
25871
|
var QUERY = "SELECT name, hex(encrypted_value) AS ev FROM cookies WHERE host_key LIKE '%claude.ai%'";
|
|
25583
25872
|
var isBun = () => typeof globalThis.Bun !== "undefined";
|
|
25584
25873
|
async function queryRows(dbPath) {
|
|
@@ -25607,7 +25896,7 @@ function nodeSqlite() {
|
|
|
25607
25896
|
return mod;
|
|
25608
25897
|
}
|
|
25609
25898
|
async function readCookieRows(dbPath) {
|
|
25610
|
-
const copy =
|
|
25899
|
+
const copy = join31(tmpdir2(), `sleds-cookies-${process.pid}-${Date.now()}.sqlite`);
|
|
25611
25900
|
copyFileSync3(dbPath, copy);
|
|
25612
25901
|
try {
|
|
25613
25902
|
const rows = await queryRows(copy);
|
|
@@ -25900,7 +26189,7 @@ function findFile(root, name) {
|
|
|
25900
26189
|
continue;
|
|
25901
26190
|
}
|
|
25902
26191
|
for (const e of entries) {
|
|
25903
|
-
const p =
|
|
26192
|
+
const p = join32(dir, e.name);
|
|
25904
26193
|
if (e.isDirectory())
|
|
25905
26194
|
stack.push(p);
|
|
25906
26195
|
else if (e.name === name)
|
|
@@ -25911,7 +26200,7 @@ function findFile(root, name) {
|
|
|
25911
26200
|
}
|
|
25912
26201
|
function findCookieDb(home, source) {
|
|
25913
26202
|
const b = BROWSERS[source.browser];
|
|
25914
|
-
const root =
|
|
26203
|
+
const root = join32(home, APP_SUPPORT, b.appDir);
|
|
25915
26204
|
if (!existsSync30(root))
|
|
25916
26205
|
throw new Error(`no ${source.browser} data at ${root} (is it installed?)`);
|
|
25917
26206
|
if (!b.profiled) {
|
|
@@ -25920,7 +26209,7 @@ function findCookieDb(home, source) {
|
|
|
25920
26209
|
throw new Error(`no cookie store under ${root}`);
|
|
25921
26210
|
return db;
|
|
25922
26211
|
}
|
|
25923
|
-
const localStatePath =
|
|
26212
|
+
const localStatePath = join32(root, "Local State");
|
|
25924
26213
|
const localState = existsSync30(localStatePath) ? readFileSync30(localStatePath, "utf8") : null;
|
|
25925
26214
|
const wanted = source.profile ?? "Default";
|
|
25926
26215
|
const { dir, ambiguous } = resolveProfileDir(localState, wanted);
|
|
@@ -25928,7 +26217,7 @@ function findCookieDb(home, source) {
|
|
|
25928
26217
|
throw new Error(`"${wanted}" names ${ambiguous.length} ${source.browser} profiles (${ambiguous.join(", ")}) — pass the directory or the account email instead`);
|
|
25929
26218
|
if (!dir)
|
|
25930
26219
|
throw new Error(`no ${source.browser} profile named "${wanted}" (check chrome://version)`);
|
|
25931
|
-
const db = cookieDbCandidates(
|
|
26220
|
+
const db = cookieDbCandidates(join32(root, dir)).find((p) => existsSync30(p));
|
|
25932
26221
|
if (!db)
|
|
25933
26222
|
throw new Error(`profile "${dir}" has no cookie store yet (open claude.ai in it once)`);
|
|
25934
26223
|
return db;
|
|
@@ -25972,7 +26261,7 @@ function fetchSeatUsage(jar, org, now, run) {
|
|
|
25972
26261
|
}
|
|
25973
26262
|
function launchAgentPlist(argv, home, source) {
|
|
25974
26263
|
const label = launchLabel(source);
|
|
25975
|
-
const log =
|
|
26264
|
+
const log = join32(home, ".config", "sleds", `${label.slice("ai.sleds.".length)}.log`);
|
|
25976
26265
|
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
25977
26266
|
const args = [...argv, "seat-sync", ...sourceArgs(source)].map((a) => ` <string>${esc(a)}</string>`).join(`
|
|
25978
26267
|
`);
|
|
@@ -25994,20 +26283,20 @@ ${args}
|
|
|
25994
26283
|
`;
|
|
25995
26284
|
}
|
|
25996
26285
|
function plistPath2(home, source) {
|
|
25997
|
-
return
|
|
26286
|
+
return join32(home, "Library", "LaunchAgents", `${launchLabel(source)}.plist`);
|
|
25998
26287
|
}
|
|
25999
26288
|
function install(home, argv, source, log, launchctl) {
|
|
26000
26289
|
if (!argv[0]) {
|
|
26001
26290
|
log("cannot resolve the sleds command to install the timer");
|
|
26002
26291
|
return 1;
|
|
26003
26292
|
}
|
|
26004
|
-
const dir =
|
|
26293
|
+
const dir = join32(home, "Library", "LaunchAgents");
|
|
26005
26294
|
mkdirSync27(dir, { recursive: true });
|
|
26006
26295
|
const path = plistPath2(home, source);
|
|
26007
26296
|
const tokenPath = seatTokenPath(home, source);
|
|
26008
26297
|
rmSync21(tokenPath, { force: true });
|
|
26009
26298
|
if (source.token) {
|
|
26010
|
-
mkdirSync27(
|
|
26299
|
+
mkdirSync27(dirname23(tokenPath), { recursive: true, mode: 448 });
|
|
26011
26300
|
writeFileSync27(tokenPath, `${source.token}
|
|
26012
26301
|
`, { mode: 384 });
|
|
26013
26302
|
}
|
|
@@ -26184,8 +26473,8 @@ var sessionEvent = async (o) => {
|
|
|
26184
26473
|
|
|
26185
26474
|
// src/commands/specEvent.ts
|
|
26186
26475
|
init_meter();
|
|
26187
|
-
import { readFileSync as readFileSync31, statSync as
|
|
26188
|
-
import { basename as basename8, isAbsolute as
|
|
26476
|
+
import { readFileSync as readFileSync31, statSync as statSync7 } from "node:fs";
|
|
26477
|
+
import { basename as basename8, isAbsolute as isAbsolute7, relative as relative2 } from "node:path";
|
|
26189
26478
|
var HOOK_STDIN_TIMEOUT_MS3 = 1000;
|
|
26190
26479
|
var ESTIMATE_TIMEOUT_MS = 4000;
|
|
26191
26480
|
var MIN_SPEC_CHARS = 200;
|
|
@@ -26229,7 +26518,7 @@ function parseHookInput(raw) {
|
|
|
26229
26518
|
return { toolName, filePath, cwd };
|
|
26230
26519
|
}
|
|
26231
26520
|
function projectKey(filePath, cwd) {
|
|
26232
|
-
if (cwd &&
|
|
26521
|
+
if (cwd && isAbsolute7(filePath) && isAbsolute7(cwd)) {
|
|
26233
26522
|
const rel = relative2(cwd, filePath);
|
|
26234
26523
|
if (rel && !rel.startsWith(".."))
|
|
26235
26524
|
return rel;
|
|
@@ -26238,7 +26527,7 @@ function projectKey(filePath, cwd) {
|
|
|
26238
26527
|
}
|
|
26239
26528
|
function readFileOrNull(path) {
|
|
26240
26529
|
try {
|
|
26241
|
-
if (
|
|
26530
|
+
if (statSync7(path).size > 2000000)
|
|
26242
26531
|
return null;
|
|
26243
26532
|
return readFileSync31(path, "utf8");
|
|
26244
26533
|
} catch {
|
|
@@ -26850,7 +27139,7 @@ var hasEitherKey = (settings) => {
|
|
|
26850
27139
|
// src/commands/update.ts
|
|
26851
27140
|
init_server();
|
|
26852
27141
|
import { existsSync as existsSync34 } from "node:fs";
|
|
26853
|
-
import { homedir as
|
|
27142
|
+
import { homedir as homedir8, userInfo as userInfo4 } from "node:os";
|
|
26854
27143
|
import { basename as basename9 } from "node:path";
|
|
26855
27144
|
init_config();
|
|
26856
27145
|
init_state();
|
|
@@ -26916,7 +27205,7 @@ var realPidAlive4 = (pid) => {
|
|
|
26916
27205
|
};
|
|
26917
27206
|
function machineClient(home, env) {
|
|
26918
27207
|
const src = meterSource(home, undefined, { env });
|
|
26919
|
-
return src ? fetchClient({ ...src, version: "0.1.
|
|
27208
|
+
return src ? fetchClient({ ...src, version: "0.1.50" }) : null;
|
|
26920
27209
|
}
|
|
26921
27210
|
async function noteAnswer2(home, a, now) {
|
|
26922
27211
|
try {
|
|
@@ -26938,7 +27227,7 @@ function busyLine(busy) {
|
|
|
26938
27227
|
return `${n} session${n === 1 ? " is" : "s are"} running on ${on} — sleds update --now releases ${n === 1 ? "it" : "them"}`;
|
|
26939
27228
|
}
|
|
26940
27229
|
async function updateCmd(o) {
|
|
26941
|
-
const home = o.home ??
|
|
27230
|
+
const home = o.home ?? homedir8();
|
|
26942
27231
|
const env = o.env ?? process.env;
|
|
26943
27232
|
const log = o.log ?? console.log;
|
|
26944
27233
|
const error = o.error ?? console.error;
|
|
@@ -26963,7 +27252,7 @@ async function updateCmd(o) {
|
|
|
26963
27252
|
const r = await rollBack({
|
|
26964
27253
|
home,
|
|
26965
27254
|
restoreState: false,
|
|
26966
|
-
why: `asked by ${o.user ??
|
|
27255
|
+
why: `asked by ${o.user ?? userInfo4().username}`,
|
|
26967
27256
|
now: now(),
|
|
26968
27257
|
platform
|
|
26969
27258
|
});
|
|
@@ -27242,12 +27531,12 @@ var webhooksCmd = async (o) => {
|
|
|
27242
27531
|
// src/config.ts
|
|
27243
27532
|
init_settings();
|
|
27244
27533
|
import { chmodSync as chmodSync8, existsSync as existsSync35, mkdirSync as mkdirSync28, readFileSync as readFileSync33, renameSync as renameSync13, writeFileSync as writeFileSync28 } from "node:fs";
|
|
27245
|
-
import { join as
|
|
27534
|
+
import { join as join33, resolve as resolve11 } from "node:path";
|
|
27246
27535
|
var configDir2 = (home, env = process.env) => {
|
|
27247
27536
|
const o = env.SLEDS_HOME?.trim();
|
|
27248
|
-
return o ? resolve11(home, o) :
|
|
27537
|
+
return o ? resolve11(home, o) : join33(home, ".config", "sleds");
|
|
27249
27538
|
};
|
|
27250
|
-
var configPath2 = (home) =>
|
|
27539
|
+
var configPath2 = (home) => join33(configDir2(home), "config.json");
|
|
27251
27540
|
var isObject17 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
27252
27541
|
var optString2 = (v) => typeof v === "string" ? v : undefined;
|
|
27253
27542
|
var parsePriorEnv2 = (v) => {
|
|
@@ -27424,10 +27713,10 @@ function runnerFor3(name, exec = defaultExec, o = {}) {
|
|
|
27424
27713
|
}
|
|
27425
27714
|
|
|
27426
27715
|
// src/runtime.ts
|
|
27427
|
-
import { homedir as
|
|
27428
|
-
import { join as
|
|
27716
|
+
import { homedir as homedir9 } from "node:os";
|
|
27717
|
+
import { join as join34, win32 as win323 } from "node:path";
|
|
27429
27718
|
var isCompiled2 = (argv1 = process.argv[1]) => Boolean(argv1 && (argv1.startsWith("/$bunfs/") || argv1.startsWith("B:\\~BUN\\")));
|
|
27430
|
-
var sledsLink2 = (home =
|
|
27719
|
+
var sledsLink2 = (home = homedir9(), platform = process.platform) => platform === "win32" ? win323.join(process.env.LOCALAPPDATA ?? win323.join(home, "AppData", "Local"), "sleds", "bin", "sleds.exe") : join34(home, ".sleds", "bin", "sleds");
|
|
27431
27720
|
|
|
27432
27721
|
// src/schedule.ts
|
|
27433
27722
|
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
@@ -27439,7 +27728,7 @@ var defaultExec5 = (cmd, args) => {
|
|
|
27439
27728
|
};
|
|
27440
27729
|
|
|
27441
27730
|
// src/settings.ts
|
|
27442
|
-
import { dirname as
|
|
27731
|
+
import { dirname as dirname24, join as join35, resolve as resolve12 } from "node:path";
|
|
27443
27732
|
var withSeatEnv2 = (command, home, env = process.env, org) => {
|
|
27444
27733
|
const parts = [];
|
|
27445
27734
|
const sh = env.SLEDS_HOME?.trim();
|
|
@@ -27625,10 +27914,16 @@ commands:
|
|
|
27625
27914
|
needs (gh signed in, git, tmux, its launchd agent, a repos dir). --json: {v, checks}.
|
|
27626
27915
|
--sandbox: also run one short sandboxed Claude Code session (haiku) and prove it
|
|
27627
27916
|
cannot read the SLEDS config dir or reach a host off the allowlist.
|
|
27917
|
+
--lent-by <lender>: check this account as a lent engine's before the install \u2014
|
|
27918
|
+
both homes 700 (an installed engine with --lent-by is checked without it).
|
|
27628
27919
|
meter Show the pipeline: built today, queued with its band, delivered overnight.
|
|
27629
27920
|
mcp Run the MCP server on stdio: tools usage, estimate, overnight, jobs.
|
|
27630
27921
|
Register with \`claude mcp add sleds -- sleds mcp\` (Cowork sees the same server).
|
|
27631
|
-
seat
|
|
27922
|
+
seat revoke [--box <name>] [--yes] [--json] Kill a seat's token in one step. --box revokes
|
|
27923
|
+
your own box:<name> seat, from any terminal; without it this machine's own seat
|
|
27924
|
+
is revoked (--yes, since SLEDS stops here until \`sleds init\` again). A proxy may
|
|
27925
|
+
honour the token for up to 60 s more. --json: {v, ok, seatId, label} or {v, ok, reason}
|
|
27926
|
+
seat-sync Read the seat's subscription usage (weekly/5h limits, per-model, credits) from a
|
|
27632
27927
|
claude.ai session and post it to the proxy. macOS.
|
|
27633
27928
|
--browser <claude|chrome|brave|edge|chromium|\u2026> which cookie store (default claude)
|
|
27634
27929
|
--profile <name> browser profile dir ("Profile 1") or its display name/email
|
|
@@ -27681,6 +27976,7 @@ var parseArgs = (argv) => {
|
|
|
27681
27976
|
}
|
|
27682
27977
|
return { cmd, flags };
|
|
27683
27978
|
};
|
|
27979
|
+
var lentByOf = (v) => typeof v === "string" && v.trim() ? { lentBy: v.trim() } : {};
|
|
27684
27980
|
var HELP = new Set(["help", "--help", "-h"]);
|
|
27685
27981
|
var wantsHelp = (argv) => {
|
|
27686
27982
|
if (HELP.has(argv[0] ?? "--help"))
|
|
@@ -27729,12 +28025,12 @@ var sledsArgv = (execPath = process.execPath, script = process.argv[1], realpath
|
|
|
27729
28025
|
return stableArgv2(script ? [execPath, script] : [execPath], realpath, o.home);
|
|
27730
28026
|
};
|
|
27731
28027
|
var shellQuote = (s) => /^[\w./-]+$/.test(s) ? s : `'${s.replace(/'/g, "'\\''")}'`;
|
|
27732
|
-
var statusLineCommand = (argv, home =
|
|
27733
|
-
var seatEventCommand = (argv, home =
|
|
27734
|
-
var promptEventCommand = (argv, home =
|
|
27735
|
-
var sessionEventCommand = (argv, home =
|
|
27736
|
-
var stopEventCommand = (argv, home =
|
|
27737
|
-
var specEventCommand = (argv, home =
|
|
28028
|
+
var statusLineCommand = (argv, home = homedir10()) => withSeatEnv2([...argv, "statusline"].map(shellQuote).join(" "), home);
|
|
28029
|
+
var seatEventCommand = (argv, home = homedir10()) => withSeatEnv2([...argv, "seat-event"].map(shellQuote).join(" "), home);
|
|
28030
|
+
var promptEventCommand = (argv, home = homedir10()) => withSeatEnv2([...argv, "prompt-event"].map(shellQuote).join(" "), home);
|
|
28031
|
+
var sessionEventCommand = (argv, home = homedir10()) => withSeatEnv2([...argv, "session-event"].map(shellQuote).join(" "), home);
|
|
28032
|
+
var stopEventCommand = (argv, home = homedir10()) => withSeatEnv2([...argv, "stop-event"].map(shellQuote).join(" "), home);
|
|
28033
|
+
var specEventCommand = (argv, home = homedir10()) => withSeatEnv2([...argv, "spec-event"].map(shellQuote).join(" "), home);
|
|
27738
28034
|
var mcpFlag = (flags) => flags["no-mcp"] === true ? false : flags.mcp === true ? true : undefined;
|
|
27739
28035
|
var main = async (argv) => {
|
|
27740
28036
|
const { cmd, flags } = parseArgs(argv);
|
|
@@ -27742,7 +28038,7 @@ var main = async (argv) => {
|
|
|
27742
28038
|
console.log(commandUsage(cmd));
|
|
27743
28039
|
return 0;
|
|
27744
28040
|
}
|
|
27745
|
-
const home =
|
|
28041
|
+
const home = homedir10();
|
|
27746
28042
|
const scheduler = {
|
|
27747
28043
|
platform: platform3(),
|
|
27748
28044
|
home,
|
|
@@ -27754,7 +28050,7 @@ var main = async (argv) => {
|
|
|
27754
28050
|
now: Date.now(),
|
|
27755
28051
|
stderr: (line) => console.error(line),
|
|
27756
28052
|
isTTY: !!process.stderr.isTTY,
|
|
27757
|
-
version: "0.1.
|
|
28053
|
+
version: "0.1.50"
|
|
27758
28054
|
});
|
|
27759
28055
|
switch (cmd) {
|
|
27760
28056
|
case "update":
|
|
@@ -27775,6 +28071,11 @@ var main = async (argv) => {
|
|
|
27775
28071
|
return sledCmd({ home, argv: argv.slice(1) });
|
|
27776
28072
|
case "reopen":
|
|
27777
28073
|
return reopenCmd({ home, argv: argv.slice(1) });
|
|
28074
|
+
case "seat":
|
|
28075
|
+
if (argv[1] === "revoke")
|
|
28076
|
+
return seatRevokeCmd({ home, argv: argv.slice(2) });
|
|
28077
|
+
console.error(SEAT_REVOKE_USAGE);
|
|
28078
|
+
return 2;
|
|
27778
28079
|
case "engine":
|
|
27779
28080
|
case "route": {
|
|
27780
28081
|
if (cmd === "engine" && argv[1] === "status")
|
|
@@ -27957,7 +28258,8 @@ var main = async (argv) => {
|
|
|
27957
28258
|
return doctor({
|
|
27958
28259
|
home,
|
|
27959
28260
|
json: argv.slice(1).includes("--json"),
|
|
27960
|
-
sandbox: argv.slice(1).includes("--sandbox")
|
|
28261
|
+
sandbox: argv.slice(1).includes("--sandbox"),
|
|
28262
|
+
...lentByOf(parseArgs(argv).flags["lent-by"])
|
|
27961
28263
|
});
|
|
27962
28264
|
case "status":
|
|
27963
28265
|
return status3({ home });
|
|
@@ -27981,7 +28283,7 @@ ${renderHelpText(argv[1])}`);
|
|
|
27981
28283
|
case "version":
|
|
27982
28284
|
case "--version":
|
|
27983
28285
|
case "-v":
|
|
27984
|
-
console.log("sleds 0.1.
|
|
28286
|
+
console.log("sleds 0.1.50");
|
|
27985
28287
|
return 0;
|
|
27986
28288
|
default:
|
|
27987
28289
|
console.error(`unknown command: ${cmd}
|