@mauricode/token-derby 2.10.0 → 2.10.1

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/bin.js CHANGED
@@ -740,8 +740,8 @@ var HEARTBEAT_RETRY_DELAYS_MS = [1e3, 2e3, 4e3, 8e3, 15e3];
740
740
  // src/version.ts
741
741
  import { createRequire } from "module";
742
742
  function readVersion() {
743
- if ("2.10.0".length > 0) {
744
- return "2.10.0";
743
+ if ("2.10.1".length > 0) {
744
+ return "2.10.1";
745
745
  }
746
746
  try {
747
747
  const req = createRequire(import.meta.url);
@@ -1430,7 +1430,7 @@ function TokenBreakdown(props) {
1430
1430
  ] });
1431
1431
  }
1432
1432
  function StatusScreen(props) {
1433
- const { race, ownHorseId, ownHorseName, ownColors, ownUserName, lastHeartbeatAgoSec, lastHeartbeatOk, stalled, primaryModel, perSource, primaryCapped } = props;
1433
+ const { race, ownHorseId, ownHorseName, ownColors, ownUserName, lastHeartbeatAgoSec, lastHeartbeatOk, stalled, stallReason, primaryModel, perSource, primaryCapped } = props;
1434
1434
  if (!race) {
1435
1435
  return /* @__PURE__ */ jsx7(Box7, { flexDirection: "column", children: /* @__PURE__ */ jsx7(Text7, { children: "Joining race\u2026" }) });
1436
1436
  }
@@ -1504,7 +1504,11 @@ function StatusScreen(props) {
1504
1504
  " ",
1505
1505
  /* @__PURE__ */ jsx7(Text7, { color: lastHeartbeatOk ? "green" : "yellow", children: lastHeartbeatOk ? "\u2713" : "\u26A0" })
1506
1506
  ] }),
1507
- stalled && /* @__PURE__ */ jsx7(Text7, { color: "yellow", children: "\u26A0 Can't read token usage \u2014 try restarting this terminal. Your race continues." })
1507
+ stalled && /* @__PURE__ */ jsxs5(Text7, { color: "yellow", children: [
1508
+ "\u26A0 ",
1509
+ stallReason ?? "Can't read token usage",
1510
+ ". Your race continues."
1511
+ ] })
1508
1512
  ] }),
