maxpool 1.5.67 → 1.5.68

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.67",
3
+ "version": "1.5.68",
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",
@@ -2692,6 +2692,17 @@ export class AccountManager {
2692
2692
  // ~60s forever (hammering Anthropic's OAuth endpoint). Cleared on re-login.
2693
2693
  if (account.refreshDead) return false;
2694
2694
 
2695
+ // A DISABLED account never spends its single-use refresh token. The prober still
2696
+ // READS its quota by design (you disable an exhausted account and still want to
2697
+ // watch it recover — prober.js:73), but rotation is a WRITE that can permanently
2698
+ // brick the account: each rotation invalidates the previous token, so a refresh
2699
+ // that races a restart (or another writer) loses the new token and the account
2700
+ // dies with invalid_grant. Spending that risk on an account the user has
2701
+ // explicitly benched is never worth it — it serves its existing access token for
2702
+ // read-only probing, and re-enabling refreshes on the next real request.
2703
+ // `force` still wins: an explicit re-auth/enable path may need the rotation.
2704
+ if (!force && account.enabled === false) return true;
2705
+
2695
2706
  if (!force && !isTokenExpiringSoon(account.expiresAt)) return true;
2696
2707
 
2697
2708
  // Coalesce concurrent refreshes
@@ -3000,6 +3011,9 @@ export class AccountManager {
3000
3011
  model: entry.model || defaultModel,
3001
3012
  stripBetaHeaders: true,
3002
3013
  configSourced: true,
3014
+ // An explicitly-disabled provider in config stays benched across restarts —
3015
+ // a second GLM account you keep configured but off (a teammate's, a spare).
3016
+ enabled: entry.enabled !== false,
3003
3017
  });
3004
3018
  if (!entry.token) {
3005
3019
  const a = this.accounts.find(a => a.name === entry.name);
package/src/index.js CHANGED
@@ -537,16 +537,23 @@ async function serverWorkerCommand() {
537
537
  const logTo = argValue('--log-to');
538
538
  if (logTo) config.logDir = logTo;
539
539
 
540
- if (config.accounts.length === 0) {
540
+ // A provider-only fleet is valid: a teammate may have a GLM/Kimi key and no Claude
541
+ // account at all. Counting only `accounts` refused to start for them — the exact
542
+ // onboarding case this config-provider feature exists to serve.
543
+ if (config.accounts.length === 0 && !(Array.isArray(config.providers) && config.providers.length > 0)) {
541
544
  console.error('No accounts configured.\n');
542
545
  console.error('Add an account first:');
543
546
  console.error(' maxpool login OAuth login via browser');
544
547
  console.error(' maxpool login --api Add an API key');
548
+ console.error(' (or add a GLM/Kimi provider from the TUI: press p → a)');
545
549
  process.exit(1);
546
550
  }
547
551
 
548
552
  const accounts = await resolveAccounts(config);
549
- if (accounts.length === 0) {
553
+ // Config providers are loaded further below (they need an AccountManager first), so
554
+ // a provider-only fleet legitimately has zero accounts HERE. Only bail when there is
555
+ // nothing to load at all.
556
+ if (accounts.length === 0 && !(Array.isArray(config.providers) && config.providers.length > 0)) {
550
557
  console.error('No valid accounts after initialization');
551
558
  process.exit(1);
552
559
  }