maxpool 1.5.21 → 1.5.22

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/tui.js +45 -23
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "maxpool",
3
- "version": "1.5.21",
3
+ "version": "1.5.22",
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",
package/src/tui.js CHANGED
@@ -183,7 +183,18 @@ function bar(ratio, w = 10, resetTs) {
183
183
  return out;
184
184
  }
185
185
 
186
- export const __tuiTest = { formatReset, quotaLabel, bar, strip, loadText, countdown };
186
+ // A gray placeholder the EXACT visible width of a bar(), for a quota that's absent
187
+ // or unpollable (label "—" / "n/a" / "probing"). Mirrors bar()'s no-data branch so
188
+ // provider rows stay column-aligned with OAuth rows.
189
+ function emptyBar(label, w = 10) {
190
+ const text = String(label).slice(0, w);
191
+ const pad = Math.max(0, w - text.length);
192
+ const lp = Math.floor(pad / 2);
193
+ const rp = pad - lp;
194
+ return `${ESC}100m${' '.repeat(lp)}${text}${' '.repeat(rp)}${RESET}`;
195
+ }
196
+
197
+ export const __tuiTest = { formatReset, quotaLabel, bar, emptyBar, strip, loadText, countdown };
187
198
 
188
199
  function timestamp() {
189
200
  return new Date().toLocaleTimeString('en-US', { hour12: false });
@@ -940,8 +951,10 @@ export class TUI {
940
951
  const rawName = a.name.slice(0, 12).padEnd(12);
941
952
  const name = isSel ? bold(rawName) : rawName;
942
953
 
943
- // Type
944
- const type = gray(a.type.padEnd(7));
954
+ // Type — pad to 8 so "provider" (8 chars) doesn't overflow a 7-wide column and
955
+ // shift the whole provider row (incl. its quota bars) 1 char out of alignment
956
+ // with the "oauth"/"apikey" rows.
957
+ const type = gray(a.type.padEnd(8));
945
958
 
946
959
  // Status
947
960
  let status;
@@ -1039,35 +1052,44 @@ export class TUI {
1039
1052
  }
1040
1053
 
1041
1054
  _renderProviderAcct(sel, cur, name, type, status, a, bw = 11, showBoth = true) {
1042
- const completed = a.completedRequests || 0;
1043
- const failed = a.failedRequests || 0;
1044
- const active = a.inFlight || 0;
1045
- const last = a.lastStatus ? `${statusColor(a.lastStatus)} ${formatMs(a.lastResponseMs)}` : '-';
1046
1055
  const q = a.quota || {};
1047
1056
 
1048
- // Quota segment. z.ai has a pollable monitor endpoint → real Ses/Wk token bars,
1049
- // same rendering as OAuth accounts. Kimi (Moonshot coding key) has NO pollable
1050
- // quota (web console only) → an honest label, never a fake bar. Fields are the
1051
- // SEPARATE provider* set, so a provider reading never leaks into an OAuth bar.
1052
- let quotaSeg = '';
1057
+ // Ses/Wk bars in the SAME columns as OAuth rows (right after status) so the
1058
+ // whole table's bars line up. z.ai exposes a 5-hour token window (Ses) and —
1059
+ // when its monitor endpoint includes it — a weekly (Wk, intermittently absent →
1060
+ // "—"). Kimi's coding key has NO pollable quota (web console only) → "n/a" both
1061
+ // + a "console-only" note; not-yet-probed → "probing". Fields are the SEPARATE
1062
+ // provider* set, so a provider reading never leaks into an OAuth bar.
1063
+ let sesCell, wkCell, note = '';
1053
1064
  if (q.providerSes != null || q.providerWk != null) {
1054
- quotaSeg = ` Ses ${bar(q.providerSes, bw, q.providerSesReset)}`;
1055
- if (showBoth && q.providerWk != null) quotaSeg += ` Wk ${bar(q.providerWk, bw, q.providerWkReset)}`;
1056
- if (this.am._quotaProbeStale?.(a)) quotaSeg += ` ${dim('stale')}`;
1065
+ sesCell = q.providerSes != null ? bar(q.providerSes, bw, q.providerSesReset) : emptyBar('—', bw);
1066
+ wkCell = q.providerWk != null ? bar(q.providerWk, bw, q.providerWkReset) : emptyBar('—', bw);
1067
+ if (this.am._quotaProbeStale?.(a)) note = ` ${dim('stale')}`;
1057
1068
  } else if (q.providerQuotaSource === 'console-only') {
1058
- quotaSeg = ` ${dim('Quota console-only')}`;
1059
- } else if (q.providerQuotaSource === 'zai') {
1060
- quotaSeg = ` ${dim('Ses/Wk probing')}`;
1069
+ sesCell = emptyBar('n/a', bw);
1070
+ wkCell = emptyBar('n/a', bw);
1071
+ note = ` ${dim('console-only')}`;
1072
+ } else {
1073
+ sesCell = emptyBar('probing', bw);
1074
+ wkCell = emptyBar('probing', bw);
1061
1075
  }
1062
1076
 
1063
- let limit = '';
1077
+ let line = ` ${sel}${cur} ${name} ${type} ${status} Ses ${sesCell}`;
1078
+ if (showBoth) line += ` Wk ${wkCell}`;
1079
+ line += note;
1080
+ // Same recent-load columns as OAuth (providers track inFlight + load events),
1081
+ // plus a compact Last <status> <ms> — the one signal that matters for a
1082
+ // rarely-hit fallback (loadText reads 0r when idle).
1083
+ line += ` ${dim(loadText(this._accountLoad(a)))}`;
1084
+ if (a.lastStatus) line += ` ${dim('Last')} ${statusColor(a.lastStatus)} ${dim(formatMs(a.lastResponseMs))}`;
1085
+ // Header-derived generic rate-limit (distinct from the monitor-endpoint quota),
1086
+ // if the provider upstream returns x-ratelimit-* headers — only when present.
1064
1087
  if (q.genericLimit != null && q.genericRemaining != null) {
1065
- const used = q.genericLimit - q.genericRemaining;
1066
1088
  const reset = formatReset(q.genericReset);
1067
- limit = ` Lim ${used}/${q.genericLimit}${reset ? ` ${reset}` : ''}`;
1089
+ line += ` ${dim(`Lim ${q.genericLimit - q.genericRemaining}/${q.genericLimit}${reset ? ' ' + reset : ''}`)}`;
1068
1090
  }
1069
- const err = a.lastError ? ` Err ${String(a.lastError).slice(0, 18)}` : '';
1070
- return ` ${sel}${cur} ${name} ${type} ${status} Act ${String(active).padStart(2)} OK ${String(completed).padStart(3)} Fail ${String(failed).padStart(2)} Last ${last}${quotaSeg} ${dim(loadText(this._accountLoad(a)))}${limit}${err}`;
1091
+ if (a.lastError) line += ` ${red('Err ' + String(a.lastError).slice(0, 18))}`;
1092
+ return line;
1071
1093
  }
1072
1094
 
1073
1095
  _accountLoad(account) {