1509
1513
  primaryModel && perSource && /* @__PURE__ */ jsx7(
1510
1514
  TokenBreakdown,
@@ -1817,6 +1821,9 @@ function parseJsonl(raw) {
1817
1821
  }
1818
1822
 
1819
1823
  // src/tokens/race-tokens.ts
1824
+ function isStall(r) {
1825
+ return "stall" in r;
1826
+ }
1820
1827
  var SCALAR_READERS = {
1821
1828
  claude: sumTokens,
1822
1829
  codex: sumCodexTokens,
@@ -1831,20 +1838,22 @@ function scoreFor(race, t) {
1831
1838
  return race.counts_input ? t.input + t.output : t.output;
1832
1839
  }
1833
1840
  async function readAllSources(race, primary) {
1841
+ const primaryByConv = /* @__PURE__ */ new Map();
1834
1842
  try {
1835
1843
  const primaryMap = await BY_CONVERSATION_READERS[primary]();
1836
- const primaryByConv = /* @__PURE__ */ new Map();
1837
1844
  for (const [id, totals] of primaryMap) primaryByConv.set(id, scoreFor(race, totals));
1838
- const secondary = { claude: 0, codex: 0, gemini: 0 };
1839
- await Promise.all(
1840
- MODEL_KEYS.filter((k) => k !== primary).map(async (k) => {
1841
- secondary[k] = await SCALAR_READERS[k]().then((t) => scoreFor(race, t)).catch(() => 0);
1842
- })
1843
- );
1844
- return { secondary, primaryByConv };
1845
- } catch {
1846
- return null;
1845
+ } catch (e) {
1846
+ if (e?.code !== "ENOENT") {
1847
+ return { stall: `Can't read ${primary} token usage: ${e?.message ?? String(e)}` };
1848
+ }
1847
1849
  }
1850
+ const secondary = { claude: 0, codex: 0, gemini: 0 };
1851
+ await Promise.all(
1852
+ MODEL_KEYS.filter((k) => k !== primary).map(async (k) => {
1853
+ secondary[k] = await SCALAR_READERS[k]().then((t) => scoreFor(race, t)).catch(() => 0);
1854
+ })
1855
+ );
1856
+ return { secondary, primaryByConv };
1848
1857
  }
1849
1858
 
1850
1859
  // src/tokens/primary-cap.ts
@@ -1866,6 +1875,7 @@ var RaceScoreTracker = class {
1866
1875
  counted;
1867
1876
  seq;
1868
1877
  stalls = 0;
1878
+ lastStall = null;
1869
1879
  primary;
1870
1880
  primaryTop5;
1871
1881
  constructor(init, primary, primaryTop5) {
@@ -1880,16 +1890,19 @@ var RaceScoreTracker = class {
1880
1890
  }
1881
1891
  /**
1882
1892
  * Record a scan result.
1883
- * - `null` → stall (warning), anchors untouched.
1893
+ * - `null` or a `{ stall }` reading → stall (warning), anchors untouched. A
1894
+ * stall reading also captures its cause for the UI.
1884
1895
  * - otherwise → secondaries advance scalar lastGood (never down to 0); the
1885
1896
  * primary's per-conversation latest readings are updated (monotonic).
1886
1897
  */
1887
1898
  recordReading(reading) {
1888
- if (reading === null) {
1899
+ if (reading === null || isStall(reading)) {
1889
1900
  this.stalls += 1;
1901
+ this.lastStall = reading?.stall ?? null;
1890
1902
  return;
1891
1903
  }
1892
1904
  this.stalls = 0;
1905
+ this.lastStall = null;
1893
1906
  for (const key of MODEL_KEYS) {
1894
1907
  if (key === this.primary) continue;
1895
1908
  const v = reading.secondary[key];
@@ -1946,6 +1959,10 @@ var RaceScoreTracker = class {
1946
1959
  get stalled() {
1947
1960
  return this.stalls >= STALL_THRESHOLD;
1948
1961
  }
1962
+ /** Human-readable cause of the most recent stall (null once a good read recovers). */
1963
+ get stallReason() {
1964
+ return this.lastStall;
1965
+ }
1949
1966
  /** Cumulative primary tokens credited so far (for the UI's primary "since join" row). */
1950
1967
  primaryCounted() {
1951
1968
  return this.counted;
@@ -1985,6 +2002,7 @@ function RunRace({ active, initialState, pendingMode, ownUserName }) {
1985
2002
  const pendingRef = useRef(pendingMode);
1986
2003
  const ctrl = useRef(new AbortController());
1987
2004
  const [stalled, setStalled] = useState5(false);
2005
+ const [stallReason, setStallReason] = useState5(null);
1988
2006
  const baselineRef = useRef(initialState.acked);
1989
2007
  const [perSource, setPerSource] = useState5({ claude: 0, codex: 0, gemini: 0 });
1990
2008
  useEffect2(() => {
@@ -2006,15 +2024,16 @@ function RunRace({ active, initialState, pendingMode, ownUserName }) {
2006
2024
  new Promise((_, reject) => setTimeout(() => reject(new Error("scan timeout")), 1e4))
2007
2025
  ]);
2008
2026
  } catch {
2009
- return null;
2027
+ return { stall: "Token scan timed out" };
2010
2028
  }
2011
2029
  };
2012
2030
  runHeartbeatLoop({
2013
2031
  prepareBeat: async () => {
2014
2032
  const reading = await scanWithTimeout();
2015
2033
  tracker.recordReading(reading);
2016
- if (pendingRef.current) tracker.reprime();
2034
+ if (pendingRef.current && !isStall(reading)) tracker.reprime();
2017
2035
  setStalled(tracker.stalled);
2036
+ setStallReason(tracker.stalled ? tracker.stallReason : null);
2018
2037
  const since = tracker.secondarySinceJoin(baselineRef.current);
2019
2038
  const ps = { claude: 0, codex: 0, gemini: 0 };
2020
2039
  for (const k of MODEL_KEYS) {
@@ -2087,6 +2106,7 @@ function RunRace({ active, initialState, pendingMode, ownUserName }) {
2087
2106
  lastHeartbeatAgoSec,
2088
2107
  lastHeartbeatOk: lastHbOk,
2089
2108
  stalled,
2109
+ stallReason,
2090
2110
  primaryModel: active.primary_model,
2091
2111
  perSource,
2092
2112
  primaryCapped: primaryConversationCap(active.primary_top5 ?? false) !== Infinity
@@ -2134,14 +2154,16 @@ function raceViewFrom(resp) {
2134
2154
  };
2135
2155
  }
2136
2156
  async function buildInitialState(args) {
2137
- let now = null;
2157
+ let secondary = { claude: 0, codex: 0, gemini: 0 };
2158
+ const primaryConvAcked = {};
2138
2159
  try {
2139
- now = await readAllSources(args.active, args.active.primary_model);
2160
+ const now = await readAllSources(args.active, args.active.primary_model);
2161
+ if (!isStall(now)) {
2162
+ secondary = now.secondary;
2163
+ for (const [id, v] of now.primaryByConv) primaryConvAcked[id] = v;
2164
+ }
2140
2165
  } catch {
2141
2166
  }
2142
- const secondary = now?.secondary ?? { claude: 0, codex: 0, gemini: 0 };
2143
- const primaryConvAcked = {};
2144
- if (now) for (const [id, v] of now.primaryByConv) primaryConvAcked[id] = v;
2145
2167
  return {
2146
2168
  initialState: {
2147
2169
  acked: { ...secondary },