maxpool 1.5.16 → 1.5.17

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.16",
3
+ "version": "1.5.17",
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",
@@ -42,6 +42,19 @@ function emptyQuota() {
42
42
  scopedWeekly: {},
43
43
  unifiedStatus: null, // allowed | allowed_warning | rejected
44
44
  resetsAt: null,
45
+ // Provider (z.ai / Kimi) quota — kept SEPARATE from unified* so a provider
46
+ // reading never leaks into the OAuth quota gates (_isAvailable / _weeklyRawState
47
+ // / _accountScarcity read unified* only). z.ai is pollable; Kimi is not.
48
+ providerSes: null, // utilization 0-1 (z.ai 5h token window)
49
+ providerSesReset: null, // ms
50
+ providerWk: null, // utilization 0-1 (z.ai weekly), null if plan has none
51
+ providerWkReset: null, // ms
52
+ providerQuotaSource: null, // 'zai' (pollable) | 'console-only' (kimi) | null
53
+ // Freshness: last time a background usage PROBE succeeded for this account
54
+ // (oauth fetchUsage OR provider fetchProviderUsage). Drives the TUI staleness
55
+ // marker — a swallowed failing probe no longer silently freezes a stale tag.
56
+ // Header-driven updates do NOT stamp this (headers can't refresh scoped/provider).
57
+ lastProbeOkAt: null, // ms
45
58
  };
46
59
  }
47
60
 
@@ -589,8 +602,14 @@ export class AccountManager {
589
602
  if (!fam) return null;
590
603
  const e = account.quota?.scopedWeekly?.[fam];
591
604
  if (!e || e.isActive === false) return null;
592
- const exhausted = e.severity === 'critical'
593
- || (e.utilization != null && e.utilization >= this.scheduler.weeklyExhaustedThreshold);
605
+ // Bench ONLY at genuine exhaustion (>= weeklyExhaustedThreshold). Anthropic
606
+ // labels a scoped weekly `severity:'critical'` well before it's actually
607
+ // capped (~90%), where the model still has headroom and is still served — a
608
+ // hard bench there strands the remainder and mislabels the account "maxed".
609
+ // A real scoped 429 writes utilization:1 (markRateLimited), so genuine
610
+ // exhaustion is still caught by the threshold. Same predicate drives the TUI
611
+ // `maxed` tag, so "maxed" renders iff the model is actually benched.
612
+ const exhausted = e.utilization != null && e.utilization >= this.scheduler.weeklyExhaustedThreshold;
594
613
  return exhausted ? { resetAt: e.resetAt || null, family: fam } : null;
595
614
  }
596
615
 
