@sleds/cli 0.1.14 → 0.1.15
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 +58 -28
- package/package.json +1 -1
package/dist/sleds.mjs
CHANGED
|
@@ -24,7 +24,7 @@ import { dirname, join, resolve } from "node:path";
|
|
|
24
24
|
var BASE_URL_KEY = "ANTHROPIC_BASE_URL", AUTH_TOKEN_KEY = "ANTHROPIC_AUTH_TOKEN", claudeDir = (home, env = process.env) => {
|
|
25
25
|
const o = env.CLAUDE_CONFIG_DIR?.trim();
|
|
26
26
|
return o ? resolve(home, o) : join(home, ".claude");
|
|
27
|
-
}, hasHomeOverride = (env = process.env) => Boolean(env.SLEDS_HOME?.trim() || env.CLAUDE_CONFIG_DIR?.trim()), settingsPath = (home) => join(claudeDir(home), "settings.json"), sledsCommand = (sub, home, env = process.env) => {
|
|
27
|
+
}, hasHomeOverride = (env = process.env) => Boolean(env.SLEDS_HOME?.trim() || env.CLAUDE_CONFIG_DIR?.trim()), settingsPath = (home) => join(claudeDir(home), "settings.json"), sledsCommand = (sub, home, env = process.env) => withSeatEnv(`sleds ${sub}`, home, env), withSeatEnv = (command, home, env = process.env) => {
|
|
28
28
|
const parts = [];
|
|
29
29
|
const sh = env.SLEDS_HOME?.trim();
|
|
30
30
|
const cc = env.CLAUDE_CONFIG_DIR?.trim();
|
|
@@ -32,7 +32,7 @@ var BASE_URL_KEY = "ANTHROPIC_BASE_URL", AUTH_TOKEN_KEY = "ANTHROPIC_AUTH_TOKEN"
|
|
|
32
32
|
parts.push(`SLEDS_HOME=${shellWord(resolve(home, sh))}`);
|
|
33
33
|
if (cc)
|
|
34
34
|
parts.push(`CLAUDE_CONFIG_DIR=${shellWord(resolve(home, cc))}`);
|
|
35
|
-
parts.push(
|
|
35
|
+
parts.push(command);
|
|
36
36
|
return parts.join(" ");
|
|
37
37
|
}, sledsCommandsIn = (settings) => {
|
|
38
38
|
const out = [];
|
|
@@ -531,7 +531,7 @@ __export(exports_seat, {
|
|
|
531
531
|
writeSeatState: () => writeSeatState2
|
|
532
532
|
});
|
|
533
533
|
import { existsSync as existsSync13, mkdirSync as mkdirSync10, readFileSync as readFileSync10, renameSync as renameSync5, writeFileSync as writeFileSync10 } from "node:fs";
|
|
534
|
-
import { join as
|
|
534
|
+
import { join as join11 } from "node:path";
|
|
535
535
|
var SEAT_POST_MIN_DELTA_PCT2 = 1, SEAT_POST_MIN_INTERVAL_MS2, SEAT_POST_TIMEOUT_MS2 = 1500, STDIN_TIMEOUT_MS2 = 300, isObject9 = (v) => typeof v === "object" && v !== null && !Array.isArray(v), num5 = (v) => typeof v === "number" && Number.isFinite(v) ? v : undefined, EPOCH_MS_THRESHOLD2 = 100000000000, parseResetsAt2 = (v) => {
|
|
536
536
|
const n = num5(v);
|
|
537
537
|
if (n !== undefined) {
|
|
@@ -604,7 +604,7 @@ var SEAT_POST_MIN_DELTA_PCT2 = 1, SEAT_POST_MIN_INTERVAL_MS2, SEAT_POST_TIMEOUT_
|
|
|
604
604
|
if (parts.length === 0)
|
|
605
605
|
return null;
|
|
606
606
|
return `seat ${parts.join(SEP)}`;
|
|
607
|
-
}, seatStatePath2 = (home) =>
|
|
607
|
+
}, seatStatePath2 = (home) => join11(configDir(home), "seat.json"), parseWindowStored2 = (v) => {
|
|
608
608
|
if (!isObject9(v))
|
|
609
609
|
return;
|
|
610
610
|
const capturedAt = num5(v.capturedAt);
|
|
@@ -750,9 +750,9 @@ var SEAT_POST_MIN_DELTA_PCT2 = 1, SEAT_POST_MIN_INTERVAL_MS2, SEAT_POST_TIMEOUT_
|
|
|
750
750
|
} catch {
|
|
751
751
|
return false;
|
|
752
752
|
}
|
|
753
|
-
}, postSeatWindow2 = (o, w) => postJson2(o, "/proxy/seat", seatWindowBody2(w)), postSeatWall2 = (o, input) => postJson2(o, "/proxy/seat-wall", input), SEAT_WALL_LINE2 = "Seat limit hit. sleds on --until-reset to continue on the org key, or sleds defer to resume here at the reset.", SEAT_WALL_LINE_NO_KEY2 = "Seat limit hit. sleds defer resumes this session on this Mac at the reset; /sled 5 to hand off — this org has no platform key to switch to.", seatWallLine2 = (hasUpstreamKey) => hasUpstreamKey ? SEAT_WALL_LINE2 : SEAT_WALL_LINE_NO_KEY2, readStdin2 = (timeoutMs, stdin = process.stdin) => new Promise((
|
|
753
|
+
}, postSeatWindow2 = (o, w) => postJson2(o, "/proxy/seat", seatWindowBody2(w)), postSeatWall2 = (o, input) => postJson2(o, "/proxy/seat-wall", input), SEAT_WALL_LINE2 = "Seat limit hit. sleds on --until-reset to continue on the org key, or sleds defer to resume here at the reset.", SEAT_WALL_LINE_NO_KEY2 = "Seat limit hit. sleds defer resumes this session on this Mac at the reset; /sled 5 to hand off — this org has no platform key to switch to.", seatWallLine2 = (hasUpstreamKey) => hasUpstreamKey ? SEAT_WALL_LINE2 : SEAT_WALL_LINE_NO_KEY2, readStdin2 = (timeoutMs, stdin = process.stdin) => new Promise((resolve5) => {
|
|
754
754
|
if (stdin.isTTY) {
|
|
755
|
-
|
|
755
|
+
resolve5("");
|
|
756
756
|
return;
|
|
757
757
|
}
|
|
758
758
|
let data = "";
|
|
@@ -762,7 +762,7 @@ var SEAT_POST_MIN_DELTA_PCT2 = 1, SEAT_POST_MIN_INTERVAL_MS2, SEAT_POST_TIMEOUT_
|
|
|
762
762
|
return;
|
|
763
763
|
settled = true;
|
|
764
764
|
clearTimeout(timer);
|
|
765
|
-
|
|
765
|
+
resolve5(data);
|
|
766
766
|
};
|
|
767
767
|
const timer = setTimeout(finish, timeoutMs);
|
|
768
768
|
stdin.setEncoding("utf8");
|
|
@@ -793,13 +793,20 @@ import { hostname } from "node:os";
|
|
|
793
793
|
// src/musher.ts
|
|
794
794
|
import { spawnSync } from "node:child_process";
|
|
795
795
|
import { createPublicKey, verify as cryptoVerify } from "node:crypto";
|
|
796
|
-
import { dirname as dirname2, join as join4 } from "node:path";
|
|
796
|
+
import { basename, dirname as dirname2, join as join4 } from "node:path";
|
|
797
797
|
var MUSHER_LABEL = "ai.sleds.musher";
|
|
798
798
|
var MUSHER_INTERVAL_S = 300;
|
|
799
799
|
var DEFAULT_PERMISSION_MODE = "acceptEdits";
|
|
800
800
|
var DEFAULT_TIMEOUT_MINUTES = 90;
|
|
801
801
|
var SUMMARY_MAX = 2000;
|
|
802
|
-
var
|
|
802
|
+
var musherLabel = (env = process.env) => {
|
|
803
|
+
const sh = env.SLEDS_HOME?.trim();
|
|
804
|
+
if (!sh)
|
|
805
|
+
return MUSHER_LABEL;
|
|
806
|
+
const tag = basename(sh).replace(/^\.+/, "").replace(/[^A-Za-z0-9_-]+/g, "-") || "seat";
|
|
807
|
+
return `${MUSHER_LABEL}.${tag}`;
|
|
808
|
+
};
|
|
809
|
+
var musherPlistPath = (home, env = process.env) => join4(home, "Library", "LaunchAgents", `${musherLabel(env)}.plist`);
|
|
803
810
|
var musherLogPath = (configDir2) => join4(configDir2, "musher.log");
|
|
804
811
|
var xmlEscape = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
805
812
|
var musherPath = (home, execPath, currentPath = "") => {
|
|
@@ -817,6 +824,7 @@ var musherPath = (home, execPath, currentPath = "") => {
|
|
|
817
824
|
return [...new Set(parts)].join(":");
|
|
818
825
|
};
|
|
819
826
|
var buildMusherPlist = (o) => {
|
|
827
|
+
const label = o.label ?? MUSHER_LABEL;
|
|
820
828
|
const args = [...o.sledsArgv, "musher", "tick"].map((a) => ` <string>${xmlEscape(a)}</string>`).join(`
|
|
821
829
|
`);
|
|
822
830
|
const env = Object.entries(o.env).filter(([, v]) => v !== "").map(([k, v]) => ` <key>${xmlEscape(k)}</key>
|
|
@@ -827,7 +835,7 @@ var buildMusherPlist = (o) => {
|
|
|
827
835
|
<plist version="1.0">
|
|
828
836
|
<dict>
|
|
829
837
|
<key>Label</key>
|
|
830
|
-
<string>${
|
|
838
|
+
<string>${label}</string>
|
|
831
839
|
<key>ProgramArguments</key>
|
|
832
840
|
<array>
|
|
833
841
|
${args}
|
|
@@ -1500,7 +1508,7 @@ var findClaude = (home, configured, which) => {
|
|
|
1500
1508
|
return null;
|
|
1501
1509
|
};
|
|
1502
1510
|
var musherAgentState = (home, env = process.env) => {
|
|
1503
|
-
const plist = musherPlistPath(home);
|
|
1511
|
+
const plist = musherPlistPath(home, env);
|
|
1504
1512
|
if (!existsSync6(plist))
|
|
1505
1513
|
return { installed: false, thisSeat: false };
|
|
1506
1514
|
try {
|
|
@@ -1696,7 +1704,11 @@ async function runDoctor(o) {
|
|
|
1696
1704
|
name: "musher",
|
|
1697
1705
|
detail: "agent installed for a different seat (SLEDS_HOME differs)",
|
|
1698
1706
|
fix: "sleds musher --install"
|
|
1699
|
-
} : {
|
|
1707
|
+
} : {
|
|
1708
|
+
level: "ok",
|
|
1709
|
+
name: "musher",
|
|
1710
|
+
detail: `launchd agent ${musherLabel(env)}, every 5 min`
|
|
1711
|
+
});
|
|
1700
1712
|
const claude = findClaude(home, readConfig(home).musher?.claudePath, (c) => (o.which ?? defaultWhich2)(c)[0] ?? null);
|
|
1701
1713
|
checks.push(claude ? { level: "ok", name: "claude cli", detail: claude } : {
|
|
1702
1714
|
level: "warn",
|
|
@@ -2770,7 +2782,8 @@ var musherInstall = (o) => {
|
|
|
2770
2782
|
return 1;
|
|
2771
2783
|
}
|
|
2772
2784
|
const env = o.env ?? process.env;
|
|
2773
|
-
const plist = musherPlistPath(o.home);
|
|
2785
|
+
const plist = musherPlistPath(o.home, env);
|
|
2786
|
+
const label = musherLabel(env);
|
|
2774
2787
|
const dir = configDir(o.home, env);
|
|
2775
2788
|
mkdirSync7(dirname3(plist), { recursive: true });
|
|
2776
2789
|
mkdirSync7(dir, { recursive: true, mode: 448 });
|
|
@@ -2784,7 +2797,7 @@ var musherInstall = (o) => {
|
|
|
2784
2797
|
const exec = o.exec ?? defaultExecSync;
|
|
2785
2798
|
if (existsSync8(plist))
|
|
2786
2799
|
exec("launchctl", ["unload", plist]);
|
|
2787
|
-
writeFileSync7(plist, buildMusherPlist({ sledsArgv: o.sledsArgv, env: agentEnv, logPath: musherLogPath(dir) }));
|
|
2800
|
+
writeFileSync7(plist, buildMusherPlist({ sledsArgv: o.sledsArgv, env: agentEnv, logPath: musherLogPath(dir), label }));
|
|
2788
2801
|
const r = exec("launchctl", ["load", plist]);
|
|
2789
2802
|
if (!r.ok) {
|
|
2790
2803
|
error(`launchctl load failed: ${r.stderr.trim() || "unknown"}`);
|
|
@@ -2793,19 +2806,20 @@ var musherInstall = (o) => {
|
|
|
2793
2806
|
const cfg = readConfig(o.home);
|
|
2794
2807
|
writeConfig(o.home, { ...cfg, musher: { ...cfg.musher ?? {}, agent: "launchd" } });
|
|
2795
2808
|
const claude = findClaude2(o.home, cfg.musher?.claudePath, o.which ?? defaultWhich3);
|
|
2796
|
-
log(`musher installed: launchd agent ${
|
|
2809
|
+
log(`musher installed: launchd agent ${label}, every 5 min · log ${musherLogPath(dir)}`);
|
|
2797
2810
|
if (!claude)
|
|
2798
2811
|
log("warn: `claude` not found on PATH — set it with `sleds musher --claude /path/to/claude`");
|
|
2799
2812
|
return 0;
|
|
2800
2813
|
};
|
|
2801
2814
|
var musherUninstall = (o) => {
|
|
2802
2815
|
const log = o.log ?? console.log;
|
|
2803
|
-
const
|
|
2816
|
+
const env = o.env ?? process.env;
|
|
2817
|
+
const plist = musherPlistPath(o.home, env);
|
|
2804
2818
|
const exec = o.exec ?? defaultExecSync;
|
|
2805
2819
|
if (existsSync8(plist)) {
|
|
2806
2820
|
exec("launchctl", ["unload", plist]);
|
|
2807
2821
|
rmSync2(plist, { force: true });
|
|
2808
|
-
log(`musher removed: ${
|
|
2822
|
+
log(`musher removed: ${musherLabel(env)}`);
|
|
2809
2823
|
} else
|
|
2810
2824
|
log("musher was not installed.");
|
|
2811
2825
|
const cfg = readConfig(o.home);
|
|
@@ -2834,9 +2848,10 @@ var clientFor = (o) => {
|
|
|
2834
2848
|
var musherStatus = async (o) => {
|
|
2835
2849
|
const log = o.log ?? console.log;
|
|
2836
2850
|
const now = (o.now ?? Date.now)();
|
|
2837
|
-
const
|
|
2851
|
+
const env = o.env ?? process.env;
|
|
2852
|
+
const plist = musherPlistPath(o.home, env);
|
|
2838
2853
|
const cfg = readConfig(o.home);
|
|
2839
|
-
log(existsSync8(plist) ? `agent ${
|
|
2854
|
+
log(existsSync8(plist) ? `agent ${musherLabel(env)} installed (${plist})` : "agent not installed — sleds musher --install");
|
|
2840
2855
|
const claude = findClaude2(o.home, cfg.musher?.claudePath, o.which ?? defaultWhich3);
|
|
2841
2856
|
log(`claude ${claude ?? "not found — sleds musher --claude /path/to/claude"}`);
|
|
2842
2857
|
log(`mode ${cfg.musher?.permissionMode ?? DEFAULT_PERMISSION_MODE} · timeout ${cfg.musher?.timeoutMinutes ?? DEFAULT_TIMEOUT_MINUTES} min`);
|
|
@@ -3797,7 +3812,7 @@ async function postSeat(proxyUrl, token, body, fetchFn) {
|
|
|
3797
3812
|
// src/commands/specEvent.ts
|
|
3798
3813
|
init_meter();
|
|
3799
3814
|
import { readFileSync as readFileSync9, statSync } from "node:fs";
|
|
3800
|
-
import { basename, isAbsolute, relative } from "node:path";
|
|
3815
|
+
import { basename as basename2, isAbsolute, relative } from "node:path";
|
|
3801
3816
|
var HOOK_STDIN_TIMEOUT_MS2 = 1000;
|
|
3802
3817
|
var ESTIMATE_TIMEOUT_MS = 4000;
|
|
3803
3818
|
var MIN_SPEC_CHARS = 200;
|
|
@@ -3810,12 +3825,12 @@ function isSpecPath(path) {
|
|
|
3810
3825
|
return false;
|
|
3811
3826
|
if (NOT_SPEC.test(path))
|
|
3812
3827
|
return false;
|
|
3813
|
-
return SPEC_DIRS.test(path) || SPEC_NAMES.test(
|
|
3828
|
+
return SPEC_DIRS.test(path) || SPEC_NAMES.test(basename2(path));
|
|
3814
3829
|
}
|
|
3815
3830
|
function specTitle(body, path) {
|
|
3816
3831
|
const m = /^#\s+(.+?)\s*$/m.exec(body);
|
|
3817
3832
|
const t = m?.[1]?.trim();
|
|
3818
|
-
return (t && t.length > 0 ? t :
|
|
3833
|
+
return (t && t.length > 0 ? t : basename2(path).replace(/\.(md|mdx)$/i, "")).slice(0, 120);
|
|
3819
3834
|
}
|
|
3820
3835
|
function looksLikeSpec(body) {
|
|
3821
3836
|
if (body.trim().length < MIN_SPEC_CHARS)
|
|
@@ -3873,7 +3888,7 @@ var specEvent = async (o) => {
|
|
|
3873
3888
|
const spec = {
|
|
3874
3889
|
title: specTitle(body, input.filePath),
|
|
3875
3890
|
body: body.slice(0, MAX_SPEC_CHARS),
|
|
3876
|
-
repoHint: input.cwd ?
|
|
3891
|
+
repoHint: input.cwd ? basename2(input.cwd) : undefined
|
|
3877
3892
|
};
|
|
3878
3893
|
try {
|
|
3879
3894
|
const res = await (o.fetchFn ?? fetch)(`${src.proxyUrl}/proxy/estimate`, {
|
|
@@ -4136,7 +4151,7 @@ var uninstall2 = (o) => {
|
|
|
4136
4151
|
if (existsSync12(plist)) {
|
|
4137
4152
|
(o.unloadAgent ?? defaultUnload)(plist);
|
|
4138
4153
|
rmSync5(plist, { force: true });
|
|
4139
|
-
removed.push(`launchd agent ${
|
|
4154
|
+
removed.push(`launchd agent ${musherLabel()}`);
|
|
4140
4155
|
}
|
|
4141
4156
|
if (removed.length === 0) {
|
|
4142
4157
|
log("Nothing to remove; SLEDS was not installed.");
|
|
@@ -4212,6 +4227,21 @@ var defaultExec = (cmd, args) => {
|
|
|
4212
4227
|
return { ok: r.status === 0, stderr: r.stderr ?? "" };
|
|
4213
4228
|
};
|
|
4214
4229
|
|
|
4230
|
+
// src/settings.ts
|
|
4231
|
+
import { dirname as dirname4, join as join10, resolve as resolve4 } from "node:path";
|
|
4232
|
+
var withSeatEnv2 = (command, home, env = process.env) => {
|
|
4233
|
+
const parts = [];
|
|
4234
|
+
const sh = env.SLEDS_HOME?.trim();
|
|
4235
|
+
const cc = env.CLAUDE_CONFIG_DIR?.trim();
|
|
4236
|
+
if (sh)
|
|
4237
|
+
parts.push(`SLEDS_HOME=${shellWord2(resolve4(home, sh))}`);
|
|
4238
|
+
if (cc)
|
|
4239
|
+
parts.push(`CLAUDE_CONFIG_DIR=${shellWord2(resolve4(home, cc))}`);
|
|
4240
|
+
parts.push(command);
|
|
4241
|
+
return parts.join(" ");
|
|
4242
|
+
};
|
|
4243
|
+
var shellWord2 = (v) => /^[\w./~-]+$/.test(v) ? v : `'${v.replace(/'/g, "'\\''")}'`;
|
|
4244
|
+
|
|
4215
4245
|
// src/index.ts
|
|
4216
4246
|
var USAGE = `usage: sleds <command> [options]
|
|
4217
4247
|
|
|
@@ -4309,9 +4339,9 @@ var sledsArgv = () => {
|
|
|
4309
4339
|
return script ? [process.execPath, script] : [process.execPath];
|
|
4310
4340
|
};
|
|
4311
4341
|
var shellQuote = (s) => /^[\w./-]+$/.test(s) ? s : `'${s.replace(/'/g, "'\\''")}'`;
|
|
4312
|
-
var statusLineCommand = (argv) => [...argv, "statusline"].map(shellQuote).join(" ");
|
|
4313
|
-
var seatEventCommand = (argv) => [...argv, "seat-event"].map(shellQuote).join(" ");
|
|
4314
|
-
var specEventCommand = (argv) => [...argv, "spec-event"].map(shellQuote).join(" ");
|
|
4342
|
+
var statusLineCommand = (argv, home = homedir()) => withSeatEnv2([...argv, "statusline"].map(shellQuote).join(" "), home);
|
|
4343
|
+
var seatEventCommand = (argv, home = homedir()) => withSeatEnv2([...argv, "seat-event"].map(shellQuote).join(" "), home);
|
|
4344
|
+
var specEventCommand = (argv, home = homedir()) => withSeatEnv2([...argv, "spec-event"].map(shellQuote).join(" "), home);
|
|
4315
4345
|
var main = async (argv) => {
|
|
4316
4346
|
const { cmd, flags } = parseArgs(argv);
|
|
4317
4347
|
const home = homedir();
|
|
@@ -4403,7 +4433,7 @@ var main = async (argv) => {
|
|
|
4403
4433
|
case "version":
|
|
4404
4434
|
case "--version":
|
|
4405
4435
|
case "-v":
|
|
4406
|
-
console.log("sleds 0.1.
|
|
4436
|
+
console.log("sleds 0.1.15");
|
|
4407
4437
|
return 0;
|
|
4408
4438
|
default:
|
|
4409
4439
|
console.error(`unknown command: ${cmd}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sleds/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"description": "SLEDS CLI — the cost and limits of AI agent work, decided at the wall. Point Claude Code at a SLEDS proxy; estimate before you run; hold, switch model, or run overnight when you hit a limit.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|