maxpool 1.13.1 → 1.14.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "maxpool",
3
- "version": "1.13.1",
3
+ "version": "1.14.0",
4
4
  "description": "Multi-account Claude Code proxy with adaptive, rate-aware load balancing across Claude accounts",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -409,17 +409,31 @@ export class CapacityLedger {
409
409
  tankStats(name, window) {
410
410
  const rec = this._accounts.get(name);
411
411
  const floor = (this._readFloorOverride ?? READ_FLOOR_MS)[window] ?? 0;
412
- const usable = (rec?.[window]?.closed || []).filter(c =>
413
- c.complete && !c.disabledDuring
414
- && Number.isFinite(c.finalUtilization)
415
- && c.finalUtilization >= TANK_MIN_UTIL
416
- && (c.endedAt - c.startedAt) >= floor - 1_000);
412
+ const closed = (rec?.[window]?.closed || []).filter(c =>
413
+ c.complete && !c.disabledDuring && (c.endedAt - c.startedAt) >= floor - 1_000);
414
+ // PHYSICAL FLOOR: a tank can never be smaller than the most tokens ever
415
+ // delivered in one complete window — every token we count is a vendor token
416
+ // (C ≤ V ≤ tank), so maxDelivered ≤ tank is an invariant, not a heuristic.
417
+ // A reading implying a smaller tank is contaminated: the vendor % counted
418
+ // spend maxpool never saw (usage outside the proxy — an account also used
419
+ // directly), or the reading was stale. Measured live 2026-08-26: a window
420
+ // that delivered 497k at a reported "95% full" implied a 523k tank while an
421
+ // earlier window of the SAME account had delivered 1.53M — impossible, and
422
+ // the understated reading silently dragged the average down 3.6x.
423
+ // CLAMP, never discard: the contaminated reading is still a real lower bound
424
+ // (the tank is at least the tokens we saw), so it joins the average AT the
425
+ // floor rather than being thrown away — discarding left an account whose
426
+ // every reading was contaminated with NOTHING to show. After a plan
427
+ // downgrade the floor over-states until old cycles age out — conservative.
428
+ const maxDelivered = closed.reduce((m, c) => Math.max(m, c.tokens), 0);
429
+ const usable = closed.filter(c =>
430
+ Number.isFinite(c.finalUtilization) && c.finalUtilization >= TANK_MIN_UTIL);
417
431
  if (!usable.length) return null;
418
432
  let sum = 0, exact = 0, bounded = 0;
419
433
  for (const c of usable) {
420
434
  const observedFromStart = c.startedAt != null && c.windowStartedAt != null
421
435
  && c.startedAt <= c.windowStartedAt + 60_000;
422
- sum += c.tokens / c.finalUtilization;
436
+ sum += Math.max(c.tokens / c.finalUtilization, maxDelivered);
423
437
  if (observedFromStart) exact++; else bounded++;
424
438
  }
425
439
  const last = usable[usable.length - 1];
package/src/tui.js CHANGED
@@ -2030,120 +2030,81 @@ export class TUI {
2030
2030
  const win = this.capacityWindow === 'wk' ? 'wk' : 'ses';
2031
2031
  const ledger = this.am.capacity;
2032
2032
  const title = win === 'wk' ? 'Weekly (7d) capacity' : 'Session (5h) capacity';
2033
+ const windowLabel = win === 'wk' ? '7d windows' : '5h windows';
2033
2034
  out.push('');
2034
- out.push(` ${bold(title)} ${dim('— how many tokens each account can deliver per window')}`);
2035
+ out.push(` ${bold(title)} ${dim(`— tokens per ${windowLabel}, from completed cycles`)}`);
2035
2036
  out.push('');
2036
2037
 
2037
2038
  if (!ledger) { out.push(yellow(' Capacity ledger unavailable on this worker.')); return out; }
2038
2039
 
2039
- // Narrow terminals: drop trailing columns rather than let fitLine chop a number
2040
- // mid-digit (at W=80 the full 6-column row is 82+ chars — every row silently lost
2041
- // its last two cells). The dropped ones are the aggregates, not the observations.
2042
- // CAPACITY (tank) is the headline: tokens ÷ the vendor's own fullness at close,
2043
- // per cycle. That measures the PLAN. The delivered-token columns measure DEMAND —
2044
- // useful, but they were the headline before 2026-08-25 and read as capacity, which
2045
- // is why an account that simply went unused looked small.
2046
- const ALL_COLS = ['Capacity', 'Used now', 'Last cyc', 'Avg cyc'];
2047
- const CW = 10;
2040
+ // Owner-specified table (2026-08-26): the same shape for BOTH views —
2041
+ // Current cycle (tokens + % used) · Prev cycle · Avg across all cycles · N cycles.
2042
+ // Current is the live window (estimate while it runs; frozen into the columns at
2043
+ // close). Prev/Avg/N are the completed-cycle history. The no-weekly account's
2044
+ // weekly view approximates capacity as avg session tank × 33.6 (7×24/5h windows).
2045
+ const ALL_COLS = ['Current', 'Prev', 'Avg', 'N'];
2046
+ const CW = 11;
2048
2047
  const nameW = 12;
2049
2048
  let COLS = ALL_COLS;
2050
- while (COLS.length > 1 && (nameW + PROVIDER_W + 2 + COLS.length * CW + 16) > W) {
2049
+ while (COLS.length > 1 && (nameW + PROVIDER_W + 2 + COLS.length * CW + 14) > W) {
2051
2050
  COLS = COLS.slice(0, -1);
2052
2051
  }
2053
2052
  const header = ' ' + 'Account'.padEnd(nameW) + ' ' + 'Provider'.padEnd(PROVIDER_W) + ' '
2054
- + COLS.map(c => c.padStart(CW)).join('') + ' Basis';
2053
+ + COLS.map(c => c.padStart(CW)).join('');
2055
2054
  out.push(dimUnderline(fitLine(header, W)));
2056
2055
 
2057
- let anyData = false;
2058
2056
  for (const i of this._displayOrder()) {
2059
2057
  const a = this.am.accounts[i];
2060
2058
  if (!a) continue;
2061
2059
  if (this.hideDisabled && a.enabled === false) continue;
2062
- const noWeekly = win === 'wk' && a.type === 'provider' && a.quota?.weeklyAbsent;
2063
2060
  const name = truncate(a.name, nameW).padEnd(nameW);
2064
2061
  const prov = gray(providerLabel(a).padEnd(PROVIDER_W));
2065
- if (noWeekly) {
2066
- // No weekly limit — the favourite legacy plan. There is no weekly CAP, so a
2067
- // measured weekly capacity is a fiction; but there IS a real ceiling: the 5h
2068
- // session limit gates throughput, capping the week at (windows/wk × session
2069
- // capacity). 33.6 five-hour windows fit in 7 days — the user's own
2070
- // approximation ("from the session limits"), shipped as a ceiling, never a cap.
2071
- const t = ledger.rollingThroughput(a.name, 7);
2072
- const windowsPerWk = (7 * 24) / 5;
2073
- anyData = anyData || t.tokens > 0;
2074
- const vol = t.tokens > 0 ? formatTokens(t.tokens) : '--';
2075
- // The ceiling needs a measured session TANK (capacity, not avg delivery) —
2076
- // multiplying an old avg-delivery number understates a demand-limited account.
2062
+
2063
+ // The no-weekly plan has NO weekly window to complete — its weekly "capacity" is
2064
+ // derived: avg session tank × 33.6 (the number of 5h windows in 7 days). Shown as
2065
+ // ≈ to mark the derivation; N is the count of session cycles it rests on.
2066
+ if (win === 'wk' && a.type === 'provider' && a.quota?.weeklyAbsent) {
2077
2067
  const sesTank = this.am.capacityTank?.(i, 'ses');
2078
- const ceiling = sesTank
2079
- ? ` · ≈${formatTokens(Math.round(windowsPerWk * sesTank.avg))}/wk ceiling`
2080
- + dim(` (${windowsPerWk.toFixed(0)} × ${formatTokens(sesTank.avg)} per 5h)`)
2081
- : '';
2082
- // Always disclose the window's age boundary: today is unfinished, so the 7d
2083
- // figure grows through the day; a genuinely partial day adds the ≤-observed floor.
2084
- const note = t.partial
2085
- ? ' (≤ observed — maxpool was down part of the window; includes today, in progress)'
2086
- : ' (includes today, in progress)';
2068
+ const approx = sesTank && sesTank.n > 0
2069
+ ? `≈${formatTokens(Math.round(sesTank.avg * (7 * 24) / 5))}` : '--';
2070
+ const cellsByName = { Current: cyan(approx), Prev: '--', Avg: '--', N: sesTank?.n ? String(sesTank.n) : '--' };
2087
2071
  out.push(' ' + name + ' ' + prov + ' '
2088
- + cyan(`no weekly limit · 7d volume ${vol}`) + yellow(ceiling) + dim(note));
2072
+ + COLS.map(c => cellsByName[c].padStart(CW)).join('')
2073
+ + dim(' no weekly limit · avg 5h × 33.6'));
2089
2074
  continue;
2090
2075
  }
2091
- const st = ledger.windowStats(a.name, win);
2076
+
2092
2077
  const tank = this.am.capacityTank?.(i, win);
2093
- const nowOpen = ledger.openCycle(a.name, win);
2094
- const util = this.am._windowUtilization?.(a, win);
2095
2078
  // A reading we cannot prove is from THIS window may describe the previous one —
2096
- // the basis line says "unproven" instead of "live", but the number still renders:
2097
- // a restored reading after a restart is real data, and suppressing it would blank
2098
- // the page at exactly the moment the user opens it.
2099
- const unproven = tank?.source === 'live' && tank.fresh === false;
2100
-
2101
- // A row with NEITHER a tank nor any delivery has genuinely nothing to say. Say
2102
- // WHY in the account's own terms — "no completed cycle yet" was true and useless
2103
- // (reported 2026-08-25: an account sitting at 99% weekly rendered that line).
2104
- if (!tank && !st && !(nowOpen?.tokensSoFar > 0)) {
2105
- const why = util == null
2106
- ? 'no quota reading from this provider'
2107
- : util > 0
2108
- ? `${(util * 100).toFixed(0)}% used, but no traffic through maxpool to measure with`
2109
- : 'window empty — nothing used yet';
2110
- out.push(' ' + name + ' ' + prov + ' ' + dim(why));
2111
- continue;
2079
+ // keep the number but never mark it live; it becomes a proper column at close.
2080
+ const unprovenLive = tank?.source === 'live' && tank.fresh === false;
2081
+ const util = this.am._windowUtilization?.(a, win);
2082
+ const nowOpen = ledger.openCycle(a.name, win);
2083
+
2084
+ // Current = the live window: capacity estimate so far, tagged with how full the
2085
+ // vendor says it is. `~` estimate-from-open-window, `≥` lower bound (joined late).
2086
+ let cur = '--';
2087
+ if (tank && !(tank.source === 'live' && unprovenLive)) {
2088
+ cur = (tank.lowerBound ? '≥' : tank.source === 'live' ? '~' : '') + formatTokens(tank.avg);
2089
+ } else if (nowOpen?.tokensSoFar > 0 && util > 0) {
2090
+ cur = '~' + formatTokens(Math.round(nowOpen.tokensSoFar / util));
2112
2091
  }
2113
- anyData = true;
2114
-
2115
- // Capacity: measured tank, or the live in-window estimate. `~` = estimate from an
2116
- // open window; `≥` = we joined the window late, so the vendor's percentage counts
2117
- // spend maxpool never saw and the true tank is at least this.
2118
- const capCell = tank
2119
- ? (tank.lowerBound ? '≥' : tank.source === 'live' ? '~' : ' ') + formatTokens(tank.avg)
2120
- : '--';
2121
- const usedNow = nowOpen?.tokensSoFar > 0 ? formatTokens(nowOpen.tokensSoFar) : '--';
2092
+ const curPct = util != null && cur !== '--' ? dim(`${Math.round(util * 100)}%`) : '';
2093
+ const st = ledger.windowStats(a.name, win);
2122
2094
  const cellsByName = {
2123
- Capacity: capCell,
2124
- 'Used now': usedNow,
2125
- 'Last cyc': st ? formatTokens(st.last) : '--',
2126
- 'Avg cyc': st ? formatTokens(st.avg10) : '--',
2095
+ Current: cur.padStart(CW - (curPct ? curPct.length + 1 : 0)),
2096
+ Prev: (st?.prev != null ? formatTokens(st.prev) : '--'),
2097
+ Avg: (tank?.source === 'cycles' ? formatTokens(tank.avg) : '--'),
2098
+ N: (st ? String(st.cycles) : '--'),
2127
2099
  };
2128
- const cells = COLS.map(c => cellsByName[c].padStart(CW)).join('');
2129
-
2130
- // Basis: how the capacity number was arrived at, in one short phrase. Never a
2131
- // bare count — "3" told the reader nothing about what it was counting.
2132
- const basis = !tank ? dim('no capacity reading yet')
2133
- : tank.source === 'cycles'
2134
- ? dim(`${tank.n} full ${tank.n === 1 ? 'window' : 'windows'}`)
2135
- : dim(`${unproven ? 'from an older reading' : 'live'} · ${((tank.utilization ?? 0) * 100).toFixed(0)}% used`);
2136
- const pct = util != null && tank?.source !== 'live' ? dim(` (${(util * 100).toFixed(0)}% full now)`) : '';
2137
- out.push(' ' + name + ' ' + prov + ' ' + cyan(cells) + ' ' + basis + pct);
2100
+ const row = ' ' + name + ' ' + prov + ' '
2101
+ + COLS.map(c => cellsByName[c].padStart(CW)).join('');
2102
+ out.push(row + (curPct ? ' ' + curPct : ''));
2138
2103
  }
2139
2104
 
2140
2105
  out.push('');
2141
- if (!anyData) {
2142
- out.push(' ' + yellow('Nothing to measure yet.')
2143
- + dim(' Capacity needs traffic through maxpool plus a quota reading from the provider.'));
2144
- }
2145
- out.push(' ' + dim('Capacity = tokens delivered ÷ how full the provider said the window was.'));
2146
- out.push(' ' + dim('~ = from the window still running · ≥ = at least this (maxpool joined the window late).'));
2106
+ out.push(' ' + dim('Capacity = tokens ÷ how full the provider said the window was, at close.'));
2107
+ out.push(' ' + dim('~ = running estimate · ≥ = at least (maxpool joined late) · ≈ = avg 5h × 33.6.'));
2147
2108
  return out;
2148
2109
  }
2149
2110