maxpool 1.5.61 → 1.5.62

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.61",
3
+ "version": "1.5.62",
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",
@@ -176,6 +176,10 @@ const LOAD_EVENT_MAX_AGE_MS = 60 * 60 * 1000;
176
176
  // fall back to per-account handling. Bounds any future "poisoned probe" from becoming
177
177
  // an indefinite fleet-wide outage (2026-07-25 incident).
178
178
  const MAX_FAILED_PROBES = 4;
179
+ // Consecutive quota-probe failures before we say so. High enough that a network blip or a
180
+ // single 429 never trips it; low enough that a permanently dead endpoint surfaces the same
181
+ // day rather than never.
182
+ const PROBE_FAILURE_ALERT_AT = 20;
179
183
  const WEEK_MS = 7 * 24 * 60 * 60 * 1000;
180
184
  const FIVE_HOUR_MS = 5 * 60 * 60 * 1000;
181
185
 
@@ -2183,6 +2187,8 @@ export class AccountManager {
2183
2187
  * Same effect as learning quota from a live response, but for idle accounts.
2184
2188
  */
2185
2189
  applyUsageData(accountIndex, usage) {
2190
+ // A successful probe ends any escalation streak.
2191
+ if (this.accounts[accountIndex]?.quota) this.accounts[accountIndex].quota.consecutiveProbeFailures = 0;
2186
2192
  const account = this.accounts[accountIndex];
2187
2193
  if (!account || !usage) return;
2188
2194
  const q = account.quota;
@@ -2257,6 +2263,22 @@ export class AccountManager {
2257
2263
  q.lastProbeError = message ? String(message).slice(0, 160) : 'probe failed';
2258
2264
  q.lastProbeErrorAt = Date.now();
2259
2265
  q.lastProbeErrorStatus = Number.isFinite(status) ? status : null;
2266
+ // ESCALATE A SYSTEMIC PROBE FAILURE. These fields were written and never read by
2267
+ // anything, so a probe that fails on EVERY call did so in total silence — measured
2268
+ // 2026-08-06: both quota endpoints (/v1/usages and /v1/usage) return 404, so weekly
2269
+ // quota was only ever learned from upstream 429 headers, and an account that had not
2270
+ // yet hit a 429 showed a blank weekly forever with no indication why.
2271
+ // A fail-open probe that never says it is failing is a log line, not a detector.
2272
+ q.consecutiveProbeFailures = (q.consecutiveProbeFailures || 0) + 1;
2273
+ const n = q.consecutiveProbeFailures;
2274
+ // Once, at a threshold that cannot be a blip, then every 100th so it stays visible
2275
+ // without walling the log.
2276
+ if (n === PROBE_FAILURE_ALERT_AT || (n > PROBE_FAILURE_ALERT_AT && n % 100 === 0)) {
2277
+ console.error(`[Maxpool] Quota probe has failed ${n}x in a row for "${account.name}"`
2278
+ + `${status ? ` (HTTP ${status})` : ''}: ${q.lastProbeError}. `
2279
+ + 'Weekly quota can only be learned from upstream 429 headers until this recovers, '
2280
+ + 'so an account that has not hit a 429 will show a blank weekly.');
2281
+ }
2260
2282
  }
2261
2283
 
2262
2284
  /**