@sleds/cli 0.1.50 → 0.1.51

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 +254 -45
  2. package/package.json +1 -1
package/dist/sleds.mjs CHANGED
@@ -769,6 +769,14 @@ var init_verbs = __esm(() => {
769
769
  app: "Work › Moving (the runs on each sled) · Record › Receipts once they land",
770
770
  how: "Newest first: id, status, route, cost. Hand-offs meant for you are listed first."
771
771
  },
772
+ {
773
+ id: "metrics",
774
+ group: "meter",
775
+ want: "See how a workspace or the whole org ships — DORA and batch size for a period",
776
+ mcp: "metrics {workspace?, range?, from?, to?} — range 2w · 1m · 3m · 6m · 1y, or from/to days",
777
+ app: "Metrics",
778
+ how: "Deploy frequency, lead time, change failure rate, time to recover and production deploys by batch size, each against the same length just before. A workspace gives one line; no workspace gives the org, one line per workspace you see."
779
+ },
772
780
  {
773
781
  id: "status",
774
782
  group: "meter",
@@ -1616,6 +1624,128 @@ var init_format = __esm(() => {
1616
1624
  OFFLINE_LINE = `${PREFIX}offline`;
1617
1625
  });
1618
1626
 
1627
+ // ../../packages/shared/src/item/outcome.ts
1628
+ var OUTCOME_WINDOW_DAYS = 14, OUTCOME_WINDOW_MS;
1629
+ var init_outcome = __esm(() => {
1630
+ OUTCOME_WINDOW_MS = OUTCOME_WINDOW_DAYS * 86400000;
1631
+ });
1632
+
1633
+ // ../../packages/shared/src/deploys/metrics.ts
1634
+ var WEEK_MS;
1635
+ var init_metrics = __esm(() => {
1636
+ WEEK_MS = 7 * 24 * 60 * 60 * 1000;
1637
+ });
1638
+
1639
+ // ../../packages/shared/src/deploys/batchSize.ts
1640
+ var TIERS;
1641
+ var init_batchSize = __esm(() => {
1642
+ init_outcome();
1643
+ init_metrics();
1644
+ TIERS = ["S", "M", "L", "G"];
1645
+ });
1646
+
1647
+ // ../../packages/shared/src/deploys/period.ts
1648
+ function periodChange(cur, prev, better) {
1649
+ if (cur == null || prev == null)
1650
+ return { pct: null, dir: "flat", tone: "neutral" };
1651
+ if (prev === 0)
1652
+ return { pct: null, dir: cur > 0 ? "up" : cur < 0 ? "down" : "flat", tone: "neutral" };
1653
+ const pct = (cur - prev) / Math.abs(prev) * 100;
1654
+ if (Math.abs(pct) < FLAT_PCT)
1655
+ return { pct, dir: "flat", tone: "neutral" };
1656
+ const dir = pct > 0 ? "up" : "down";
1657
+ return { pct, dir, tone: dir === better ? "success" : "error" };
1658
+ }
1659
+ var DAY_MS2, FLAT_PCT = 0.5;
1660
+ var init_period = __esm(() => {
1661
+ DAY_MS2 = 24 * 60 * 60 * 1000;
1662
+ });
1663
+
1664
+ // ../../packages/shared/src/deploys/report.ts
1665
+ function duration(ms) {
1666
+ const min = ms / 60000;
1667
+ if (min < 60)
1668
+ return `${Math.round(min)}m`;
1669
+ const hours = min / 60;
1670
+ if (hours < 48)
1671
+ return `${hours.toFixed(1)}h`;
1672
+ return `${(hours / 24).toFixed(1)}d`;
1673
+ }
1674
+ function change(pair, better) {
1675
+ const { current, previous } = pair;
1676
+ if (current == null)
1677
+ return "";
1678
+ if (previous == null)
1679
+ return " (none before)";
1680
+ const c = periodChange(current, previous, better);
1681
+ if (c.dir === "flat")
1682
+ return " (flat)";
1683
+ if (c.pct == null)
1684
+ return " (none before)";
1685
+ return ` (${c.pct > 0 ? "+" : "−"}${Math.round(Math.abs(c.pct))}%)`;
1686
+ }
1687
+ function timeFigure(label, pair) {
1688
+ if (pair.current == null)
1689
+ return `${label} none`;
1690
+ return `${label} ${duration(pair.current)}${change(pair, "down")}`;
1691
+ }
1692
+ function rateFigure(pair) {
1693
+ const { current, previous } = pair;
1694
+ if (current == null)
1695
+ return "failure rate none";
1696
+ const pct = Math.round(current * 100);
1697
+ if (previous == null)
1698
+ return `failure rate ${pct}% (none before)`;
1699
+ const pts = pct - Math.round(previous * 100);
1700
+ return `failure rate ${pct}% (${pts === 0 ? "flat" : `${pts > 0 ? "+" : "−"}${Math.abs(pts)} pts`})`;
1701
+ }
1702
+ function batchFigure(pair) {
1703
+ if (total(pair.current) === 0)
1704
+ return "batch none";
1705
+ const before = total(pair.previous) === 0 ? "none before" : `was ${tiers(pair.previous)}`;
1706
+ return `batch ${tiers(pair.current)} (${before})`;
1707
+ }
1708
+ function lineText(l) {
1709
+ const head = `${l.name} (${l.slug})`;
1710
+ if (l.production == null)
1711
+ return `${head} · no production environment set, so no deploy metrics`;
1712
+ const deploys = `${l.deploys.current} deploy${l.deploys.current === 1 ? "" : "s"}${change(l.deploys, "up")}`;
1713
+ return [
1714
+ `${head} · ${l.production}: ${deploys}`,
1715
+ timeFigure("lead time", l.leadTime),
1716
+ rateFigure(l.failRate),
1717
+ timeFigure("time to recover", l.recover),
1718
+ batchFigure(l.batch)
1719
+ ].join(" · ");
1720
+ }
1721
+ function metricsText(r) {
1722
+ const sameYear = r.from.slice(0, 4) === r.to.slice(0, 4);
1723
+ const span = `${dayLabel(r.from, !sameYear)} – ${dayLabel(r.to, true)}`;
1724
+ const days = `${r.days} day${r.days === 1 ? "" : "s"}`;
1725
+ const header = `${r.scope === "org" ? "Org" : "Workspace"} · ${span} (${days}), against the ${days} before`;
1726
+ const lines = r.lines.length ? r.lines.map(lineText) : [r.scope === "org" ? "No workspaces in this org." : "No workspace."];
1727
+ return [header, ...lines].join(`
1728
+ `);
1729
+ }
1730
+ var DAY_MS3, METRICS_RANGES, tiers = (c) => TIERS.map((t) => `${t}${c[t]}`).join(" "), total = (c) => TIERS.reduce((n, t) => n + c[t], 0), dayLabel = (day, year) => new Date(`${day}T00:00:00Z`).toLocaleDateString("en-US", {
1731
+ month: "short",
1732
+ day: "numeric",
1733
+ ...year ? { year: "numeric" } : {},
1734
+ timeZone: "UTC"
1735
+ });
1736
+ var init_report = __esm(() => {
1737
+ init_batchSize();
1738
+ init_period();
1739
+ DAY_MS3 = 24 * 60 * 60 * 1000;
1740
+ METRICS_RANGES = [
1741
+ { key: "2w", days: 14 },
1742
+ { key: "1m", days: 30 },
1743
+ { key: "3m", days: 91 },
1744
+ { key: "6m", days: 182 },
1745
+ { key: "1y", days: 365 }
1746
+ ];
1747
+ });
1748
+
1619
1749
  // ../../packages/shared/src/guidance/model.ts
1620
1750
  var CARD_FIELDS;
1621
1751
  var init_model = __esm(() => {
@@ -2120,7 +2250,7 @@ var read = (title) => ({
2120
2250
  destructiveHint: false,
2121
2251
  idempotentHint: idempotent,
2122
2252
  openWorldHint: false
2123
- }), change = (title, idempotent = false) => ({
2253
+ }), change2 = (title, idempotent = false) => ({
2124
2254
  title,
2125
2255
  readOnlyHint: false,
2126
2256
  destructiveHint: true,
@@ -2130,6 +2260,7 @@ var read = (title) => ({
2130
2260
  var init_annotations = __esm(() => {
2131
2261
  TOOL_ANNOTATIONS = {
2132
2262
  usage: read("Seat usage"),
2263
+ metrics: read("Delivery metrics"),
2133
2264
  jobs: read("Overnight jobs"),
2134
2265
  status: read("Where is it"),
2135
2266
  touches: read("What it touches"),
@@ -2158,9 +2289,9 @@ var init_annotations = __esm(() => {
2158
2289
  buddy: add("Pair with a buddy"),
2159
2290
  pickup: add("Pick up a hand-off"),
2160
2291
  reopen: add("Reopen an item", true),
2161
- update: change("Change an item", true),
2162
- archive: change("Archive an item", true),
2163
- withdraw: change("Withdraw a hand-off", true)
2292
+ update: change2("Change an item", true),
2293
+ archive: change2("Archive an item", true),
2294
+ withdraw: change2("Withdraw a hand-off", true)
2164
2295
  };
2165
2296
  });
2166
2297
 
@@ -2421,19 +2552,23 @@ var init_plan2 = __esm(() => {
2421
2552
  });
2422
2553
 
2423
2554
  // ../../packages/shared/src/mcp/sled.ts
2424
- function section(label, rows, now) {
2555
+ function section(label, rows, now, count = rows.length) {
2425
2556
  if (rows.length === 0)
2426
2557
  return null;
2427
- return `${label} (${rows.length}):
2558
+ const total = Math.max(count, rows.length);
2559
+ const more = total > rows.length ? `
2560
+
2561
+ …and ${total - rows.length} more` : "";
2562
+ return `${label} (${total}):
2428
2563
 
2429
2564
  ${rows.map((r) => statusLine(r, now)).join(`
2430
2565
 
2431
- `)}`;
2566
+ `)}${more}`;
2432
2567
  }
2433
2568
  function sledText(s, now) {
2434
2569
  const parts = [
2435
2570
  section("On your sled", s.mine, now),
2436
- section("Proposed to you", s.proposed, now),
2571
+ section("Proposed to you", s.proposed, now, s.proposedCount),
2437
2572
  section("Sent to you", s.sent, now)
2438
2573
  ].filter((p) => p !== null);
2439
2574
  if (parts.length === 0)
@@ -2706,6 +2841,60 @@ async function usageTool(ctx) {
2706
2841
  return { text: formatMeter(m, (ctx.now ?? Date.now)()).join(`
2707
2842
  `) };
2708
2843
  }
2844
+ function asMetricsReport(j) {
2845
+ if (!j || j.scope !== "workspace" && j.scope !== "org")
2846
+ return null;
2847
+ if (typeof j.from !== "string" || typeof j.to !== "string" || num3(j.days) === undefined)
2848
+ return null;
2849
+ if (!Array.isArray(j.lines) || !j.lines.every(isObject4))
2850
+ return null;
2851
+ return j;
2852
+ }
2853
+ async function metricsTool(ctx, args) {
2854
+ if (!ctx.client)
2855
+ return NOT_SET_UP;
2856
+ const qs = new URLSearchParams;
2857
+ for (const k of ["workspace", "range", "from", "to"]) {
2858
+ const v = str5(args[k])?.trim();
2859
+ if (v)
2860
+ qs.set(k, v);
2861
+ }
2862
+ const query = qs.toString();
2863
+ const path = query ? `/proxy/metrics?${query}` : "/proxy/metrics";
2864
+ const noReport = { text: "SLEDS answered without a metrics report.", isError: true };
2865
+ if (!ctx.client.getFull) {
2866
+ const j = await ctx.client.get(path);
2867
+ if (!j)
2868
+ return UNREACHABLE;
2869
+ const report = asMetricsReport(j);
2870
+ return report ? { text: metricsText(report) } : noReport;
2871
+ }
2872
+ const r = await ctx.client.getFull(path);
2873
+ if ("error" in r)
2874
+ return {
2875
+ text: `Control plane unreachable: ${r.error} → try again in a moment.`,
2876
+ isError: true
2877
+ };
2878
+ const why = errorMessage(r.json);
2879
+ if (r.status === 200) {
2880
+ const report = asMetricsReport(r.json);
2881
+ return report ? { text: metricsText(report) } : noReport;
2882
+ }
2883
+ const workspace = qs.get("workspace");
2884
+ if (r.status === 404)
2885
+ return {
2886
+ text: workspace ? `No workspace "${workspace}" that this seat sees. Leave workspace out for the whole org, one line per workspace.` : `${why ?? "Not found"} (HTTP 404).`,
2887
+ isError: true
2888
+ };
2889
+ if (r.status === 400)
2890
+ return { text: why ?? "Bad request (HTTP 400).", isError: true };
2891
+ if (r.status >= 500)
2892
+ return {
2893
+ text: `${why ?? "Control plane unreachable"} (HTTP ${r.status}) → try once more in a moment, then move on and say so.`,
2894
+ isError: true
2895
+ };
2896
+ return { text: `${why ?? "SLEDS refused it"} (HTTP ${r.status}).`, isError: true };
2897
+ }
2709
2898
  function bandLine(band) {
2710
2899
  if (!isObject4(band))
2711
2900
  return null;
@@ -3328,7 +3517,12 @@ async function sledTool(ctx, args) {
3328
3517
  return UNREACHABLE;
3329
3518
  const rows = (k) => Array.isArray(r[k]) ? r[k].filter(isObject4) : [];
3330
3519
  return {
3331
- text: sledText({ mine: rows("mine"), proposed: rows("proposed"), sent: rows("sent") }, (ctx.now ?? Date.now)())
3520
+ text: sledText({
3521
+ mine: rows("mine"),
3522
+ proposed: rows("proposed"),
3523
+ ...typeof r.proposedCount === "number" ? { proposedCount: r.proposedCount } : {},
3524
+ sent: rows("sent")
3525
+ }, (ctx.now ?? Date.now)())
3332
3526
  };
3333
3527
  }
3334
3528
  function checkWarningsOf(ctx, drafts) {
@@ -4300,6 +4494,8 @@ async function callTool(name, args, ctx) {
4300
4494
  switch (name) {
4301
4495
  case "usage":
4302
4496
  return usageTool(ctx);
4497
+ case "metrics":
4498
+ return metricsTool(ctx, args);
4303
4499
  case "estimate":
4304
4500
  return estimateTool(ctx, args);
4305
4501
  case "intake":
@@ -4439,6 +4635,7 @@ async function handleLine(line, ctx) {
4439
4635
  }
4440
4636
  var PROTOCOL_VERSION = "2025-06-18", SERVER_INFO, SERVER_INSTRUCTIONS, MCP_TIMEOUT_MS = 5000, sourceSchema, specSchema, TOOLS, VIEW_TOOLS, NOT_SET_UP, UNREACHABLE, isObject4 = (v) => typeof v === "object" && v !== null && !Array.isArray(v), num3 = (v) => typeof v === "number" && Number.isFinite(v) ? v : undefined, str5 = (v) => typeof v === "string" ? v : undefined, errorMessage = (j) => isObject4(j?.error) ? str5(j.error.message) : str5(j?.error), proposalText = (t) => (t ?? "").replace(/\n*Nothing runs until a person says yes:[^\n]*$/, ""), PROPOSED_NEXT = (key) => `Nothing runs until a person approves it: Approve in the SLEDS app or on the item page, or \`sleds route approve ${key}\`. If you are a planning session, stop here.`, strList = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string") : undefined, RELATION_HOWS, UI_RESOURCES, response = (id, result) => JSON.stringify({ jsonrpc: "2.0", id, result }), errorResponse = (id, code, message) => JSON.stringify({ jsonrpc: "2.0", id, error: { code, message } });
4441
4637
  var init_server = __esm(() => {
4638
+ init_report();
4442
4639
  init_worth();
4443
4640
  init_intake();
4444
4641
  init_model();
@@ -4506,6 +4703,32 @@ var init_server = __esm(() => {
4506
4703
  description: "The SLEDS meter for this seat: built today, month against the ceiling, window and reset, allowance, queued/running/delivered jobs, the last wall, and the seat's own Pro/Max limit bars.",
4507
4704
  inputSchema: { type: "object", properties: {} }
4508
4705
  },
4706
+ {
4707
+ name: "metrics",
4708
+ description: "DORA and batch-size metrics for a period, against the same length just before it: deploy frequency, lead time, change failure rate, time to recover and production deploys by batch size. For one workspace, or — with no `workspace` — the whole org, one line per workspace. Only the workspaces this seat sees. The same days the Metrics page counts.",
4709
+ inputSchema: {
4710
+ type: "object",
4711
+ properties: {
4712
+ workspace: {
4713
+ type: "string",
4714
+ description: "The workspace's slug. Leave it out for the whole org."
4715
+ },
4716
+ range: {
4717
+ type: "string",
4718
+ enum: METRICS_RANGES.map((r) => r.key),
4719
+ description: "A preset period ending today; default 2w. Leave it out when giving from."
4720
+ },
4721
+ from: {
4722
+ type: "string",
4723
+ description: "First day of a custom period, YYYY-MM-DD (UTC). At most 366 days."
4724
+ },
4725
+ to: {
4726
+ type: "string",
4727
+ description: "Last day of a custom period, YYYY-MM-DD, included; default today."
4728
+ }
4729
+ }
4730
+ }
4731
+ },
4509
4732
  {
4510
4733
  name: "estimate",
4511
4734
  description: "Call this BEFORE starting any build that will take more than a few minutes — before the first line of work, not after. Sizes the task: the org estimator's cost and time band with confidence and a spend cap, never a point figure. Pass a stable `source` (kind · project · doc · item) so the item has a home on the sled and the later `actual` finds it. Recorded, so actuals calibrate the next estimate.",
@@ -5443,12 +5666,6 @@ var init_recommend = __esm(() => {
5443
5666
  var init_profile2 = __esm(() => {
5444
5667
  init_profile();
5445
5668
  });
5446
- // ../../packages/shared/src/item/outcome.ts
5447
- var OUTCOME_WINDOW_DAYS = 14, OUTCOME_WINDOW_MS;
5448
- var init_outcome = __esm(() => {
5449
- OUTCOME_WINDOW_MS = OUTCOME_WINDOW_DAYS * 86400000;
5450
- });
5451
-
5452
5669
  // ../../packages/shared/src/slack/mention.ts
5453
5670
  var MENTION_HELP;
5454
5671
  var init_mention = __esm(() => {
@@ -6534,30 +6751,12 @@ var init_deploys = __esm(() => {
6534
6751
  SERVICE_RE = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,39}$/;
6535
6752
  });
6536
6753
 
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
6754
  // ../../packages/shared/src/deploys/stability.ts
6550
6755
  var init_stability = __esm(() => {
6551
6756
  init_outcome();
6552
6757
  init_metrics();
6553
6758
  });
6554
6759
 
6555
- // ../../packages/shared/src/deploys/batchSize.ts
6556
- var init_batchSize = __esm(() => {
6557
- init_outcome();
6558
- init_metrics();
6559
- });
6560
-
6561
6760
  // ../../packages/shared/src/newrelic/newrelic.ts
6562
6761
  var init_newrelic = () => {};
6563
6762
 
@@ -7968,6 +8167,7 @@ var init_src = __esm(() => {
7968
8167
  init_period();
7969
8168
  init_stability();
7970
8169
  init_batchSize();
8170
+ init_report();
7971
8171
  init_sentry();
7972
8172
  init_newrelic();
7973
8173
  init_musher();
@@ -8692,6 +8892,7 @@ init_metrics();
8692
8892
  init_period();
8693
8893
  init_stability();
8694
8894
  init_batchSize();
8895
+ init_report();
8695
8896
  init_sentry();
8696
8897
  init_newrelic();
8697
8898
  init_musher();
@@ -11248,7 +11449,7 @@ function beatBody(state, flags, host = {}, cap = {}) {
11248
11449
  name: flags.name,
11249
11450
  os: host.os ?? process.platform,
11250
11451
  runner: flags.runner,
11251
- version: host.version ?? "0.1.50" ?? "dev",
11452
+ version: host.version ?? "0.1.51" ?? "dev",
11252
11453
  running: live.length,
11253
11454
  items: live.slice(0, BEAT_ITEMS).map((r) => `${r.item}/${r.node}`),
11254
11455
  ...cap.atOnce !== undefined ? { atOnce: cap.atOnce } : {},
@@ -16973,7 +17174,7 @@ async function fetchVersion(o) {
16973
17174
  const platform = o.platform ?? process.platform;
16974
17175
  const arch = o.arch ?? process.arch;
16975
17176
  const publicKey = o.publicKey ?? RELEASE_PUBLIC_KEY;
16976
- const running = o.running ?? "0.1.50";
17177
+ const running = o.running ?? "0.1.51";
16977
17178
  if (!publicKey)
16978
17179
  return { ok: false, why: "no release key yet" };
16979
17180
  if (!VERSION_RE2.test(o.version))
@@ -18557,7 +18758,7 @@ function engineClient(o, org) {
18557
18758
  return fetchClient({
18558
18759
  ...src,
18559
18760
  timeoutMs: ENGINE_TIMEOUT_MS,
18560
- version: "0.1.50"
18761
+ version: "0.1.51"
18561
18762
  });
18562
18763
  const asked = org?.trim() || env.SLEDS_ORG?.trim();
18563
18764
  if (asked && !selectOrg(readConfig(o.home), org, env).seat)
@@ -18848,7 +19049,7 @@ async function driveEngine(o, flags, deps, until = {}) {
18848
19049
  runner: deps.runner.name,
18849
19050
  atOnce: flags.atOnce,
18850
19051
  interval: flags.interval,
18851
- cliVersion: "0.1.50"
19052
+ cliVersion: "0.1.51"
18852
19053
  };
18853
19054
  const beat = (checkedAt) => {
18854
19055
  const m = deps.machine;
@@ -20705,7 +20906,7 @@ function engineClient2(o, org) {
20705
20906
  return fetchClient({
20706
20907
  ...src,
20707
20908
  timeoutMs: ENGINE_TIMEOUT_MS2,
20708
- version: "0.1.50"
20909
+ version: "0.1.51"
20709
20910
  });
20710
20911
  const asked = org?.trim() || env.SLEDS_ORG?.trim();
20711
20912
  if (asked && !selectOrg(readConfig(o.home), org, env).seat)
@@ -21031,7 +21232,7 @@ async function driveEngine2(o, flags, deps, until = {}) {
21031
21232
  runner: deps.runner.name,
21032
21233
  atOnce: flags.atOnce,
21033
21234
  interval: flags.interval,
21034
- cliVersion: "0.1.50"
21235
+ cliVersion: "0.1.51"
21035
21236
  };
21036
21237
  const beat = (checkedAt) => {
21037
21238
  const m = deps.machine;
@@ -23119,7 +23320,7 @@ function contextFor(deps) {
23119
23320
  ...src,
23120
23321
  fetchFn: deps.fetchFn,
23121
23322
  timeoutMs: deps.timeoutMs,
23122
- version: "0.1.50"
23323
+ version: "0.1.51"
23123
23324
  }), deps.home, now) : null;
23124
23325
  return {
23125
23326
  channel: "code",
@@ -27205,7 +27406,7 @@ var realPidAlive4 = (pid) => {
27205
27406
  };
27206
27407
  function machineClient(home, env) {
27207
27408
  const src = meterSource(home, undefined, { env });
27208
- return src ? fetchClient({ ...src, version: "0.1.50" }) : null;
27409
+ return src ? fetchClient({ ...src, version: "0.1.51" }) : null;
27209
27410
  }
27210
27411
  async function noteAnswer2(home, a, now) {
27211
27412
  try {
@@ -28050,7 +28251,7 @@ var main = async (argv) => {
28050
28251
  now: Date.now(),
28051
28252
  stderr: (line) => console.error(line),
28052
28253
  isTTY: !!process.stderr.isTTY,
28053
- version: "0.1.50"
28254
+ version: "0.1.51"
28054
28255
  });
28055
28256
  switch (cmd) {
28056
28257
  case "update":
@@ -28283,7 +28484,7 @@ ${renderHelpText(argv[1])}`);
28283
28484
  case "version":
28284
28485
  case "--version":
28285
28486
  case "-v":
28286
- console.log("sleds 0.1.50");
28487
+ console.log("sleds 0.1.51");
28287
28488
  return 0;
28288
28489
  default:
28289
28490
  console.error(`unknown command: ${cmd}
@@ -28304,10 +28505,18 @@ var isMain = () => {
28304
28505
  return false;
28305
28506
  }
28306
28507
  };
28508
+ var drained = (stream) => new Promise((resolve) => {
28509
+ stream.once("error", () => resolve());
28510
+ stream.write("", () => resolve());
28511
+ });
28512
+ var exitDrained = async (code) => {
28513
+ await Promise.all([drained(process.stdout), drained(process.stderr)]);
28514
+ process.exit(code);
28515
+ };
28307
28516
  if (isMain()) {
28308
- main(process.argv.slice(2)).then((code) => process.exit(code), (err) => {
28517
+ main(process.argv.slice(2)).then((code) => exitDrained(code), (err) => {
28309
28518
  console.error(err instanceof Error ? err.message : String(err));
28310
- process.exit(1);
28519
+ return exitDrained(1);
28311
28520
  });
28312
28521
  }
28313
28522
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sleds/cli",
3
- "version": "0.1.50",
3
+ "version": "0.1.51",
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",