@sleds/cli 0.1.29 → 0.1.30
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 +52 -21
- package/package.json +1 -1
package/dist/sleds.mjs
CHANGED
|
@@ -198,7 +198,7 @@ var BASE_URL_KEY = "ANTHROPIC_BASE_URL", AUTH_TOKEN_KEY = "ANTHROPIC_AUTH_TOKEN"
|
|
|
198
198
|
visit(settings[STATUS_LINE_KEY]);
|
|
199
199
|
visit(settings.hooks);
|
|
200
200
|
return out;
|
|
201
|
-
}, bakedHome = (command) => command.match(/(?:^|\s)SLEDS_HOME=('([^']*)'|(\S+))/)?.[2] ?? command.match(/(?:^|\s)SLEDS_HOME=(\S+)/)?.[1], shellWord = (v) => /^[\w./~-]+$/.test(v) ? v : `'${v.replace(/'/g, "'\\''")}'`, backupPath = (home) => join(claudeDir(home), "settings.json.sleds-backup"), tokenPath = (home, env = process.env) => {
|
|
201
|
+
}, inFnmShell = (command) => /[/\\]fnm_multishells[/\\]/.test(command), bakedHome = (command) => command.match(/(?:^|\s)SLEDS_HOME=('([^']*)'|(\S+))/)?.[2] ?? command.match(/(?:^|\s)SLEDS_HOME=(\S+)/)?.[1], shellWord = (v) => /^[\w./~-]+$/.test(v) ? v : `'${v.replace(/'/g, "'\\''")}'`, backupPath = (home) => join(claudeDir(home), "settings.json.sleds-backup"), tokenPath = (home, env = process.env) => {
|
|
202
202
|
const o2 = env.SLEDS_HOME?.trim();
|
|
203
203
|
return o2 ? join(resolve2(home, o2), ".sleds-token") : join(home, ".sleds-token");
|
|
204
204
|
}, skillDir = (home) => join(claudeDir(home), "skills", "sled"), skillPath = (home) => join(skillDir(home), "SKILL.md"), isObject5 = (v) => typeof v === "object" && v !== null && !Array.isArray(v), envOf = (settings) => {
|
|
@@ -2586,6 +2586,12 @@ function nodePlanOf(raw) {
|
|
|
2586
2586
|
function routeApproachOf(raw) {
|
|
2587
2587
|
return cleanParagraph(raw, ROUTE_APPROACH_MAX).text || undefined;
|
|
2588
2588
|
}
|
|
2589
|
+
function isPrMirror(source) {
|
|
2590
|
+
if (!source || typeof source !== "object")
|
|
2591
|
+
return false;
|
|
2592
|
+
const { kind, doc } = source;
|
|
2593
|
+
return typeof kind === "string" && kind.toLowerCase() === "github" && typeof doc === "string" && /^#\d+$/.test(doc.trim());
|
|
2594
|
+
}
|
|
2589
2595
|
var AREA_ROOTS = new Set(["apps", "packages", "services", "libs", "crates", "modules"]);
|
|
2590
2596
|
var NOT_AREAS = new Set(["docs", "doc", "specs"]);
|
|
2591
2597
|
function planLines(plan, indent = "") {
|
|
@@ -3885,10 +3891,14 @@ var TOOLS = [
|
|
|
3885
3891
|
},
|
|
3886
3892
|
{
|
|
3887
3893
|
name: "actual",
|
|
3888
|
-
description: "Call this WHEN THE WORK LANDS (merged, shipped, done) — the last thing you do on a build, every time, with the same `source` the estimate was filed under. Records what happened: state (started · done · merged · shipped), where the output lives (`ref`: PR url, commit, doc), the model, who did it, dollars and tokens when something counted them, time by phase. Minutes are MEASURED by SLEDS from the pickup (or the estimate) to now — do not invent a number; pass `minutes` only when a person stated it. Pass `sessionId` (your session link) so the session's token spend joins the item. If SLEDS answers that no estimate is on file, call `estimate` with this source first, then send this again.",
|
|
3894
|
+
description: "Call this WHEN THE WORK LANDS (merged, shipped, done) — the last thing you do on a build, every time, with the same `source` the estimate was filed under (or the item's key as `project`, QW-142, when you took it from the sled). Records what happened: state (started · done · merged · shipped), where the output lives (`ref`: PR url, commit, doc), the model, who did it, dollars and tokens when something counted them, time by phase. Minutes are MEASURED by SLEDS from the pickup (or the estimate) to now — do not invent a number; pass `minutes` only when a person stated it. Pass `sessionId` (your session link) so the session's token spend joins the item. If SLEDS answers that no estimate is on file, call `estimate` with this source first, then send this again.",
|
|
3889
3895
|
inputSchema: {
|
|
3890
3896
|
type: "object",
|
|
3891
3897
|
properties: {
|
|
3898
|
+
project: {
|
|
3899
|
+
type: "string",
|
|
3900
|
+
description: "The item's key — QW-142 — or its project key, in place of `source` (resolved the way `status` finds it)."
|
|
3901
|
+
},
|
|
3892
3902
|
source: {
|
|
3893
3903
|
type: "object",
|
|
3894
3904
|
description: "The same source the estimate was filed under.",
|
|
@@ -3969,8 +3979,7 @@ var TOOLS = [
|
|
|
3969
3979
|
type: "string",
|
|
3970
3980
|
description: "Spec 26: this actual is for one node of the item's route (its key — B). State `pr` when the PR opens (the seat is free, the node is not landed yet); merged · done · shipped land the node, and the item lands when its last node does."
|
|
3971
3981
|
}
|
|
3972
|
-
}
|
|
3973
|
-
required: ["source"]
|
|
3982
|
+
}
|
|
3974
3983
|
}
|
|
3975
3984
|
},
|
|
3976
3985
|
{
|
|
@@ -4135,6 +4144,7 @@ var TOOLS = [
|
|
|
4135
4144
|
}
|
|
4136
4145
|
}
|
|
4137
4146
|
];
|
|
4147
|
+
var VIEW_TOOLS = new Set(TOOLS.filter((t) => ("_meta" in t) && t._meta?.ui).map((t) => t.name));
|
|
4138
4148
|
var NOT_SET_UP = {
|
|
4139
4149
|
text: "SLEDS is not connected to a seat here. Run `sleds init` (CLI) or connect SLEDS as a connector.",
|
|
4140
4150
|
isError: true
|
|
@@ -5567,7 +5577,7 @@ async function actualTool(ctx, args, to = { path: "/proxy/estimate/actual" }) {
|
|
|
5567
5577
|
const source = to.project ? null : args.source;
|
|
5568
5578
|
if (!to.project && (typeof source !== "object" || source === null))
|
|
5569
5579
|
return {
|
|
5570
|
-
text: "`source` is required — the
|
|
5580
|
+
text: "`source` or `project` is required — the source the estimate was filed under, or the item's key (QW-142).",
|
|
5571
5581
|
isError: true
|
|
5572
5582
|
};
|
|
5573
5583
|
const iso2 = (v) => {
|
|
@@ -5602,18 +5612,21 @@ async function actualTool(ctx, args, to = { path: "/proxy/estimate/actual" }) {
|
|
|
5602
5612
|
if (!res)
|
|
5603
5613
|
return { text: `Nothing recorded. ${UNREACHABLE.text}`, isError: true };
|
|
5604
5614
|
const r = res.json ?? {};
|
|
5605
|
-
|
|
5606
|
-
|
|
5607
|
-
|
|
5608
|
-
|
|
5609
|
-
|
|
5610
|
-
|
|
5615
|
+
const reason = (str5(r.reason) ?? errorMessage(r))?.trim().replace(/\.$/, "");
|
|
5616
|
+
if (to.project && (r.notFound === true || res.status === 404))
|
|
5617
|
+
return {
|
|
5618
|
+
text: `Nothing recorded: nothing on the sled answers to "${to.project}". Try \`status\` for its key, or pass the \`source\` the estimate was filed under.`,
|
|
5619
|
+
isError: true
|
|
5620
|
+
};
|
|
5621
|
+
if (!to.project && res.status === 404 && r.refused !== true && r.badState !== true) {
|
|
5611
5622
|
const src = isObject4(source) ? sourceText(source) : "that source";
|
|
5612
5623
|
return {
|
|
5613
5624
|
text: `Nothing recorded: no estimate on file for ${src}. Size it first — call estimate with the same source and a one-line spec of what was built — then send this actual again; SLEDS will measure the time from that estimate. Do not invent minutes to get past this.`,
|
|
5614
5625
|
isError: true
|
|
5615
5626
|
};
|
|
5616
5627
|
}
|
|
5628
|
+
if (r.ok === false && res.status < 500)
|
|
5629
|
+
return { text: `Nothing recorded: ${reason ?? `HTTP ${res.status}`}.`, isError: true };
|
|
5617
5630
|
if (res.status >= 500)
|
|
5618
5631
|
return {
|
|
5619
5632
|
text: `Nothing recorded. ${errorMessage(r) ?? "Control plane unreachable"} (HTTP ${res.status}) → try once more in a moment, then move on and say the actual is still owed.`,
|
|
@@ -5737,8 +5750,10 @@ async function callTool(name, args, ctx) {
|
|
|
5737
5750
|
return withGuidanceText(await pickupTool(ctx, args), await guidanceBlock(ctx, { moment: "handoff", channel: "code" }));
|
|
5738
5751
|
case "defer":
|
|
5739
5752
|
return deferTool(ctx, args);
|
|
5740
|
-
case "actual":
|
|
5741
|
-
|
|
5753
|
+
case "actual": {
|
|
5754
|
+
const project = isObject4(args.source) ? undefined : str5(args.project)?.trim();
|
|
5755
|
+
return project ? actualTool(ctx, args, { path: "/proxy/estimate/actual", project }) : actualTool(ctx, args);
|
|
5756
|
+
}
|
|
5742
5757
|
case "land":
|
|
5743
5758
|
case "finish":
|
|
5744
5759
|
return landTool(ctx, args);
|
|
@@ -5825,7 +5840,7 @@ async function handleLine(line, ctx) {
|
|
|
5825
5840
|
} catch {}
|
|
5826
5841
|
return response(id, {
|
|
5827
5842
|
content: [{ type: "text", text: r.text }],
|
|
5828
|
-
...r.structured ? { structuredContent: r.structured } : {},
|
|
5843
|
+
...r.structured && VIEW_TOOLS.has(name) ? { structuredContent: r.structured } : {},
|
|
5829
5844
|
...r.isError ? { isError: true } : {}
|
|
5830
5845
|
});
|
|
5831
5846
|
}
|
|
@@ -10121,6 +10136,8 @@ function nextPickup(r, o2) {
|
|
|
10121
10136
|
const route3 = row2.route;
|
|
10122
10137
|
if (!isObject10(route3) || isObject10(route3.armed) || route3.draftParked)
|
|
10123
10138
|
continue;
|
|
10139
|
+
if (isPrMirror(row2.source))
|
|
10140
|
+
continue;
|
|
10124
10141
|
const states = isObject10(route3.states) ? route3.states : {};
|
|
10125
10142
|
if (statesLanded(states) || keysIn(states, "running").length > 0)
|
|
10126
10143
|
continue;
|
|
@@ -14659,6 +14676,15 @@ async function runDoctor(o2) {
|
|
|
14659
14676
|
fix: wrong.length === 0 ? undefined : `${overrides.length ? `${overrides.join(" ")} ` : ""}sleds hooks (re-writes the status line + hooks with this seat baked in)`
|
|
14660
14677
|
});
|
|
14661
14678
|
}
|
|
14679
|
+
const fnm = cmds.filter(inFnmShell);
|
|
14680
|
+
if (fnm.length > 0) {
|
|
14681
|
+
checks.push({
|
|
14682
|
+
level: "warn",
|
|
14683
|
+
name: "commands path",
|
|
14684
|
+
detail: `${fnm.length} of ${cmds.length} commands in settings.json run sleds from fnm_multishells — fnm deletes that folder, and they fail silently`,
|
|
14685
|
+
fix: `${overrides.length ? `${overrides.join(" ")} ` : ""}sleds hooks (re-writes the status line + hooks with sleds's resolved path)`
|
|
14686
|
+
});
|
|
14687
|
+
}
|
|
14662
14688
|
const wantOrg = orgChoice(cfg, undefined, env).slug ?? cfg.org?.slug;
|
|
14663
14689
|
if (cmds.length > 0 && wantOrg) {
|
|
14664
14690
|
const unpinned = cmds.filter((c) => bakedOrg(c) === undefined);
|
|
@@ -16436,10 +16462,17 @@ var PROFILE_FIELDS = [
|
|
|
16436
16462
|
"mcpAllow",
|
|
16437
16463
|
"holdCpu",
|
|
16438
16464
|
"holdLoad",
|
|
16465
|
+
"holdUsage",
|
|
16466
|
+
"holdPressure",
|
|
16467
|
+
"holdOff"
|
|
16468
|
+
];
|
|
16469
|
+
var HOLD_FIELDS = [
|
|
16470
|
+
"holdCpu",
|
|
16471
|
+
"holdLoad",
|
|
16472
|
+
"holdUsage",
|
|
16439
16473
|
"holdPressure",
|
|
16440
16474
|
"holdOff"
|
|
16441
16475
|
];
|
|
16442
|
-
var HOLD_FIELDS = ["holdCpu", "holdLoad", "holdPressure", "holdOff"];
|
|
16443
16476
|
var CMUX_PASSWORD_FIELD = "cmuxPassword";
|
|
16444
16477
|
function patchFromArgs(words) {
|
|
16445
16478
|
const patch = {};
|
|
@@ -16466,7 +16499,7 @@ function patchFromArgs(words) {
|
|
|
16466
16499
|
if (!Number.isInteger(n) || n < 1)
|
|
16467
16500
|
return { error: "atOnce is a whole number from 1" };
|
|
16468
16501
|
patch[field2] = n;
|
|
16469
|
-
} else if (field2 === "holdCpu" || field2 === "holdLoad") {
|
|
16502
|
+
} else if (field2 === "holdCpu" || field2 === "holdLoad" || field2 === "holdUsage") {
|
|
16470
16503
|
const n = Number(value);
|
|
16471
16504
|
if (!Number.isFinite(n))
|
|
16472
16505
|
return { error: `${field2} is a number` };
|
|
@@ -21168,10 +21201,7 @@ var hookStdin = async () => {
|
|
|
21168
21201
|
const text = await readStdin3(300);
|
|
21169
21202
|
return text.trim() ? text : undefined;
|
|
21170
21203
|
};
|
|
21171
|
-
var sledsArgv = () =>
|
|
21172
|
-
const script = process.argv[1];
|
|
21173
|
-
return script ? [process.execPath, script] : [process.execPath];
|
|
21174
|
-
};
|
|
21204
|
+
var sledsArgv = (execPath = process.execPath, script = process.argv[1], realpath) => stableArgv2(script ? [execPath, script] : [execPath], realpath);
|
|
21175
21205
|
var shellQuote = (s) => /^[\w./-]+$/.test(s) ? s : `'${s.replace(/'/g, "'\\''")}'`;
|
|
21176
21206
|
var statusLineCommand = (argv, home = homedir()) => withSeatEnv2([...argv, "statusline"].map(shellQuote).join(" "), home);
|
|
21177
21207
|
var seatEventCommand = (argv, home = homedir()) => withSeatEnv2([...argv, "seat-event"].map(shellQuote).join(" "), home);
|
|
@@ -21392,7 +21422,7 @@ ${renderHelpText(argv[1])}`);
|
|
|
21392
21422
|
case "version":
|
|
21393
21423
|
case "--version":
|
|
21394
21424
|
case "-v":
|
|
21395
|
-
console.log("sleds 0.1.
|
|
21425
|
+
console.log("sleds 0.1.30");
|
|
21396
21426
|
return 0;
|
|
21397
21427
|
default:
|
|
21398
21428
|
console.error(`unknown command: ${cmd}
|
|
@@ -21424,6 +21454,7 @@ export {
|
|
|
21424
21454
|
stopEventCommand,
|
|
21425
21455
|
statusLineCommand,
|
|
21426
21456
|
specEventCommand,
|
|
21457
|
+
sledsArgv,
|
|
21427
21458
|
sessionEventCommand,
|
|
21428
21459
|
seatEventCommand,
|
|
21429
21460
|
promptEventCommand,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sleds/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.30",
|
|
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",
|