maxpool 1.10.4 → 1.11.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "maxpool",
3
- "version": "1.10.4",
3
+ "version": "1.11.1",
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",
@@ -111,6 +111,31 @@ const DEFAULT_SCHEDULER = {
111
111
  // it's essentially full (a near-guaranteed-waste hard-429). A real 429 sets util≈1.0
112
112
  // and still benches here. Critical (0.95-0.999) stays last-resort-only (pass 2).
113
113
  weeklyExhaustedThreshold: 0.999,
114
+ // ── Situational CRITICAL unlock (2026-08-24) ────────────────────────────────
115
+ // An account at critical (≥0.95 weekly) used to be pass-2-only: spent ONLY during
116
+ // a total-fleet outage for the exact request, so its last ~5% usually died unused
117
+ // at reset. Three situational lifts make critical reachable without an outage.
118
+ // preReset: a critical account whose weekly reset is < this many hours away is
119
+ // unlocked, and its cost decays to NEGATIVE (below an idle healthy account — a
120
+ // decay to 0 only TIES, which rotation splits ~1/N; the drain must actually win).
121
+ // Stamp-freshness required (probe or header seen recently). 0 disables.
122
+ criticalPreResetHours: 2,
123
+ // pressure: unlock when at most this many healthy+reserve routes still have
124
+ // CONCURRENCY HEADROOM for the request (an at-cap route cannot serve without
125
+ // deepening the congestion). Congestion-based, not presence-based: an idle provider
126
+ // or reserve account keeps serving and no unlock fires — critical becomes relief
127
+ // exactly when the fleet is out of headroom, and never preempts an idle route
128
+ // (cost is also ABOVE reserve's attainable max ~19, pinning the ordering).
129
+ // -1 disables; 0 = unlock only when every route is at cap.
130
+ criticalPressureUnlockRoutes: 0,
131
+ criticalPressureCost: 21,
132
+ // Cost at the OPEN of the preReset window, decaying linearly to
133
+ // -(reserveFloorCost+1) at reset — below every healthy account, bounded only by
134
+ // the concurrency cap.
135
+ criticalDrainFloorCost: 8,
136
+ // peak: unlock critical Claude accounts while a provider peak de-preference is
137
+ // ACTIVE (_peakTier ≥ 1). Default OFF — mechanism shipped, immediate use declined.
138
+ criticalPeakUnlock: false,
114
139
  weeklyBurnDebtWeight: 0.6,
115
140
  // Routing-cost tuning (lower cost = preferred). The goal is to AVOID
116
141
  // short-term (rate/concurrency) throttling by spreading load across healthy
@@ -212,6 +237,10 @@ const WEEK_MS = 7 * 24 * 60 * 60 * 1000;
212
237
  // `priority < bestPriority` is false for Infinity vs Infinity and an all-peaked pool
213
238
  // would select nothing.
214
239
  const PEAK_TIER_STRIDE = 1_000_000;
240
+
241
+ // Memo for _pressureEligibleRoutes, keyed on the requestInfo object (one selection
242
+ // pass = one requestInfo instance).
243
+ const _pressureCache = new WeakMap();
215
244
  const FIVE_HOUR_MS = 5 * 60 * 60 * 1000;
216
245
 
217
246
  // Quota fields that survive a restart: utilization levels and their reset
@@ -1734,6 +1763,7 @@ export class AccountManager {
1734
1763
  { allowWeeklyReserve: true, allowWeeklyCritical: true },
1735
1764
  ];
1736
1765
 
1766
+ const bestUnlockMap = new Map();
1737
1767
  for (const weeklyOptions of weeklyPasses) {
1738
1768
  best = null;
1739
1769
  bestScore = Infinity;
@@ -1744,14 +1774,20 @@ export class AccountManager {
1744
1774
  const account = this.accounts[idx];
1745
1775
  if (excludedIndexes.has(account.index)) continue;
1746
1776
  if (!this._matchesRequest(account, profile, requestInfo)) continue;
1747
- if (!this._isAvailable(account, { ...weeklyOptions, model: requestInfo.model, now })) continue;
1777
+ // Situational critical unlock: computed per-account per-request (pressure
1778
+ // memoized by requestInfo). pass 2 keeps its unconditional fallback.
1779
+ const critUnlock = weeklyOptions.allowWeeklyCritical
1780
+ ? null
1781
+ : this._criticalUnlock(account, requestInfo, excludedIndexes, null, now);
1782
+ if (!this._isAvailable(account, { ...weeklyOptions, allowWeeklyCritical: weeklyOptions.allowWeeklyCritical || !!critUnlock, model: requestInfo.model, now })) continue;
1748
1783
 
1749
1784
  const priority = this._effectivePriority(account, requestInfo, now);
1750
- const score = this._scoreAccount(account, requestInfo, scoringCtx);
1785
+ const score = this._scoreAccount(account, requestInfo, scoringCtx, critUnlock);
1751
1786
  if (priority < bestPriority || (priority === bestPriority && score < bestScore)) {
1752
1787
  bestPriority = priority;
1753
1788
  bestScore = score;
1754
1789
  best = account;
1790
+ if (critUnlock) bestUnlockMap.set(account.name, critUnlock); else bestUnlockMap.delete(account.name);
1755
1791
  }
1756
1792
  }
1757
1793
 
@@ -1759,6 +1795,19 @@ export class AccountManager {
1759
1795
  const switched = best.index !== this.currentIndex;
1760
1796
  this.currentIndex = best.index;
1761
1797
  this.nextIndex = (best.index + 1) % this.accounts.length;
1798
+ // Unlock visibility: ONE line per account+reason when a critical account
1799
+ // first serves via a situational unlock (per-request would spam the log).
1800
+ const usedUnlock = bestUnlockMap.get(best.name);
1801
+ if (usedUnlock) {
1802
+ const key = usedUnlock.reason;
1803
+ if (best._lastUnlockLogged !== key) {
1804
+ best._lastUnlockLogged = key;
1805
+ const eta = usedUnlock.etaMs != null ? ` (reset in ${(usedUnlock.etaMs / 60000).toFixed(0)}m)` : '';
1806
+ console.log(`[Maxpool] Critical unlock "${key}": routing to "${best.name}"${eta}`);
1807
+ }
1808
+ } else if (best._lastUnlockLogged) {
1809
+ best._lastUnlockLogged = null; // state left critical — re-log next unlock
1810
+ }
1762
1811
  // If we switched to an account whose weekly quota is still unknown, flag
1763
1812
  // it so we re-evaluate once that quota is learned (see updateQuota).
1764
1813
  best.probing = best.quota.unified7dReset == null;
@@ -1976,6 +2025,11 @@ export class AccountManager {
1976
2025
  // ranks strictly below every non-peak account in EVERY routing mode with no
1977
2026
  // per-mode branch. Tier 0 returns base IDENTICALLY — off-peak behaviour is
1978
2027
  // byte-identical to the pre-peak implementation (SC2 by construction).
2028
+ // The critical unlock deliberately does NOT touch this axis: priority dominates
2029
+ // score, so any unlock tier here would block same-family relief entirely. The
2030
+ // unlock's cross-class posture is enforced by the CONGESTION gate instead (an
2031
+ // idle provider has headroom → no pressure unlock → provider keeps serving), and
2032
+ // by the score cost (21 > reserve's max 19).
1979
2033
  const base = this._basePriority(account, requestInfo);
1980
2034
  const tier = this._peakTier(account, now);
1981
2035
  return tier === 0 ? base : base + tier * PEAK_TIER_STRIDE;
@@ -2406,7 +2460,7 @@ export class AccountManager {
2406
2460
  * - ramp: ease a just-recovered account back in instead of slamming it
2407
2461
  * - failures: direct per-account backoff after errors
2408
2462
  */
2409
- _scoreAccount(account, requestInfo = {}, ctx = null) {
2463
+ _scoreAccount(account, requestInfo = {}, ctx = null, criticalUnlock = null) {
2410
2464
  const now = ctx?.now ?? Date.now();
2411
2465
  const reqWeight = Math.max(1, requestInfo.weight || 1);
2412
2466
  const inflight = account.activeWeight + reqWeight;
@@ -2422,7 +2476,10 @@ export class AccountManager {
2422
2476
  // bites sooner — load fans out across the fleet before a low-quota account is
2423
2477
  // dogpiled toward a 429.
2424
2478
  const weeklyState = this._weeklyRawState(account);
2425
- const concTarget = weeklyState === 'reserve'
2479
+ // An UNLOCKED critical account is the lowest-headroom tier of all — it gets the
2480
+ // same tight target as reserve (red team finding A: inheriting the looser
2481
+ // per-account target removed the anti-dogpile cap exactly where quota is lowest).
2482
+ const concTarget = (weeklyState === 'reserve' || (weeklyState === 'critical' && criticalUnlock))
2426
2483
  ? this.scheduler.reserveConcurrencyTarget
2427
2484
  : this.scheduler.perAccountConcurrencyTarget;
2428
2485
  const capPenalty = this.scheduler.capPenaltyWeight
@@ -2457,6 +2514,7 @@ export class AccountManager {
2457
2514
 
2458
2515
  const ramp = this._recoveryRamp(account, now);
2459
2516
  const reserveCost = this._reserveCost(account, now, weeklyState);
2517
+ const criticalCost = this._criticalCost(account, now, criticalUnlock, weeklyState);
2460
2518
  const failurePenalty = account.consecutiveFailures * 5;
2461
2519
  // NO unknown-quota bonus. An account whose quota we cannot see must never be
2462
2520
  // MORE attractive than a known-healthy one — the old -0.5 nudge (safe only
@@ -2466,7 +2524,7 @@ export class AccountManager {
2466
2524
  // default) learns the real number within a cycle. `probing`/requalify still
2467
2525
  // flags a never-seen account for learning — that path is unchanged.
2468
2526
 
2469
- return concurrency + capPenalty + paceCost + utilizationCost + scopedPace + spread + ramp + reserveCost + failurePenalty;
2527
+ return concurrency + capPenalty + paceCost + utilizationCost + scopedPace + spread + ramp + reserveCost + criticalCost + failurePenalty;
2470
2528
  }
2471
2529
 
2472
2530
  /**
@@ -2562,6 +2620,108 @@ export class AccountManager {
2562
2620
  * above a lightly-loaded reserve one (its capPenalty is unbounded) — that's intended
2563
2621
  * load-spread, not a violation of "healthy first".
2564
2622
  */
2623
+ /**
2624
+ * Situational CRITICAL unlock (2026-08-24). Returns null or { reason, etaMs }:
2625
+ * - 'prereset' — the account's weekly reset lands inside criticalPreResetHours.
2626
+ * That capacity is FREE: it dies at reset regardless, so it is
2627
+ * drained FIRST (cost decays negative) while every other account's
2628
+ * weekly budget survives. Requires a FRESH reset stamp (a stale
2629
+ * future stamp with probing off must not fire the window early).
2630
+ * - 'pressure' — ≤ criticalPressureUnlockRoutes healthy+reserve routes remain
2631
+ * for THIS request (full pre-pass incl. _matchesRequest and
2632
+ * excludedIndexes — an inline count is rotation-order-dependent).
2633
+ * Relief one step BEFORE the stall, not only during it.
2634
+ * - 'peak' — a provider peak de-preference is ACTIVE (tier ≥ 1, not merely
2635
+ * in-window) and criticalPeakUnlock is enabled. Default off.
2636
+ * Precedence prereset > pressure > peak: the cheaper drain wins.
2637
+ */
2638
+ _criticalUnlock(account, requestInfo = {}, excludedIndexes = new Set(), pressureCache = null, now = Date.now()) {
2639
+ const state = this._weeklyRawState(account);
2640
+ if (state !== 'critical') return null;
2641
+
2642
+ const hours = this.scheduler.criticalPreResetHours ?? 0;
2643
+ if (hours > 0) {
2644
+ const q = account.quota;
2645
+ const resetAt = account.type === 'provider' ? q.providerWkReset : q.unified7dReset;
2646
+ const etaMs = resetAt != null ? resetAt - now : null;
2647
+ // Stamp freshness: a header or probe reading within max(2 probe intervals,
2648
+ // the window itself). Without this, quotaProbeSeconds=0 + an idle account can
2649
+ // carry a days-old future stamp and fire the drain far too early.
2650
+ const probeInterval = this.quotaProbeIntervalMs || 60_000;
2651
+ const freshBy = q.lastProbeOkAt != null && (now - q.lastProbeOkAt) < Math.max(2 * probeInterval, hours * 3600_000);
2652
+ if (etaMs != null && etaMs > 0 && etaMs <= hours * 3600_000 && freshBy) {
2653
+ return { reason: 'prereset', etaMs };
2654
+ }
2655
+ }
2656
+
2657
+ const routes = this.scheduler.criticalPressureUnlockRoutes;
2658
+ if (routes != null && routes >= 0 && this._pressureEligibleRoutes(requestInfo, excludedIndexes, now) <= routes) {
2659
+ return { reason: 'pressure' };
2660
+ }
2661
+
2662
+ if (this.scheduler.criticalPeakUnlock && this.accounts.some(a => a.type === 'provider' && this._peakTier(a, now) >= 1)) {
2663
+ return { reason: 'peak' };
2664
+ }
2665
+ return null;
2666
+ }
2667
+
2668
+ /** Full pre-pass: how many healthy+reserve routes can take THIS request NOW —
2669
+ * pass-1-eligible AND under their concurrency target (an at-cap route cannot serve
2670
+ * without joining the congestion). Congestion-based, deliberately: a presence-only
2671
+ * count forced the unlock onto the PRIORITY axis, which then blocked same-family
2672
+ * relief entirely (priority dominates score — a slammed healthy account at priority
2673
+ * 0 always beat the unlocked critical at 0+21). Counting only routes with headroom
2674
+ * keeps the unlock on the score axis where reserve/critical ordering lives.
2675
+ * Memoized per requestInfo via a module WeakMap. */
2676
+ _pressureEligibleRoutes(requestInfo = {}, excludedIndexes = new Set(), now = Date.now()) {
2677
+ let cached = _pressureCache.get(requestInfo);
2678
+ if (cached != null) return cached;
2679
+ const profile = requestInfo.profile || 'claude';
2680
+ let n = 0;
2681
+ for (const a of this.accounts) {
2682
+ if (excludedIndexes.has(a.index)) continue;
2683
+ if (!this._matchesRequest(a, profile, requestInfo)) continue;
2684
+ if (!this._isAvailable(a, { allowWeeklyReserve: true, allowWeeklyCritical: false, model: requestInfo.model, now })) continue;
2685
+ const target = this._weeklyRawState(a) === 'reserve'
2686
+ ? this.scheduler.reserveConcurrencyTarget
2687
+ : this.scheduler.perAccountConcurrencyTarget;
2688
+ if (a.activeWeight + 1 > target) continue; // at/over cap — cannot take more
2689
+ n++;
2690
+ }
2691
+ _pressureCache.set(requestInfo, n);
2692
+ return n;
2693
+ }
2694
+
2695
+ /**
2696
+ * Score cost for a situationally-unlocked critical account. State-gated exactly like
2697
+ * _reserveCost (0 for any non-critical state) so the cost cannot linger past the
2698
+ * weekly reset into the fresh 'unknown' state.
2699
+ * - prereset: decays linearly from criticalDrainFloorCost (window open) to
2700
+ * -(reserveFloorCost+1) AT reset — BELOW an idle healthy account, so dying
2701
+ * capacity is drained first (a decay to 0 only ties; rotation then splits the
2702
+ * drain ~1/N and the point is lost). Bounded by the concurrency cap, which the
2703
+ * shared target-2 keeps tight.
2704
+ * - pressure/peak: a flat cost ABOVE reserve's attainable max, so critical is
2705
+ * relief for a LOADED last route and never preempts an idle reserve.
2706
+ */
2707
+ _criticalCost(account, now = Date.now(), unlock = null, weeklyState = this._weeklyRawState(account)) {
2708
+ if (weeklyState !== 'critical') return 0;
2709
+ if (!unlock) return 0;
2710
+ if (unlock.reason === 'prereset') {
2711
+ const hours = this.scheduler.criticalPreResetHours || 1;
2712
+ const floor = this.scheduler.criticalDrainFloorCost;
2713
+ const bottom = -(this.scheduler.reserveFloorCost + 1);
2714
+ const frac = unlock.etaMs != null ? Math.max(0, Math.min(1, 1 - unlock.etaMs / (hours * 3600_000))) : 1;
2715
+ return floor + (bottom - floor) * frac;
2716
+ }
2717
+ return this.scheduler.criticalPressureCost;
2718
+ }
2719
+
2720
+ /** TUI/status summary: { reason, etaMs } or null, without request context. */
2721
+ criticalUnlockSummary(account, now = Date.now()) {
2722
+ return this._criticalUnlock(account, { profile: 'claude' }, new Set(), null, now);
2723
+ }
2724
+
2565
2725
  _reserveCost(account, now = Date.now(), weeklyState = this._weeklyRawState(account)) {
2566
2726
  if (weeklyState !== 'reserve') return 0;
2567
2727
  const q = account.quota;
package/src/tui.js CHANGED
@@ -180,7 +180,7 @@ function loadText(load) {
180
180
  return `${now} 15m ${recent}${recentAvg}${fails} 1h ${hour}`;
181
181
  }
182
182
 
183
- function weeklyPolicyText(am, account) {
183
+ export function weeklyPolicyText(am, account) {
184
184
  if (!am?._weeklyState || !account || account.type === 'provider') return '';
185
185
  const state = am._weeklyState(account);
186
186
  if (!state || state === 'unknown' || state === 'normal') return '';
@@ -191,7 +191,19 @@ function weeklyPolicyText(am, account) {
191
191
  : '';
192
192
  const paceOnly = state !== rawState && rawState !== 'exhausted';
193
193
  const label = paceOnly ? `Pace ${state}` : `Wk ${state}`;
194
- const text = paceOnly ? label : `${label}${pct}`;
194
+ let text = paceOnly ? label : `${label}${pct}`;
195
+ // Critical-unlock visibility (2026-08-24): a red "Wk critical 96%" row that is
196
+ // ACTIVELY ROUTING must say why, or the user watches a benched-looking account
197
+ // hoover traffic with no explanation (the peak-shipped-invisible lesson).
198
+ if (state === 'critical') {
199
+ const u = am.criticalUnlockSummary?.(account);
200
+ if (u) {
201
+ const eta = u.etaMs != null ? ` ${(u.etaMs / 60000).toFixed(0)}m` : '';
202
+ text += u.reason === 'prereset'
203
+ ? ` ·drain${eta}`
204
+ : u.reason === 'pressure' ? ' ·relief' : ' ·peak-relief';
205
+ }
206
+ }
195
207
  if (state === 'critical' || state === 'exhausted') return state !== rawState ? yellow(text) : red(text);
196
208
  if (state === 'reserve') return yellow(text);
197
209
  return cyan(text);
@@ -2070,6 +2082,12 @@ export class TUI {
2070
2082
  // being an estimate. `~` marks it; a measured column replaces it after the first
2071
2083
  // full window. A stale-util caveat only when we cannot prove same-window.
2072
2084
  const est = this.am.capacityEstimate?.(i, win);
2085
+ // LIVE now-column: the open cycle is the only number that moves between window
2086
+ // closes, and without it the page read as frozen (reported 2026-08-25: "they
2087
+ // don't seem to be updating at all"). Rendered on every row that has one.
2088
+ const nowOpen = ledger.openCycle(a.name, win);
2089
+ const nowTag = nowOpen && nowOpen.tokensSoFar > 0
2090
+ ? ' ' + yellow(`▸ ${formatTokens(nowOpen.tokensSoFar)} this window`) : '';
2073
2091
  if (est) {
2074
2092
  anyData = true;
2075
2093
  const caveat = est.fresh ? '' : ' (utilization reading may be from the previous window)';
@@ -2080,16 +2098,19 @@ export class TUI {
2080
2098
  const via = est.method === 'delta'
2081
2099
  ? `Δ ${(est.utilization * 100).toFixed(0)}% full` : `${(est.utilization * 100).toFixed(0)}% full`;
2082
2100
  out.push(' ' + name + ' ' + prov + ' ' + cyan(op + formatTokens(est.tokens).padStart(CW - 1))
2083
- + dim(` est from ${via}${caveat} — measured after this window completes`));
2101
+ + dim(` est from ${via}${caveat} — measured after this window completes`) + nowTag);
2084
2102
  } else {
2085
- out.push(' ' + name + ' ' + prov + ' ' + dim('no completed cycle yet'));
2103
+ out.push(' ' + name + ' ' + prov + ' ' + dim('no completed cycle yet') + nowTag);
2086
2104
  }
2087
2105
  continue;
2088
2106
  }
2089
2107
  anyData = true;
2090
2108
  const all = { Last: st.last, Prev: st.prev, 'Prev-1': st.prev1, 'Avg 3': st.avg3, 'Avg 10': st.avg10, 'All time': st.allTime };
2091
2109
  const cells = COLS.map(c => formatTokens(all[c]).padStart(CW)).join('');
2092
- out.push(' ' + name + ' ' + prov + ' ' + cells + ' ' + dim(String(st.cycles)));
2110
+ const nowOpen = ledger.openCycle(a.name, win);
2111
+ const nowTag = nowOpen && nowOpen.tokensSoFar > 0
2112
+ ? ' ' + yellow(`▸ ${formatTokens(nowOpen.tokensSoFar)}`) : '';
2113
+ out.push(' ' + name + ' ' + prov + ' ' + cells + ' ' + dim(String(st.cycles)) + nowTag);
2093
2114
  }
2094
2115
 
2095
2116
  out.push('');
@@ -2102,7 +2123,7 @@ export class TUI {
2102
2123
  : ' A session figure appears after an account\'s 5h window resets once.'));
2103
2124
  }
2104
2125
  out.push(' ' + dim('A cycle counts only if maxpool ran for all of it and the account stayed enabled.'));
2105
- out.push(' ' + dim('~ = estimated from utilization; ≥ = at least this (window joined late); Δ = exact-by-difference; ≈/wk ceiling = session rate, not a cap.'));
2126
+ out.push(' ' + dim('~ = estimated; ≥ = at least; Δ = exact-by-difference; ≈/wk = session-rate ceiling; ▸ = live this window.'));
2106
2127
  return out;
2107
2128
  }
2108
2129