@@ -1648,6 +1667,16 @@ export class AccountManager {
1648
1667
  // soft de-preference of accounts burning ahead of an even pace. Never a bench.
1649
1668
  const paceCost = this._accountScarcity(account, now) * this.scheduler.paceCostWeight;
1650
1669
 
1670
+ // Per-model weekly de-preference: an account whose scoped weekly for THIS
1671
+ // request's model (e.g. Fable) is high-but-not-exhausted is a poor pick for
1672
+ // that model — shed its load toward healthier accounts BEFORE the hard bench
1673
+ // at weeklyExhaustedThreshold, so it's chosen only as overflow (rarely
1674
+ // re-429ing). Scoped weekly is otherwise absent from scoring. Soft, never a
1675
+ // bench; 0 below reserve and for models with no scoped cap.
1676
+ const scopedPace = requestInfo.model
1677
+ ? this._scopedScarcity(account, requestInfo.model, now) * this.scheduler.paceCostWeight
1678
+ : 0;
1679
+
1651
1680
  const fleetRecentWeight = ctx?.fleetRecentWeight ?? 0;
1652
1681
  const recentWeight = this._loadSummary(account, this.scheduler.spreadWindowMs, now).weight;
1653
1682
  const share = fleetRecentWeight > 0 ? recentWeight / fleetRecentWeight : 0;
@@ -1663,7 +1692,22 @@ export class AccountManager {
1663
1692
  // default) learns the real number within a cycle. `probing`/requalify still
1664
1693
  // flags a never-seen account for learning — that path is unchanged.
1665
1694
 
1666
- return concurrency + capPenalty + paceCost + spread + ramp + failurePenalty;
1695
+ return concurrency + capPenalty + paceCost + scopedPace + spread + ramp + failurePenalty;
1696
+ }
1697
+
1698
+ /**
1699
+ * Per-model weekly pace-overage for `model`'s family, or 0 when the account has
1700
+ * no scoped cap for it, the cap is inactive, or it's below the reserve tier
1701
+ * (plenty of headroom → no steering). Same pace discount as _windowScarcity, so
1702
+ * a scoped window about to reset is cheap to spend.
1703
+ */
1704
+ _scopedScarcity(account, model, now = Date.now()) {
1705
+ const fam = modelFamily(model);
1706
+ if (!fam) return 0;
1707
+ const e = account.quota?.scopedWeekly?.[fam];
1708
+ if (!e || e.isActive === false || e.utilization == null) return 0;
1709
+ if (e.utilization < this.scheduler.weeklyReserveThreshold) return 0;
1710
+ return this._windowScarcity(e.utilization, e.resetAt, WEEK_MS, now);
1667
1711
  }
1668
1712
 
1669
1713
  /**
@@ -1795,8 +1839,15 @@ export class AccountManager {
1795
1839
  }
1796
1840
  // Per-model weekly sub-limits (Fable, Opus, ...). Replace wholesale with the
1797
1841
  // fresh probe set so a family that dropped out of the response doesn't linger
1798
- // stale; expiry on reset is a backstop for the between-probe window.
1842
+ // stale; expiry on reset is a backstop for the between-probe window. EXCEPTION:
1843
+ // a `reactive` scoped-429 bench is authoritative-high — while its resetAt is
1844
+ // still future, a lagging probe may neither lower it nor drop it (a probe that
1845
+ // omits the family, or reports the pre-429 level, would otherwise un-bench it
1846
+ // and trigger an immediate re-429 flap). _clearExpiredQuotas self-clears it at
1847
+ // resetAt even if probes die.
1799
1848
  if (usage.scopedWeekly && typeof usage.scopedWeekly === 'object') {
1849
+ const now = Date.now();
1850
+ const prev = (q.scopedWeekly && typeof q.scopedWeekly === 'object') ? q.scopedWeekly : {};
1800
1851
  const fresh = {};
1801
1852
  for (const [fam, e] of Object.entries(usage.scopedWeekly)) {
1802
1853
  if (!e) continue;
@@ -1807,9 +1858,21 @@ export class AccountManager {
1807
1858
  isActive: e.isActive !== false,
1808
1859
  };
1809
1860
  }
1861
+ for (const [fam, pe] of Object.entries(prev)) {
1862
+ if (!pe || !pe.reactive || pe.resetAt == null || pe.resetAt <= now) continue;
1863
+ const f = fresh[fam];
1864
+ // Probe absent, null, or LOWER than the reactive bench → keep the bench.
1865
+ // Probe CONFIRMS >= the reactive level → take the fresh reading (still >=
1866
+ // threshold, so still exhausted; no stickiness needed).
1867
+ if (!f || f.utilization == null || f.utilization < (pe.utilization ?? 0)) {
1868
+ fresh[fam] = { ...pe };
1869
+ }
1870
+ }
1810
1871
  q.scopedWeekly = fresh;
1811
1872
  }
1812
1873
 
1874
+ q.lastProbeOkAt = Date.now();
1875
+
1813
1876
  // If we just learned this account's weekly window while probing, re-evaluate
1814
1877
  // selection (same path as learning it from a live response).
1815
1878
  if (account.probing && q.unified7dReset != null) {
@@ -1818,6 +1881,55 @@ export class AccountManager {
1818
1881
  }
1819
1882
  }
1820
1883
 
1884
+ /**
1885
+ * Update a PROVIDER account's quota from a provider usage probe
1886
+ * (fetchProviderUsage). z.ai maps to Ses/Wk token windows; Kimi has no pollable
1887
+ * source and only sets a `console-only` marker. Writes ONLY the provider* fields
1888
+ * (never the unified or scopedWeekly fields) so a provider reading can't reach
1889
+ * the OAuth quota gates.
1890
+ */
1891
+ applyProviderUsage(accountIndex, usage) {
1892
+ const account = this.accounts[accountIndex];
1893
+ if (!account || !usage) return;
1894
+ const q = account.quota;
1895
+ if (usage.error) {
1896
+ // Distinguish "no pollable quota" (Kimi) from a transient probe failure.
1897
+ // Never clear existing values on a transient error — let them age into the
1898
+ // staleness marker instead of blanking the bars.
1899
+ if (usage.source === 'console-only') q.providerQuotaSource = 'console-only';
1900
+ return;
1901
+ }
1902
+ q.providerQuotaSource = usage.source || 'zai';
1903
+ if (usage.ses) {
1904
+ if (usage.ses.utilization != null) q.providerSes = clamp01(usage.ses.utilization);
1905
+ if (usage.ses.resetAt != null) q.providerSesReset = usage.ses.resetAt;
1906
+ }
1907
+ if (usage.wk) {
1908
+ if (usage.wk.utilization != null) q.providerWk = clamp01(usage.wk.utilization);
1909
+ if (usage.wk.resetAt != null) q.providerWkReset = usage.wk.resetAt;
1910
+ } else {
1911
+ // Weekly window absent from this plan/response — clear so a stale weekly
1912
+ // reading doesn't linger after a plan/window change.
1913
+ q.providerWk = null;
1914
+ q.providerWkReset = null;
1915
+ }
1916
+ q.lastProbeOkAt = Date.now();
1917
+ }
1918
+
1919
+ /**
1920
+ * True when the background quota probe hasn't succeeded in > 2× its interval —
1921
+ * the last-known scoped/provider values are aging with no confirmation. Returns
1922
+ * false when the probe is off (nothing to be stale against) or has never yet
1923
+ * succeeded (startup — shown as "no data", not "stale").
1924
+ */
1925
+ _quotaProbeStale(account, now = Date.now()) {
1926
+ const interval = this.quotaProbeIntervalMs;
1927
+ if (!interval || interval <= 0) return false;
1928
+ const last = account?.quota?.lastProbeOkAt;
1929
+ if (last == null) return false;
1930
+ return (now - last) > Math.max(2 * interval, 120_000);
1931
+ }
1932
+
1821
1933
  /**
1822
1934
  * Update an account's quota tracking from upstream response headers.
1823
1935
  */
@@ -1956,6 +2068,10 @@ export class AccountManager {
1956
2068
  resetAt: Date.now() + (retryAfter * 1000),
1957
2069
  severity: 'critical',
1958
2070
  isActive: true,
2071
+ // Authoritative-high: a real reject. A lagging 60s probe reporting the
2072
+ // pre-429 level (e.g. 0.96) must NOT lower/drop this before resetAt, else
2073
+ // the account un-benches and immediately re-429s — a per-probe flap.
2074
+ reactive: true,
1959
2075
  };
1960
2076
  account.lastStatus = options.status || 429;
1961
2077
  account.lastErrorAt = Date.now();
package/src/index.js CHANGED
@@ -564,6 +564,9 @@ async function serverWorkerCommand() {
564
564
  // assertions (mirrors MAXPOOL_DISABLE_SLEEP_GUARD).
565
565
  const probeSeconds = process.env.MAXPOOL_DISABLE_QUOTA_PROBE === '1' ? 0 : (config.quotaProbeSeconds || 0);
566
566
  const prober = new Prober(accountManager, { intervalMs: probeSeconds * 1000 });
567
+ // Tell the AM the probe cadence so the TUI can flag a scoped/provider tag whose
568
+ // background probe has gone stale (> 2× interval since last success).
569
+ accountManager.quotaProbeIntervalMs = probeSeconds * 1000;
567
570
 
568
571
  // Persist refreshed tokens back to config. Defense-in-depth: the updater reads
569
572
  // the on-disk refresh token and SKIPS the rotation if a fresher writer already
package/src/oauth.js CHANGED
@@ -245,6 +245,61 @@ export async function fetchUsage(accessToken) {
245
245
  }
246
246
  }
247
247
 
248
+ // z.ai quota monitor — a DIFFERENT host/path than the message upstream
249
+ // (account.upstream is the Anthropic-compat endpoint). Zero-spend read.
250
+ const ZAI_QUOTA_URL = 'https://api.z.ai/api/monitor/usage/quota/limit';
251
+
252
+ /** Classify one z.ai `limits[]` entry into a Ses (5h) or Wk (weekly) TOKEN window.
253
+ * Only `TOKENS_LIMIT` maps to the quota bars; `TIME_LIMIT` is a tool-call cap
254
+ * (web-search/reader counts) and is intentionally ignored. `unit` is z.ai's
255
+ * window enum (3 = 5-hour session, 6 = weekly); we fall back to reset-distance
256
+ * when the code is unfamiliar so a new plan tier still classifies sanely. */
257
+ export function classifyZaiLimit(l, now = Date.now()) {
258
+ if (!l || l.type !== 'TOKENS_LIMIT') return null;
259
+ const reset = Number(l.nextResetTime);
260
+ const resetAt = Number.isFinite(reset) && reset > 0 ? reset : null;
261
+ const pct = typeof l.percentage === 'number' ? l.percentage : parseFloat(l.percentage);
262
+ const utilization = Number.isFinite(pct) ? Math.max(0, Math.min(1, pct / 100)) : null;
263
+ let bucket;
264
+ if (l.unit === 3) bucket = 'ses';
265
+ else if (l.unit === 6) bucket = 'wk';
266
+ else if (resetAt) bucket = (resetAt - now) <= 12 * 60 * 60 * 1000 ? 'ses' : 'wk';
267
+ else bucket = 'ses';
268
+ return { bucket, utilization, resetAt };
269
+ }
270
+
271
+ /** Read a provider account's quota. z.ai has a pollable monitor endpoint mapped
272
+ * to Ses/Wk token windows; Kimi (Moonshot coding key) has NO pollable quota
273
+ * (web console only), so it returns a `console-only` marker instead of fake
274
+ * bars. Returns { ses, wk, level } | { error, status?, source? }. */
275
+ export async function fetchProviderUsage(account) {
276
+ const provider = account?.provider;
277
+ const token = account?.credential;
278
+ if (provider === 'kimi') return { error: 'unsupported', source: 'console-only' };
279
+ if (provider !== 'zai' || !token) return { error: 'unsupported', source: null };
280
+ try {
281
+ const res = await fetch(ZAI_QUOTA_URL, {
282
+ headers: { 'Authorization': `Bearer ${token}`, 'Accept': 'application/json' },
283
+ });
284
+ if (!res.ok) return { error: `HTTP ${res.status}`, status: res.status };
285
+ const data = await res.json();
286
+ if (data?.code !== 200 || !data?.data) {
287
+ return { error: `bad_envelope${data?.code != null ? ' code=' + data.code : ''}` };
288
+ }
289
+ const now = Date.now();
290
+ let ses = null, wk = null;
291
+ for (const l of (Array.isArray(data.data.limits) ? data.data.limits : [])) {
292
+ const c = classifyZaiLimit(l, now);
293
+ if (!c) continue;
294
+ if (c.bucket === 'ses') ses = { utilization: c.utilization, resetAt: c.resetAt };
295
+ else if (c.bucket === 'wk') wk = { utilization: c.utilization, resetAt: c.resetAt };
296
+ }
297
+ return { ses, wk, level: data.data.level || null, source: 'zai' };
298
+ } catch (err) {
299
+ return { error: err.message || String(err), status: null };
300
+ }
301
+ }
302
+
248
303
  // OAuth config (extracted from Claude Code)
249
304
  const OAUTH_CLIENT_ID = '9d1c250a-e61b-44d9-88ed-5944d1962f5e';
250
305
  const OAUTH_AUTHORIZE = 'https://claude.ai/oauth/authorize';
package/src/prober.js CHANGED
@@ -7,13 +7,14 @@
7
7
  // is blind to an account it isn't actively routing to and will pile traffic onto it.
8
8
  // This is the one sanctioned active-upstream feature; the proxy is otherwise passive.
9
9
 
10
- import { fetchUsage } from './oauth.js';
10
+ import { fetchUsage, fetchProviderUsage } from './oauth.js';
11
11
 
12
12
  export class Prober {
13
- constructor(accountManager, { intervalMs = 0, probeFn = fetchUsage, timeoutMs = 10_000, log = console.log } = {}) {
13
+ constructor(accountManager, { intervalMs = 0, probeFn = fetchUsage, providerProbeFn = fetchProviderUsage, timeoutMs = 10_000, log = console.log } = {}) {
14
14
  this.am = accountManager;
15
15
  this.intervalMs = intervalMs;
16
16
  this.probeFn = probeFn;
17
+ this.providerProbeFn = providerProbeFn;
17
18
  this.timeoutMs = timeoutMs;
18
19
  this.log = log;
19
20
  this.timer = null;
@@ -49,15 +50,21 @@ export class Prober {
49
50
  if (this._inflight) { try { await this._inflight; } catch { /* swallow */ } }
50
51
  }
51
52
 
52
- /** Probe every OAuth account once. Overlapping cycles are skipped. The active
53
- * cycle is tracked on `_inflight` so stop() can await it. */
53
+ /** Probe every OAuth account (usage endpoint) and every provider account with a
54
+ * pollable/known quota source (z.ai monitor; Kimi → console-only marker) once.
55
+ * Overlapping cycles are skipped. The active cycle is tracked on `_inflight` so
56
+ * stop() can await it. */
54
57
  probeAll() {
55
58
  if (this._running) return this._inflight || Promise.resolve();
56
59
  this._running = true;
57
60
  this._inflight = (async () => {
58
61
  try {
59
- const accounts = this.am.accounts.filter(a => a.type === 'oauth' && a.credential);
60
- await Promise.all(accounts.map(a => this.probeOne(a)));
62
+ const oauth = this.am.accounts.filter(a => a.type === 'oauth' && a.credential);
63
+ const providers = this.am.accounts.filter(a => a.type === 'provider' && a.credential);
64
+ await Promise.all([
65
+ ...oauth.map(a => this.probeOne(a)),
66
+ ...providers.map(a => this.probeProvider(a)),
67
+ ]);
61
68
  } finally {
62
69
  this._running = false;
63
70
  this._inflight = null;
@@ -66,6 +73,16 @@ export class Prober {
66
73
  return this._inflight;
67
74
  }
68
75
 
76
+ /** Probe one PROVIDER account. Provider tokens are static API keys (no OAuth
77
+ * refresh). Best-effort; never throws. */
78
+ async probeProvider(account) {
79
+ try {
80
+ const usage = await this._withTimeout(this.providerProbeFn(account));
81
+ if (!usage) return; // timed out — try again next cycle
82
+ this.am.applyProviderUsage(account.index, usage);
83
+ } catch { /* best-effort; never let a probe throw */ }
84
+ }
85
+
69
86
  async probeOne(account) {
70
87
  try {
71
88
  await this.am.ensureTokenFresh(account.index);
package/src/tui.js CHANGED
@@ -984,7 +984,7 @@ export class TUI {
984
984
  status = rpad(status, 13);
985
985
 
986
986
  if (a.type === 'provider') {
987
- return this._renderProviderAcct(sel, cur, name, type, status, a);
987
+ return this._renderProviderAcct(sel, cur, name, type, status, a, bw, showBoth);
988
988
  }
989
989
 
990
990
  // Quota ratios — prefer unified (Claude Max), fall back to standard (API key)
@@ -1013,25 +1013,53 @@ export class TUI {
1013
1013
  }
1014
1014
  const weekly = weeklyPolicyText(this.am, a);
1015
1015
  if (weekly) line += ` ${weekly}`;
1016
- // Per-model weekly caps (e.g. Fable maxed while the unified weekly still has
1017
- // headroom) — surfaced separately so a capped model on an otherwise-healthy
1018
- // account is visible, and routing away from it is explained.
1016
+ // Per-model weekly caps (e.g. Fable, while the unified weekly still has
1017
+ // headroom). Show the ACTUAL utilization — "Fable 90%" (yellow) while high but
1018
+ // still usable, "Fable maxed" (red) ONLY at genuine exhaustion. This is the
1019
+ // SAME predicate the router benches on (_scopedExhausted), so "maxed" renders
1020
+ // iff the model is actually benched — 90%/critical is no longer mislabelled.
1019
1021
  const exhaustedFloor = this.am.scheduler?.weeklyExhaustedThreshold ?? 0.985;
1020
- const capped = Object.entries(q.scopedWeekly || {})
1021
- .filter(([, e]) => e && e.isActive !== false
1022
- && (e.severity === 'critical' || (e.utilization != null && e.utilization >= exhaustedFloor)))
1023
- .map(([fam]) => fam.charAt(0).toUpperCase() + fam.slice(1));
1024
- if (capped.length) line += ` ${red(`${capped.join(',')} maxed`)}`;
1022
+ const reserveFloor = this.am.scheduler?.weeklyReserveThreshold ?? 0.85;
1023
+ const scopedTags = [];
1024
+ for (const [fam, e] of Object.entries(q.scopedWeekly || {})) {
1025
+ if (!e || e.isActive === false || e.utilization == null) continue;
1026
+ if (e.utilization < reserveFloor) continue;
1027
+ const Fam = fam.charAt(0).toUpperCase() + fam.slice(1);
1028
+ scopedTags.push(e.utilization >= exhaustedFloor
1029
+ ? red(`${Fam} maxed`)
1030
+ : yellow(`${Fam} ${Math.round(e.utilization * 100)}%`));
1031
+ }
1032
+ if (scopedTags.length) line += ` ${scopedTags.join(' ')}`;
1033
+ // Freshness: scoped caps are refreshed ONLY by the background probe (response
1034
+ // headers don't carry them). If the probe has gone stale (> 2× interval since
1035
+ // last success), say so rather than imply the last-known value is current.
1036
+ if (this.am._quotaProbeStale?.(a)) line += ` ${dim('stale')}`;
1025
1037
  line += ` ${dim(loadText(this._accountLoad(a)))}`;
1026
1038
  return line;
1027
1039
  }
1028
1040
 
1029
- _renderProviderAcct(sel, cur, name, type, status, a) {
1041
+ _renderProviderAcct(sel, cur, name, type, status, a, bw = 11, showBoth = true) {
1030
1042
  const completed = a.completedRequests || 0;
1031
1043
  const failed = a.failedRequests || 0;
1032
1044
  const active = a.inFlight || 0;
1033
1045
  const last = a.lastStatus ? `${statusColor(a.lastStatus)} ${formatMs(a.lastResponseMs)}` : '-';
1034
1046
  const q = a.quota || {};
1047
+
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 = '';
1053
+ 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')}`;
1057
+ } else if (q.providerQuotaSource === 'console-only') {
1058
+ quotaSeg = ` ${dim('Quota console-only')}`;
1059
+ } else if (q.providerQuotaSource === 'zai') {
1060
+ quotaSeg = ` ${dim('Ses/Wk probing')}`;
1061
+ }
1062
+
1035
1063
  let limit = '';
1036
1064
  if (q.genericLimit != null && q.genericRemaining != null) {
1037
1065
  const used = q.genericLimit - q.genericRemaining;
@@ -1039,7 +1067,7 @@ export class TUI {
1039
1067
  limit = ` Lim ${used}/${q.genericLimit}${reset ? ` ${reset}` : ''}`;
1040
1068
  }
1041
1069
  const err = a.lastError ? ` Err ${String(a.lastError).slice(0, 18)}` : '';
1042
- return ` ${sel}${cur} ${name} ${type} ${status} Act ${String(active).padStart(2)} OK ${String(completed).padStart(3)} Fail ${String(failed).padStart(2)} Last ${last} ${dim(loadText(this._accountLoad(a)))}${limit}${err}`;
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}`;
1043
1071
  }
1044
1072
 
1045
1073
  _accountLoad(account) {