maxpool 1.5.19 → 1.5.20
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 +1 -1
- package/src/account-manager.js +36 -0
package/package.json
CHANGED
package/src/account-manager.js
CHANGED
|
@@ -974,16 +974,52 @@ export class AccountManager {
|
|
|
974
974
|
*/
|
|
975
975
|
refreshExpiredQuotas() {
|
|
976
976
|
let changed = false;
|
|
977
|
+
const now = Date.now();
|
|
977
978
|
const sessionReset = [];
|
|
978
979
|
for (const account of this.accounts) {
|
|
979
980
|
const r = this._clearExpiredQuotas(account);
|
|
980
981
|
if (r.changed) changed = true;
|
|
981
982
|
if (r.session) sessionReset.push(account);
|
|
983
|
+
this._clearRecoveredNetworkError(account, now);
|
|
982
984
|
}
|
|
983
985
|
if (sessionReset.length) this._switchOnSessionReset(sessionReset);
|
|
984
986
|
return changed;
|
|
985
987
|
}
|
|
986
988
|
|
|
989
|
+
/**
|
|
990
|
+
* Clear a fully-healed transient error so a long-gone blip stops showing as a
|
|
991
|
+
* phantom "Err" in the TUI. A network blip (markTransientFailure network:true)
|
|
992
|
+
* and an expired upstream_throttled window both set `lastError` WITHOUT bumping
|
|
993
|
+
* `consecutiveFailures`; once the account is active again with no live backoff
|
|
994
|
+
* window, that error is history. Runs for EVERY account on the display/request
|
|
995
|
+
* refresh — required (not just `_isAvailable`, which never evaluates an idle
|
|
996
|
+
* fallback provider that Claude-health keeps out of the candidate set, so its
|
|
997
|
+
* blip lingered ~100 min until restart). Mirrors the rate_limited /
|
|
998
|
+
* upstream_throttled recovery clears in `_isAvailable`.
|
|
999
|
+
*
|
|
1000
|
+
* The `consecutiveFailures > 0` guard is load-bearing: a genuinely-flaky account
|
|
1001
|
+
* (markResult failure — windowless, status active, counter bumped) must KEEP its
|
|
1002
|
+
* error visible. Only the fleet-wide-blip paths leave the counter at 0.
|
|
1003
|
+
*/
|
|
1004
|
+
_clearRecoveredNetworkError(account, now = Date.now()) {
|
|
1005
|
+
if (!account.lastError) return;
|
|
1006
|
+
if (account.status !== 'active') return; // throttled / error / exhausted keep their error
|
|
1007
|
+
if (account.consecutiveFailures > 0) return; // an ongoing per-account fault stays visible
|
|
1008
|
+
const blocked = Math.max(
|
|
1009
|
+
account.cooldownUntil || 0,
|
|
1010
|
+
account.rateLimitedUntil || 0,
|
|
1011
|
+
account.provisionalUpstreamUntil || 0,
|
|
1012
|
+
);
|
|
1013
|
+
if (blocked && now < blocked) return; // still in a backoff window → keep showing why
|
|
1014
|
+
account.lastError = null;
|
|
1015
|
+
account.lastErrorAt = null;
|
|
1016
|
+
// Mirror _isAvailable's recovery: drop the now-past backoff windows + fingerprint
|
|
1017
|
+
// so getStatus() doesn't emit a stale past cooldown and no fingerprint dangles.
|
|
1018
|
+
account.cooldownUntil = null;
|
|
1019
|
+
account.provisionalUpstreamUntil = null;
|
|
1020
|
+
account.provisionalUpstreamFingerprint = null;
|
|
1021
|
+
}
|
|
1022
|
+
|
|
987
1023
|
/**
|
|
988
1024
|
* Given accounts whose session quota just reset, switch to the one whose
|
|
989
1025
|
* weekly limit expires soonest — but only if that is sooner than the current
|