@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.
Files changed (2) hide show
  1. package/dist/sleds.mjs +52 -21
  2. 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 same one the estimate was filed under.",
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
- if (res.status === 404 || r.ok === false) {
5606
- if (to.project)
5607
- return {
5608
- 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.`,
5609
- isError: true
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
- return actualTool(ctx, args);
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.29");
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.29",
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",