maxpool 1.5.17 → 1.5.18

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.5.17",
3
+ "version": "1.5.18",
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",
@@ -448,6 +448,10 @@ export class AccountManager {
448
448
  hasAvailableRoute(requestInfo = {}, excludedIndexes = new Set()) {
449
449
  this.refreshExpiredQuotas();
450
450
  const profile = requestInfo.profile || 'claude';
451
+ // Route-EXISTENCE check only (order-independent `.some`): unlike the acquire
452
+ // path's re-home loop, pass ORDER doesn't matter here — the bound 2-entry set
453
+ // covers the same accounts (reserve+critical) — so it intentionally is NOT
454
+ // unified to the healthy-first ladder. Do not "sync" these.
451
455
  const hasBinding = Boolean(requestInfo.sessionKey && this.sessionBindings.has(requestInfo.sessionKey));
452
456
  const weeklyPasses = hasBinding
453
457
  ? [
@@ -1106,6 +1110,11 @@ export class AccountManager {
1106
1110
  // Keep a signed-thinking session's live migration on Claude accounts only —
1107
1111
  // don't shuttle an Anthropic-signed block onto a provider mid-session even
1108
1112
  // though _isRequestCompatible now allows providers for thinking under policy.
1113
+ // LOAD-BEARING for the absolute-near-cap `return true` below: it's what
1114
+ // guarantees that path only fires with a CLAUDE target present (a signed
1115
+ // session with no healthy Claude alt → bestScore stays Infinity → return
1116
+ // false → stays on its Claude account, never re-homed to a provider). Do not
1117
+ // remove assuming the fall-through protects signed thinking — it does not.
1109
1118
  if (requestInfo.requiresAnthropicThinkingIntegrity === true && account.type === 'provider') continue;
1110
1119
  if (!this._matchesRequest(account, profile, requestInfo)) continue;
1111
1120
  // Genuinely-healthy alternatives only (normal/soft/unknown weekly + model headroom).
@@ -1116,8 +1125,26 @@ export class AccountManager {
1116
1125
  bestTier = WEEKLY_TIER[this._weeklyPaceState(account)] ?? 0;
1117
1126
  }
1118
1127
  }
1119
- if (!Number.isFinite(bestScore)) return false; // no healthy alternative
1120
-
1128
+ if (!Number.isFinite(bestScore)) return false; // no RAW-healthy alternative → don't move (no stranding)
1129
+
1130
+ // Absolute near-cap: the bound account is genuinely low on weekly headroom
1131
+ // (RAW reserve+, not merely burning fast). Every candidate the loop kept is RAW
1132
+ // normal/soft, so this is a STRICT absolute-headroom improvement and flap-stable
1133
+ // (a reserve account can never be a target → no bounce-back). Skip the
1134
+ // concurrency-relief margin: it's calibrated for moving off a LOADED account and
1135
+ // is UNSATISFIABLE for an idle near-cap one — an idle boundScore ≈ the ~2
1136
+ // concurrency floor, so boundScore*0.5 ≈ 1 sits below every account's minimum
1137
+ // score, pinning the session to the near-exhausted account. Preserving the thin
1138
+ // remaining weekly headroom dominates concurrency spread; the per-request
1139
+ // candidate loop lands on the least-loaded healthy account, spreading the move.
1140
+ if ((WEEKLY_TIER[this._weeklyRawState(bound)] ?? 0) >= WEEKLY_TIER.reserve) return true;
1141
+
1142
+ // Otherwise the trigger was PACE-only on a RAW-healthy account — a fast-burner
1143
+ // that still has real absolute headroom (RAW soft but pace reserve/critical,
1144
+ // e.g. 79% used resetting in ~3.5d). Keep the conservative gate so it isn't
1145
+ // churned off an account that's genuinely fine: move only for a clearly-cheaper,
1146
+ // strictly-healthier-pace-tier target. (A RAW-soft/pace-normal fast-burner with
1147
+ // lots of headroom never even reaches here — _isBoundAccountHot gates it out.)
1121
1148
  return bestScore <= boundScore * REBALANCE_SCORE_MARGIN
1122
1149
  && (boundScore - bestScore) >= REBALANCE_MIN_ABS_GAP
1123
1150
  && bestTier < boundTier;
@@ -1263,7 +1290,6 @@ export class AccountManager {
1263
1290
  }
1264
1291
  }
1265
1292
 
1266
- const hasBinding = Boolean(requestInfo.sessionKey && this.sessionBindings.has(requestInfo.sessionKey));
1267
1293
  const preferred = this._preferredAccount(profile, excludedIndexes, requestInfo);
1268
1294
  if (preferred) {
1269
1295
  const preferredPasses = [
@@ -1284,16 +1310,17 @@ export class AccountManager {
1284
1310
  // Else fall through to the candidate score loop, which re-homes the session
1285
1311
  // onto the best healthy account via _bindSession on acquire.
1286
1312
 
1287
- const weeklyPasses = hasBinding
1288
- ? [
1289
- { allowWeeklyReserve: true, allowWeeklyCritical: false },
1290
- { allowWeeklyReserve: true, allowWeeklyCritical: true },
1291
- ]
1292
- : [
1293
- { allowWeeklyReserve: false, allowWeeklyCritical: false },
1294
- { allowWeeklyReserve: true, allowWeeklyCritical: false },
1295
- { allowWeeklyReserve: true, allowWeeklyCritical: true },
1296
- ];
1313
+ // Healthy-first ladder for BOTH bound and unbound sessions. A bound session
1314
+ // only reaches this loop once we've decided to LEAVE its account (rebalance
1315
+ // fired / a higher-priority account is available / the bound account is down) —
1316
+ // the sticky "stay put" path returns above without reaching here — so re-homing
1317
+ // must prefer a genuinely-healthy account and fall back to reserve/critical only
1318
+ // if none exists, never re-pick the idle reserve account it's leaving.
1319
+ const weeklyPasses = [
1320
+ { allowWeeklyReserve: false, allowWeeklyCritical: false },
1321
+ { allowWeeklyReserve: true, allowWeeklyCritical: false },
1322
+ { allowWeeklyReserve: true, allowWeeklyCritical: true },
1323
+ ];
1297
1324
 
1298
1325
  for (const weeklyOptions of weeklyPasses) {
1299
1326
  best = null;