maxpool 1.3.0 → 1.3.1

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 +33 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "maxpool",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
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
@@ -93,16 +93,37 @@ function statusColor(status) {
93
93
  return String(status);
94
94
  }
95
95
 
96
+ /** Short live countdown to a timestamp, SINGLE-unit so it stays ≤3 chars
97
+ * ("41s"/"5m"/"23h"/"2d") and never overflows the status column: seconds under a
98
+ * minute (the common throttle cooldown), then minute/hour/day. '' once elapsed.
99
+ * Accepts a numeric ms timestamp (live account field) or an ISO string (snapshot). */
100
+ function countdown(ts) {
101
+ if (!ts) return '';
102
+ const target = typeof ts === 'string' ? Date.parse(ts) : ts;
103
+ const ms = target - Date.now();
104
+ if (!Number.isFinite(ms) || ms <= 0) return '';
105
+ if (ms < 60_000) return `${Math.ceil(ms / 1000)}s`;
106
+ if (ms < 3_600_000) return `${Math.ceil(ms / 60_000)}m`;
107
+ if (ms < 86_400_000) return `${Math.ceil(ms / 3_600_000)}h`;
108
+ return `${Math.ceil(ms / 86_400_000)}d`;
109
+ }
110
+
96
111
  function loadText(load) {
97
112
  const cur = load?.current || {};
98
113
  const m15 = load?.last15m || {};
99
114
  const h1 = load?.last1h || {};
100
- const current = `${cur.inFlight || 0}/${cur.activeWeight || 0}`;
115
+ // "Now" = what this account is handling right THIS moment: N in-flight requests
116
+ // (and their combined weight ~ payload size, the scheduler's load input). Kept
117
+ // distinct from the "15m"/"1h" THROUGHPUT counts that follow, which the old
118
+ // "Load X/Y" label collided with.
119
+ const inflight = cur.inFlight || 0;
120
+ const weight = cur.activeWeight || 0;
121
+ const now = weight > 0 ? `Now ${inflight} (${weight}w)` : `Now ${inflight}`;
101
122
  const recent = `${m15.requests || 0}r`;
102
123
  const recentAvg = m15.avgMs != null ? ` ${formatMs(m15.avgMs)}` : '';
103
124
  const hour = `${h1.requests || 0}r`;
104
125
  const fails = (m15.failed || 0) > 0 ? ` ${red(`${m15.failed}f`)}` : '';
105
- return `Load ${current} 15m ${recent}${recentAvg}${fails} 1h ${hour}`;
126
+ return `${now} 15m ${recent}${recentAvg}${fails} 1h ${hour}`;
106
127
  }
107
128
 
108
129
  function weeklyPolicyText(am, account) {
@@ -161,7 +182,7 @@ function bar(ratio, w = 10, resetTs) {
161
182
  return out;
162
183
  }
163
184
 
164
- export const __tuiTest = { formatReset, quotaLabel, bar, strip };
185
+ export const __tuiTest = { formatReset, quotaLabel, bar, strip, loadText, countdown };
165
186
 
166
187
  function timestamp() {
167
188
  return new Date().toLocaleTimeString('en-US', { hour12: false });
@@ -906,12 +927,19 @@ export class TUI {
906
927
  case 'waiting': status = yellow('waiting'); break;
907
928
  case 'paused': status = yellow('paused'); break;
908
929
  case 'disabled': status = gray('disabled'); break;
909
- case 'throttled': status = yellow('throttled'); break;
930
+ case 'throttled': {
931
+ // A transient auto-recovering cooldown — show the remaining time (from
932
+ // rateLimitedUntil) so it reads as "recovering in Ns", not stuck.
933
+ const cd = countdown(a.rateLimitedUntil);
934
+ status = yellow(cd ? `throttled ${cd}` : 'throttled');
935
+ break;
936
+ }
910
937
  case 'exhausted': status = red('exhausted'); break;
911
938
  case 'error': status = red('error'); break;
912
939
  default: status = a.status || 'ready';
913
940
  }
914
- status = rpad(status, 10);
941
+ // Widened from 10 to fit "throttled 59s" so the quota bars stay column-aligned.
942
+ status = rpad(status, 13);
915
943
 
916
944
  if (a.type === 'provider') {
917
945
  return this._renderProviderAcct(sel, cur, name, type, status, a);